Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

SSH Keygen on Windows: ssh-keygen, PuTTYgen, and WSL

Sean

Platform Writer

Jul 05, 2026
6 min read

Generating an SSH key on Windows is ssh-keygen -t ed25519 from PowerShell, CMD, or WSL. That single command creates ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519.pub, and the .pub file is what gets added to the server’s ~/.ssh/authorized_keys. The team that needs a .ppk for older PuTTY clients converts with PuTTYgen - the conversion is a one-way bridge from OpenSSH format to PuTTY’s format.

SSH Keygen on Windows: ssh-keygen, PuTTYgen, and WSL

Table of contents

The PowerShell ssh-keygen command

Open PowerShell as your normal user (no admin needed) and run:

ssh-keygen -t ed25519 -C "[email protected]"

The -t ed25519 flag picks the ed25519 algorithm - smaller, faster, and the modern default. The -C flag sets a comment that shows up in authorized_keys so the team can identify which key belongs to which machine later.

Press Enter to accept the default path (C:\Users\you\.ssh\id_ed25519). The passphrase prompt is optional but recommended - a stolen key without a passphrase is the same as a stolen password. The team that uses a passphrase on their dev key and a separate no-passphrase key for CI has the right setup. The team that reuses one key for both has a single point of failure.

ssh-keygen ships with Windows 10 1809+ and with all current Windows Server SKUs. The team that runs ssh-keygen and gets not recognized needs to install the OpenSSH client feature - Settings -> Apps -> Optional Features -> OpenSSH Client, or Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 from an elevated PowerShell.

The CMD version

The same command works from CMD:

ssh-keygen -t ed25519 -C "[email protected]"

CMD does not have $HOME - the key gets written to %USERPROFILE%\.ssh\id_ed25519, which is C:\Users\you\.ssh\id_ed25519. The team that checks dir %USERPROFILE%\.ssh after the command sees both files. The team that does not check never knows the key was created.

Both PowerShell and CMD use the same ssh-keygen.exe from C:\Windows\System32\OpenSSH\. The team that has multiple OpenSSH installs (Git for Windows, WSL, native) sometimes gets the wrong one - where ssh-keygen shows which binary is on PATH first.

The PuTTYgen option for .ppk output

The team that still uses PuTTY to connect to older Windows servers needs a .ppk (PuTTY Private Key) file. PuTTYgen is the tool:

  1. Open PuTTYgen (usually in C:\Program Files\PuTTY\).
  2. Parameters: ed25519, 256 bits.
  3. Click Generate, move the mouse in the blank area to seed randomness.
  4. Set a passphrase.
  5. Save private key as id_ed25519.ppk.
  6. The “Public key for pasting” box at the top is the .pub content - paste it into the server’s authorized_keys.

The conversion path from a native OpenSSH key to a .ppk: open PuTTYgen, Conversions -> Import key, pick id_ed25519, then save as .ppk. The team that goes the other direction (.ppk to OpenSSH) uses PuTTYgen’s Export OpenSSH key menu item.

In 2026 the team that still uses PuTTY is shrinking - Windows Terminal + native OpenSSH covers most workflows. The team that needs PuTTY is the team that connects to a network device (switch, firewall, router) where SSH is a CLI-only protocol.

The WSL option

WSL has its own Linux filesystem and its own ~/.ssh/:

wsl ssh-keygen -t ed25519 -C "[email protected]"

Or open a WSL terminal and run the command normally.

The trap: Windows and WSL do not share ~/.ssh by default. The team that creates a key in PowerShell and tries to use it from WSL needs to copy id_ed25519 to WSL’s home directory. The team that does this with cp /mnt/c/Users/you/.ssh/id_ed25519 ~/.ssh/ should also chmod 600 on the copied file - the Windows file has Windows permissions that WSL does not understand as private.

The team that uses \\wsl$\Ubuntu\home\you\.ssh\id_ed25519 from Windows-side SSH config keeps the key in WSL but reads it from Windows - that path syntax works in .ssh\config on the Windows side.

Copy the public key to the server

The key generation is half the job. The other half is installing the .pub on the server:

type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"

That pipe uses ssh itself (which is in the same OpenSSH install as ssh-keygen) to copy the public key into the server’s authorized_keys. The team that sees Permission denied (publickey) after this command usually has one of three problems: the key was added to the wrong user, the perms on the server are too open (chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys), or the server’s sshd_config does not have PubkeyAuthentication yes.

The team that uses GitHub or GitLab uses the same .pub file - the SSH and GPG keys page on GitHub accepts the entire cat ~/.ssh/id_ed25519.pub output verbatim.

FAQ

Where does ssh-keygen save the key on Windows?

Default is C:\Users\<you>\.ssh\id_ed25519 (and id_ed25519.pub next to it). The team that wants a different path passes it as the second argument: ssh-keygen -t ed25519 -f C:\keys\github_ed25519.

What algorithm should I use in 2026?

ed25519. It is shorter, faster to sign, and the modern default. RSA 4096 still works but is the legacy option. The team that has an existing RSA key from a 2018 server can keep using it - ed25519 is for new keys.

Do I need a passphrase?

Yes for personal keys. No for keys that go into CI/CD (the team protects those with secret-scanning, not passphrases). A passphrase-protected key is decrypted to a memory-only key when first used per session.

Can I use the same key on multiple machines?

Yes. Copy id_ed25519 (the private key) to each machine’s ~/.ssh/. The team that does this should set chmod 600 on each copy. The team that copies via email or unencrypted cloud storage has leaked the key - regenerate and remove the old one from all servers.

What is the difference between .ssh\config and authorized_keys?

~/.ssh/config is on the client (this Windows machine) - it tells the client which key to use for which host. ~/.ssh/authorized_keys is on the server - it lists which public keys are allowed to log in. The team that confuses them is debugging in the wrong file.

If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.

Useful related references:

#ssh#windows#ssh-keygen#dev-infra