SSH keys: you make two files. One stays on your machine and never fucking leaves (private key). The other goes to GitHub (public key). When you push code, they do cryptographic math together and GitHub says "yep, this is actually you."
Before you start, check this shit or you'll waste an hour
Windows users: PowerShell SSH is broken garbage. Download Git for Windows, use Git Bash, pretend PowerShell doesn't exist. I wasted 3 hours in 2024 trying to make PowerShell SSH work with Unicode passphrases - just fucking don't. If you're using WSL2, stick to the Linux SSH client but Windows Terminal vs Git Bash use different home directories - pick one and stick with it.
macOS users: Your SSH tools are built-in, but check if you're running ancient software:
ssh -V
If you see OpenSSH older than 6.5, you're living in 2013. ED25519 won't work and you'll get "unknown key type" errors that make no fucking sense. Current OpenSSH releases (9.6+ as of 2025) support ed25519 natively. Check the OpenSSH release history - ed25519 support was added in OpenSSH 6.5 (January 2014), and DSA support is finally being completely removed in 2025.
Linux users: If ssh-keygen
says command not found, install OpenSSH: sudo apt install openssh-client
(Ubuntu/Debian) or sudo yum install openssh-clients
(RHEL/CentOS). Different distros package it differently - check pkgs.org for yours. Ubuntu 18.04 ships with OpenSSH 7.6 which supports ed25519 but I've had it randomly fail with Cisco AnyConnect VPN - took me 4 hours to figure out the corporate VPN was mangling SSH packets.
Key Types That Don't Suck
Use ed25519 keys. Period. GitHub deprecated DSA keys in March 2022 because they're cryptographically broken. RSA-2048 still works but it's like using Internet Explorer - technically functional but why would you?
- ed25519: Generates in 0.2 seconds, small keys, fast crypto - RFC 8709 standard
- RSA 4096-bit: Takes 30 seconds to generate, massive keys, but works on ancient systems - NIST approved
- RSA 2048-bit: What everyone used to use, still works but deprecated by 2030 - quantum vulnerable
- DSA: Dead since March 2022. GitHub returns "DSA keys are no longer supported" - SHA-1 collision attacks
Things That Will Bite You
Before you start generating keys and wonder why nothing works:
- Use the right email: Match the email on your GitHub account or you'll spend an hour debugging why authentication fails. Check GitHub's SSH troubleshooting guide for common email issues.
- Don't skip the passphrase: I don't care how tedious it seems, use one. The OWASP guide explains why passphrases matter.
- Windows file permissions: Git Bash handles this, but if you're messing with WSL, chmod 600 your private key or SSH will refuse to use it. See Windows SSH permissions for WSL specifics. Windows Terminal vs Git Bash handle paths differently - stick with Git Bash.
- Corporate networks: Some companies block port 22. You'll need to use HTTPS instead or configure SSH over HTTPS on port 443. Your corporate laptop probably has some security software that fucks with SSH. Check your company's firewall policies.
- Multiple GitHub accounts: Each account needs its own SSH key. You cannot share them. Follow GitHub's multiple accounts guide carefully.
The whole process takes 10 minutes unless something breaks, then it's 2 hours of Stack Overflow and questioning your career choices.
Ready to Generate Keys? Platform Reality Check
You've confirmed your system has the right tools, you understand the key types, and you've mentally prepared for the platform-specific gotchas. Time for the actual SSH key generation and setup.
The commands are basically the same across platforms, but each operating system has its own special way of making simple things complicated. Windows has clipboard quirks and SSH agent that dies every reboot, macOS has Keychain integration that randomly breaks after OS updates, and Linux has the delightful variety of desktop environments that each handle SSH agent differently.
You understand what SSH keys are, you've checked your platform compatibility, and you know what's going to break. Time for the actual commands that will either work perfectly or send you down a 2-hour debugging rabbit hole where you question every life choice that led you to this moment.