DevToolBoxFREE
Blog

SSH Keygen: Ed25519 vs RSA Guide

9 min readby DevToolBox

SSH keys are the gold standard for secure server authentication, replacing passwords with cryptographic key pairs. Whether you are setting up a new development machine, configuring CI/CD pipelines, or hardening production servers, understanding how to generate and manage SSH keys is a fundamental skill. This comprehensive guide covers everything from key algorithm selection (Ed25519 vs RSA vs ECDSA) to advanced SSH configuration, agent management, and troubleshooting common issues.

What Are SSH Keys?

SSH (Secure Shell) keys are cryptographic key pairs used for authentication. Instead of typing a password every time you connect to a remote server, SSH keys let you prove your identity using public-key cryptography. This is both more secure and more convenient than password-based authentication.

An SSH key pair consists of two files:

  • Private key: Private key: Stays on your local machine. Never share this file with anyone. It is analogous to a physical key that unlocks a door.
  • Public key: Public key: Placed on every server you want to access. It is analogous to a lock — anyone can see it, but only the matching private key can open it.

How SSH Key Authentication Works

1. You attempt to connect to a server: ssh user@server.example.com
2. The server sends a random challenge encrypted with your public key.
3. Your SSH client uses your private key to decrypt the challenge and sends the response.
4. The server verifies the response. If correct, you are authenticated without ever sending a password.
# SSH Key Authentication Flow
Client                          Server
  │                               │
  │── 1. Connection request ─────>│
  │                               │
  │<── 2. Random challenge ───────│  (encrypted with your public key)
  │                               │
  │── 3. Decrypted response ─────>│  (signed with your private key)
  │                               │
  │<── 4. Access granted ─────────│  (response verified)
  │                               │

This means even if an attacker intercepts the network traffic, they cannot authenticate as you without possessing your private key. Passwords, on the other hand, can be captured by keyloggers, phishing, or brute-force attacks.

Ed25519 vs RSA vs ECDSA: Algorithm Comparison

There are several algorithms available for SSH key generation. The three most common are RSA, ECDSA, and Ed25519. Each has different security properties, performance characteristics, and compatibility considerations.

FeatureEd25519RSAECDSA
Introduced2014 (OpenSSH 6.5)1995 (SSH-1)2011 (OpenSSH 5.7)
Security Level~128-bit (equivalent to RSA-3072)112-bit (2048) / 128-bit (3072) / 192-bit (4096)128-bit (P-256) / 192-bit (P-384)
Private Key Size64 bytes (fixed)~3,200 bytes (4096-bit)~256 bytes (P-256)
Public Key Size32 bytes (fixed)~512 bytes (4096-bit)~64 bytes (P-256)
Sign SpeedVery fastSlowFast
Verify SpeedVery fastFastModerate
CompatibilityOpenSSH 6.5+ (2014), most modern systemsUniversal (all SSH implementations)OpenSSH 5.7+, but NIST curve concerns
RecommendationBest choice for new keysUse 4096-bit if Ed25519 not supportedGenerally avoid — prefer Ed25519

Ed25519 is the recommended algorithm for new SSH keys. It provides excellent security with small key sizes, fast operations, and resistance to several classes of implementation attacks. RSA-4096 remains a solid fallback for systems that do not support Ed25519. ECDSA is generally not recommended due to concerns about the NIST P-256 curve and sensitivity to poor random number generation.

Generate an Ed25519 SSH Key

Ed25519 keys are the modern standard. They are fast, secure, and produce compact key files. Here is how to generate one step by step:

Step 1: Open your terminal (Linux/macOS) or Git Bash / PowerShell (Windows).

Step 2: Run the ssh-keygen command with the Ed25519 algorithm:

ssh-keygen -t ed25519 -C "your_email@example.com"

Step 3: When prompted for a file location, press Enter to accept the default (~/.ssh/id_ed25519), or specify a custom path:

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# Press Enter for default, or type a custom path like:
# /home/user/.ssh/id_ed25519_github

Step 4: Enter a strong passphrase when prompted (recommended), or press Enter for no passphrase:

Enter passphrase (empty for no passphrase):
Enter same passphrase again:
# Use a strong passphrase like: correct-horse-battery-staple

Step 5: Verify the key was created:

ls -la ~/.ssh/id_ed25519*

# Expected output:
-rw-------  1 user user  464 Jan 15 10:30 /home/user/.ssh/id_ed25519
-rw-r--r--  1 user user  105 Jan 15 10:30 /home/user/.ssh/id_ed25519.pub

# View your public key:
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your_email@example.com

The command generates two files: id_ed25519 (private key) and id_ed25519.pub (public key). The -C flag adds a comment (typically your email) to help identify the key.

Useful ssh-keygen flags for Ed25519:

  • -t ed25519: -t ed25519: Specifies the Ed25519 algorithm.
  • -C "comment": -C "comment": Adds an identifying comment (usually your email).
  • -f /path/to/key: -f /path/to/key: Specifies the output file path.
  • -N "passphrase": -N "passphrase": Sets the passphrase non-interactively (useful in scripts).
  • -a 100: -a 100: Number of KDF rounds for passphrase protection (higher = slower brute force). Default is 16.
# Generate Ed25519 key with all options in one command:
ssh-keygen -t ed25519 -C "work@company.com" -f ~/.ssh/id_ed25519_work -a 100

# Generate key non-interactively (for scripts):
ssh-keygen -t ed25519 -C "deploy@ci" -f ~/.ssh/id_deploy -N "" -a 16

Generate an RSA SSH Key (4096-bit)

If you need compatibility with older systems that do not support Ed25519, use RSA with a minimum key size of 4096 bits. RSA-2048 is still considered secure but offers a smaller security margin for the future.

Step 1: Run the ssh-keygen command with RSA and 4096 bits:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Step 2: Follow the same prompts as above (file location and passphrase).

Step 3: Verify the key:

ls -la ~/.ssh/id_rsa*

# Expected output:
-rw-------  1 user user 3,381 Jan 15 10:35 /home/user/.ssh/id_rsa
-rw-r--r--  1 user user   749 Jan 15 10:35 /home/user/.ssh/id_rsa.pub

# View the public key:
cat ~/.ssh/id_rsa.pub
# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ... your_email@example.com

# Verify key details:
ssh-keygen -l -f ~/.ssh/id_rsa.pub
# 4096 SHA256:abc123... your_email@example.com (RSA)

Important: Important: Never use RSA keys shorter than 2048 bits. RSA-1024 has been considered insecure since 2013. For maximum security margin, always use 4096 bits.

Useful ssh-keygen flags for RSA:

  • -b 4096: -b 4096: Specifies 4096-bit key length (default is 3072 in modern OpenSSH).
  • -o: -o: Uses the new OpenSSH private key format (more resistant to brute-force). This is the default since OpenSSH 7.8.

SSH Key File Locations

SSH keys and configuration files are stored in the ~/.ssh/ directory. Understanding this directory structure is essential for managing your SSH setup.

~/.ssh/
├── id_ed25519          # Ed25519 private key (chmod 600)
├── id_ed25519.pub      # Ed25519 public key  (chmod 644)
├── id_rsa              # RSA private key      (chmod 600)
├── id_rsa.pub          # RSA public key       (chmod 644)
├── config              # SSH client config    (chmod 600)
├── known_hosts         # Server fingerprints  (chmod 644)
└── authorized_keys     # Allowed public keys  (chmod 600, server-side)
FilePurposePermissions
~/.ssh/ directoryThe parent directory must also have correct permissions700 (drwx------)
id_ed25519Ed25519 private key600 (-rw-------)
id_ed25519.pubEd25519 public key644 (-rw-r--r--)
id_rsaRSA private key600 (-rw-------)
id_rsa.pubRSA public key644 (-rw-r--r--)
configSSH client configuration file600 (-rw-------)
known_hostsList of server fingerprints you have connected to (prevents MITM attacks)644 (-rw-r--r--)
authorized_keysPublic keys allowed to log in to this server (on the server side)600 (-rw-------)

On Windows, the SSH directory is typically located at C:\Users\YourUsername\.ssh\. If you are using Git Bash, it maps to ~/.ssh/ as on Linux/macOS.

SSH Config File (~/.ssh/config)

The SSH config file is a powerful tool that lets you define connection presets, manage multiple keys, and configure advanced options. Instead of typing long SSH commands, you can create named aliases.

Basic Configuration Example

Create or edit ~/.ssh/config:

# ~/.ssh/config

# Personal server
Host myserver
    HostName 203.0.113.50
    User deploy
    Port 22
    IdentityFile ~/.ssh/id_ed25519

# Now connect with just:
# ssh myserver
# Instead of:
# ssh -i ~/.ssh/id_ed25519 deploy@203.0.113.50

Using Multiple Keys for Different Services

If you use different keys for GitHub, GitLab, and your production servers:

# ~/.ssh/config

# GitHub (personal account)
Host github.com-personal
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
    IdentitiesOnly yes

# GitHub (work account)
Host github.com-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work
    IdentitiesOnly yes

# GitLab
Host gitlab.com
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_ed25519_gitlab
    IdentitiesOnly yes
    PreferredAuthentications publickey

# Production server
Host production
    HostName prod.example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_prod
    IdentitiesOnly yes

# Usage:
# git clone git@github.com-personal:myuser/repo.git
# git clone git@github.com-work:company/repo.git
# ssh production

ProxyJump: Connecting Through a Bastion Host

If you need to SSH through a jump server (bastion host) to reach an internal server:

# ~/.ssh/config

# Bastion / Jump host
Host bastion
    HostName bastion.example.com
    User jumpuser
    IdentityFile ~/.ssh/id_ed25519
    Port 22

# Internal server (accessed through bastion)
Host internal-server
    HostName 10.0.1.50
    User admin
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump bastion

# Chained jump: client → bastion1 → bastion2 → target
Host deep-internal
    HostName 10.0.2.100
    User admin
    ProxyJump bastion,bastion2

Now you can connect directly with: ssh internal-server. SSH will automatically jump through the bastion host first.

Wildcard and Default Settings

Apply default settings to all connections:

# ~/.ssh/config

# Default settings for all hosts
Host *
    AddKeysToAgent yes
    IdentitiesOnly yes
    ServerAliveInterval 60
    ServerAliveCountMax 3
    Compression yes

# Settings for all *.example.com hosts
Host *.example.com
    User deploy
    IdentityFile ~/.ssh/id_ed25519_work
    Port 2222

Useful SSH Config Options

  • IdentityFile: IdentityFile: Path to the private key to use.
  • IdentitiesOnly: IdentitiesOnly yes: Only use the specified key, do not try others from the agent.
  • ForwardAgent: ForwardAgent yes: Forward your local SSH agent to the remote server (use cautiously).
  • ServerAliveInterval: ServerAliveInterval 60: Send a keep-alive packet every 60 seconds to prevent disconnection.
  • ProxyJump: ProxyJump bastion: Route the connection through another SSH host.
  • Port: Port 2222: Connect to a non-standard SSH port.

Add SSH Key to GitHub / GitLab

Using SSH keys with GitHub and GitLab is the recommended way to authenticate for Git operations. Here is how to set it up:

Step 1: Copy Your Public Key

Display and copy your public key:

# Linux / macOS
cat ~/.ssh/id_ed25519.pub

# macOS — copy directly to clipboard:
pbcopy < ~/.ssh/id_ed25519.pub

# Linux (with xclip):
xclip -selection clipboard < ~/.ssh/id_ed25519.pub

# Windows (PowerShell):
Get-Content ~/.ssh/id_ed25519.pub | Set-Clipboard

# Windows (Git Bash):
clip < ~/.ssh/id_ed25519.pub

Step 2: Add the Key to GitHub

1. Go to GitHub.com > Settings > SSH and GPG keys > New SSH key.
2. Give the key a descriptive title (e.g., "Work Laptop 2024").
3. Paste your public key into the "Key" field.
4. Click "Add SSH key".

Step 3: Add the Key to GitLab

1. Go to GitLab.com > Preferences > SSH Keys.
2. Paste your public key, set a title and optional expiry date.
3. Click "Add key".

Step 4: Test the Connection

Verify that your SSH key is working:

# Test GitHub connection:
ssh -T git@github.com

If successful, you will see a message like:

Hi username! You've successfully authenticated, but GitHub does not provide shell access.

For GitLab:

# Test GitLab connection:
ssh -T git@gitlab.com

# Expected output:
Welcome to GitLab, @username!

Step 5: Clone Repositories Using SSH

Now you can clone repositories using the SSH URL instead of HTTPS:

# Clone via SSH (recommended):
git clone git@github.com:username/repository.git

# Instead of HTTPS:
# git clone https://github.com/username/repository.git

To switch an existing repository from HTTPS to SSH:

# Check current remote URL:
git remote -v
# origin  https://github.com/username/repo.git (fetch)

# Switch to SSH:
git remote set-url origin git@github.com:username/repo.git

# Verify:
git remote -v
# origin  git@github.com:username/repo.git (fetch)

SSH Agent: Managing Keys in Memory

The SSH agent is a background process that holds your private keys in memory so you do not have to enter your passphrase every time you use an SSH key. It is especially useful if your keys are protected with a passphrase (which they should be).

Start the SSH Agent

On Linux/macOS:

# Start the SSH agent in the background:
eval "$(ssh-agent -s)"
# Output: Agent pid 12345

# Add to your shell profile (~/.bashrc, ~/.zshrc) to start automatically:
if [ -z "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -s)" > /dev/null
fi

On Windows (PowerShell):

# PowerShell (run as Administrator to enable the service):
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent

# Verify it is running:
Get-Service ssh-agent
# Status: Running

Add Keys to the Agent

Add your private key to the agent:

# Add a specific key:
ssh-add ~/.ssh/id_ed25519
# Enter passphrase for /home/user/.ssh/id_ed25519:
# Identity added: /home/user/.ssh/id_ed25519 (your_email@example.com)

# Add RSA key:
ssh-add ~/.ssh/id_rsa

Add all default keys:

# Add all default keys (id_rsa, id_ed25519, etc.):
ssh-add

List Keys in the Agent

View all keys currently loaded in the agent:

# List keys with fingerprints:
ssh-add -l
# 256 SHA256:abc123... your_email@example.com (ED25519)
# 4096 SHA256:def456... your_email@example.com (RSA)

# List keys with full public key:
ssh-add -L

macOS Keychain Integration

On macOS, you can store your SSH key passphrase in the system Keychain so it persists across reboots:

# Add key to macOS Keychain:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Add this to your ~/.ssh/config to automatically load keys from the Keychain:

# ~/.ssh/config (macOS)
Host *
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/id_ed25519

Set Key Lifetime

For security, you can set a timeout so keys are automatically removed after a period of inactivity:

# Add key with 1-hour timeout:
ssh-add -t 3600 ~/.ssh/id_ed25519

# Add key with 8-hour timeout (workday):
ssh-add -t 28800 ~/.ssh/id_ed25519

# Remove all keys from the agent:
ssh-add -D

Agent Forwarding

Agent forwarding lets you use your local SSH keys on a remote server without copying the keys there. Use it when you need to SSH from one server to another (e.g., pulling from GitHub on a deployment server):

# Forward agent for a single connection:
ssh -A user@server.example.com

# Or configure in ~/.ssh/config:
Host deploy-server
    HostName deploy.example.com
    User deploy
    ForwardAgent yes

# On the remote server, you can now use your local keys:
# ssh -T git@github.com  ← works without copying keys to the server

Warning: Warning: Agent forwarding exposes your keys to anyone with root access on the remote server. Only use it with servers you trust. Consider ProxyJump as a safer alternative.

SSH Key Passphrase

A passphrase adds a layer of encryption to your private key file. Even if someone steals your private key file, they cannot use it without the passphrase.

Why Use a Passphrase?

  • Laptop theft: If your laptop is stolen, the passphrase prevents immediate access to your servers.
  • Malware: If malware reads your ~/.ssh/ directory, encrypted keys are useless without the passphrase.
  • Shared machines: If others have access to your user account, the passphrase is your last line of defense.
  • Compliance: Many security standards (SOC 2, ISO 27001) require encrypted private keys.

Creating a Key with a Strong Passphrase

When generating a new key, ssh-keygen will prompt for a passphrase. Use a strong, unique passphrase:

# Generate key with increased KDF rounds for stronger passphrase protection:
ssh-keygen -t ed25519 -C "your_email@example.com" -a 100

# When prompted, use a strong passphrase:
# Good:  correct-horse-battery-staple  (4+ random words)
# Good:  My$ecure_Key_2024!ForWork     (mixed characters)
# Bad:   password123                    (too simple)
# Bad:   qwerty                         (dictionary word)

Change an Existing Key Passphrase

You can change (or add) a passphrase to an existing key without regenerating it:

# Change passphrase on an existing key:
ssh-keygen -p -f ~/.ssh/id_ed25519

# Output:
Enter old passphrase:
Enter new passphrase:
Enter same passphrase again:
Your identification has been saved with the new passphrase.

Remove a Passphrase (Not Recommended)

If you need an unencrypted key (e.g., for automated scripts), you can remove the passphrase:

# Remove passphrase (enter empty string as new passphrase):
ssh-keygen -p -f ~/.ssh/id_ed25519

Enter old passphrase:
Enter new passphrase:        # ← Press Enter (empty)
Enter same passphrase again:  # ← Press Enter (empty)

Warning: Warning: Keys without a passphrase are a significant security risk. For automated systems, consider using ssh-agent, deploy keys with limited permissions, or a secrets manager instead.

Increase KDF Rounds

The -a flag controls how many rounds of key derivation are applied to the passphrase. Higher values make brute-force attacks slower:

# Default KDF rounds: 16 (fast, less secure against brute-force)
ssh-keygen -t ed25519 -C "email@example.com"

# Increased KDF rounds: 100 (slower key loading, much harder to brute-force)
ssh-keygen -t ed25519 -C "email@example.com" -a 100

# High KDF rounds: 200 (very slow, maximum brute-force resistance)
ssh-keygen -t ed25519 -C "email@example.com" -a 200

# Note: KDF rounds affect how long it takes to decrypt the key
# with the passphrase, NOT the SSH connection speed.
# -a 100 adds ~1 second to key loading time.

SSH Key Security Best Practices

File Permissions

Incorrect permissions are one of the most common SSH issues. SSH will refuse to use keys or config files with overly permissive permissions:

# If permissions are wrong, SSH will show errors like:
# "WARNING: UNPROTECTED PRIVATE KEY FILE!"
# "Permissions 0644 for '/home/user/.ssh/id_ed25519' are too open."
# "It is required that your private key files are NOT accessible by others."

Set correct permissions:

# Set correct permissions for the .ssh directory:
chmod 700 ~/.ssh

# Set correct permissions for private keys:
chmod 600 ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/config

# Set correct permissions for public keys:
chmod 644 ~/.ssh/id_ed25519.pub
chmod 644 ~/.ssh/id_rsa.pub

# Set correct permissions for authorized_keys (server-side):
chmod 600 ~/.ssh/authorized_keys

# Set correct permissions for known_hosts:
chmod 644 ~/.ssh/known_hosts

# Verify all permissions at once:
ls -la ~/.ssh/
# drwx------  2 user user 4096 Jan 15 10:30 .
# -rw-------  1 user user  464 Jan 15 10:30 id_ed25519
# -rw-r--r--  1 user user  105 Jan 15 10:30 id_ed25519.pub
# -rw-------  1 user user  222 Jan 15 10:30 config

Rotate Keys Regularly

Key rotation limits the blast radius if a key is compromised. Best practices:

  • Generate new keys at least once a year (or per your organization's policy).
  • Add the new public key to all servers before removing the old one.
  • Remove the old public key from authorized_keys after confirming the new key works.
  • Revoke old keys from GitHub/GitLab/Bitbucket.
  • Keep a record of when each key was generated and where it is deployed.
# Key rotation workflow:

# 1. Generate new key
ssh-keygen -t ed25519 -C "email@example.com-2025" -f ~/.ssh/id_ed25519_2025

# 2. Add new public key to server
ssh-copy-id -i ~/.ssh/id_ed25519_2025.pub user@server

# 3. Test new key works
ssh -i ~/.ssh/id_ed25519_2025 user@server

# 4. Remove old public key from server
ssh user@server "sed -i '/old_key_comment/d' ~/.ssh/authorized_keys"

# 5. Update local SSH config to use new key
# Edit ~/.ssh/config and change IdentityFile paths

# 6. Remove old local key files
rm ~/.ssh/id_ed25519_old ~/.ssh/id_ed25519_old.pub

Disable Password Authentication on Servers

Once SSH key authentication is configured, disable password authentication to prevent brute-force attacks:

Edit /etc/ssh/sshd_config:

# /etc/ssh/sshd_config

# Disable password authentication
PasswordAuthentication no

# Disable challenge-response authentication
ChallengeResponseAuthentication no

# Disable PAM (optional, depends on your setup)
# UsePAM no

# Enable public key authentication (should be default)
PubkeyAuthentication yes

# Disable root login
PermitRootLogin no

# Allow only specific users
AllowUsers deploy admin

Restart the SSH service:

# Debian / Ubuntu:
sudo systemctl restart sshd

# RHEL / CentOS / Fedora:
sudo systemctl restart sshd

# Older systems:
sudo service ssh restart

Warning: Warning: Before disabling password authentication, make sure your SSH key login works. Otherwise, you may lock yourself out of the server.

Additional Security Measures

  • Use a non-standard SSH port (e.g., Port 2222) to reduce automated scanning noise.
  • Install fail2ban to block IP addresses with too many failed login attempts.
  • Disable root login: set PermitRootLogin no in sshd_config.
  • Use AllowUsers or AllowGroups to restrict which users can SSH in.
  • Enable two-factor authentication (2FA) for an additional layer of security.
  • Monitor /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL/CentOS) for suspicious activity.

Troubleshooting Common SSH Key Issues

Permission Denied (publickey)

This is the most common SSH error. It means the server rejected your key. Common causes and fixes:

Wrong key being offered: Use ssh -i ~/.ssh/id_ed25519 user@server to specify the correct key.
Public key not in authorized_keys: Add your public key to ~/.ssh/authorized_keys on the server.
Wrong permissions on server: The server-side ~/.ssh/ directory and authorized_keys must have correct permissions.
SSH agent not running: Start the agent and add your key.
# Fix: Specify the correct key explicitly
ssh -i ~/.ssh/id_ed25519 user@server.example.com

# Fix: Copy your public key to the server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server.example.com

# Or manually:
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# Fix: Correct server-side permissions
ssh user@server "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

"Permissions are too open" Error

If you see "WARNING: UNPROTECTED PRIVATE KEY FILE!" or "Permissions 0644 for 'id_ed25519' are too open", SSH is refusing to use the key because others can read it:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/user/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.

Fix the permissions:

# Fix permissions:
chmod 600 ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh

On Windows, right-click the file > Properties > Security > Advanced, and remove all permissions except for your user account.

Debug SSH Connections

Use the -v, -vv, or -vvv flags for increasing levels of debug output:

# Verbose mode (increasing detail):
ssh -v user@server.example.com     # Level 1: basic debug info
ssh -vv user@server.example.com    # Level 2: more detail
ssh -vvv user@server.example.com   # Level 3: maximum detail

# Example debug output (key parts):
debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519 SHA256:abc123...
debug1: Server accepts key: /home/user/.ssh/id_ed25519 ED25519 SHA256:abc123...
debug1: Authentication succeeded (publickey).

Look for these key lines in the debug output:

  • "Offering public key": "Offering public key": Shows which keys SSH is trying.
  • "Server accepts key": "Server accepts key": Confirms the key was accepted.
  • "Authentication succeeded": "Authentication succeeded": Login was successful.
  • "No more authentication methods to try": "No more authentication methods to try": All offered keys were rejected.

Host Key Verification Failed

If the server's host key has changed (e.g., server rebuild), you will see a warning. Remove the old host key:

# Remove a specific host key:
ssh-keygen -R server.example.com

# Remove by IP address:
ssh-keygen -R 203.0.113.50

# Remove by IP and port:
ssh-keygen -R "[server.example.com]:2222"

# Then reconnect and accept the new host key:
ssh user@server.example.com
# The authenticity of host 'server.example.com' can't be established.
# ED25519 key fingerprint is SHA256:xyz789...
# Are you sure you want to continue connecting (yes/no)? yes

Warning: Warning: Only do this if you expect the host key to have changed (e.g., server rebuild). An unexpected change could indicate a man-in-the-middle attack.

Connection Timed Out

  • Verify the server is running and accepting connections on the correct port.
  • Check firewalls (ufw, iptables, or cloud security groups).
  • Try connecting with a specific port: ssh -p 2222 user@server.
  • Add ServerAliveInterval to your SSH config to prevent idle disconnections.
# Test connectivity:
ssh -v -o ConnectTimeout=10 user@server.example.com

# Check if the port is open:
nc -zv server.example.com 22
# or
telnet server.example.com 22

# Add keep-alive to prevent idle timeout (~/.ssh/config):
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

Frequently Asked Questions

Should I use Ed25519 or RSA for SSH keys?

Use Ed25519 for all new SSH keys. Ed25519 provides equivalent or better security than RSA-4096 with significantly smaller key sizes (32 bytes vs ~512 bytes for the public key), faster signing and verification, and resistance to certain implementation attacks. Only use RSA-4096 if you need compatibility with very old systems (pre-2014) that do not support Ed25519.

Is it safe to use SSH keys without a passphrase?

SSH keys without a passphrase are a significant security risk. If your private key file is ever compromised (laptop theft, malware, backup exposure), the attacker gets immediate access to all servers that trust that key. Always use a strong passphrase and rely on ssh-agent to avoid typing it repeatedly. For automated systems, use deploy keys with minimal permissions or a secrets manager.

How do I use multiple SSH keys for different GitHub accounts?

Create a separate key for each account and configure ~/.ssh/config with different Host aliases. For example, set Host github-personal with HostName github.com and IdentityFile ~/.ssh/id_ed25519_personal, and Host github-work with IdentityFile ~/.ssh/id_ed25519_work. Then clone using the alias: git clone git@github-personal:user/repo.git.

What do I do if my SSH private key is compromised?

Immediately remove the compromised public key from all servers (authorized_keys), GitHub, GitLab, and any other services. Generate a new key pair and deploy the new public key. Audit logs for any unauthorized access during the period the key may have been compromised. If the key was used for production servers, consider a full security audit.

Can I convert an RSA key to Ed25519?

No, you cannot convert between key algorithms. You must generate a new Ed25519 key pair with ssh-keygen -t ed25519 and then add the new public key to your servers and services (GitHub, GitLab, etc.). You can keep the old RSA key as a backup while transitioning, then remove it once the new Ed25519 key is deployed everywhere.

Related Tools

Hash Generator - Generate SHA-256, MD5, and other hashes for verifying file integrity and key fingerprints.Password Generator - Create strong, random passphrases for your SSH keys.
𝕏 Twitterin LinkedIn
Was this helpful?

Stay Updated

Get weekly dev tips and new tool announcements.

No spam. Unsubscribe anytime.

Try These Related Tools

#Hash Generator🔑Password Generator📜PEM / Certificate Decoder

Related Articles

bcrypt vs Argon2 vs scrypt: Password Hashing in 2026

Compare bcrypt, Argon2id, and scrypt for password hashing. Benchmarks, security analysis, code examples in 5 languages, and OWASP recommendations.

Password Strength Requirements in 2025: NIST Guidelines & Best Practices

Modern password strength requirements based on NIST SP 800-63B. Minimum length, complexity rules, blocklists, MFA, and what has changed from old practices.