| | |

LFCA 52 ๐Ÿง SSH Keys โ€” Generating and Using

The previous chapter covered connecting with SSH โ€” the commands, the file transfers, and the configuration. This chapter goes deeper into the authentication itself: the key pairs that replace the password with the cryptographic proof. A key pair is two mathematically linked files โ€” the private key that stays on the client and the public key that is copied to the server. The server grants the access only to the connections that can prove they hold the private key, and the proof never sends the private key across the network. This is the modern’s authentication, and it is more secure than the password for the three reasons: the private key is not guessable, the server never sees the secret, and the key can be protected by the passphrase. This chapter covers the key’s generation, the algorithm’s choice, the ssh-copy-id‘s, the manual’s authorized_keys, the permissions’s, the ssh-agent‘s, the passphrase’s, the key’s rotation, the known_hosts, the authorized_keys‘s options, and the patterns that make the key’s management safe.

Key point: The ssh-keygen -t ed25519 -C "comment" is the generation’s, and the Ed25519 is the modern’s algorithm. The ~/.ssh/id_ed25519 is the private’s, and the ~/.ssh/id_ed25519.pub is the public’s. The ssh-copy-id user@host is the copy’s, and the copy’s is the server’s ~/.ssh/authorized_keys‘s. The private’s permission is the 600‘s, the ~/.ssh‘s is the 700‘s, and the authorized_keys‘s is the 600‘s. The ssh-agent‘s is the passphrase’s cache’s, and the ssh-add‘s is the key’s addition’s. The authorized_keys‘s options are the from=, the command=, the no-pty, the no-port-forwarding, the restrict‘s. The known_hosts‘s is the server’s identity’s, and the ssh-keygen -R host is the entry’s removal’s.


Why the SSH keys matter

The SSH keys are the modern’s authentication’s, and the modern’s is the secure’s.

The password’s weaknesses. The password is the guessable’s, the reuse’s, the brute-forceable’s. The ssh‘s password is the network’s, and the network’s is the MITM’s. The password’s is the server’s, and the server’s is the exposure’s.

The key’s strengths. The key’s is the cryptographic’s, and the cryptographic’s is the unguessable’s. The key’s is the two’s, and the two’s is the private’s and the public’s. The key’s is the server’s never’s, and the never’s is the safety’s.

Why the keys are the standard. The keys are the standard, and the standard is the modern’s. The GitHub, the GitLab, the cloud’s, the server’s are the keys’s, and the keys’s is the universal’s. The two are the pair, and the pair is the design’s.

Why the keys matter for the automation. The keys matter for the automation, and the automation’s is the script’s. The scp, the rsync, the git, the ansible are the keys’s, and the keys’s is the passwordless’s. The two are the pair, and the pair is the efficiency’s.

Why the keys matter for the security. The keys matter for the security, and the security’s is the password’s disabling’s. The PasswordAuthentication no is the keys’s, and the keys’s is the only’s. The two are the pair, and the pair is the design’s.

Why the keys matter for the compliance. The keys matter for the compliance, and the compliance’s is the audit’s. The PCI-DSS, the HIPAA, the SOC 2 are the keys’s, and the keys’s is the requirement’s. The two are the pair, and the pair is the design’s.

Why the keys matter for the scale. The keys matter for the scale, and the scale’s is the fleet’s. The thousands’s servers are the keys’s, and the keys’s is the automation’s. The two are the pair, and the pair is the efficiency’s.

Why the keys matter for the rotation. The keys matter for the rotation, and the rotation’s is the lifecycle’s. The keys’s is the periodic’s, and the periodic’s is the rotation’s. The two are the pair, and the pair is the design’s.

Why the keys are the better’s. The keys are the better’s, and the better’s is the password’s. The keys’s is the cryptographic’s, and the cryptographic’s is the stronger’s. The two are the pair, and the pair is the design’s.


The key’s generation

The ssh-keygen -t ed25519 -C "comment" is the generation’s, and the generation’s is the pair’s.

ssh-keygen -t ed25519 -C "user@host"
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase):
# Enter same passphrase again:
# Your identification has been saved in /home/user/.ssh/id_ed25519
# Your public key has been saved in /home/user/.ssh/id_ed25519.pub
# The key fingerprint is:
# SHA256:abcdef... user@host
# The key's randomart image is:
# +--[ED25519 256]--+
# |      .o.        |
# |     . . .       |
# |      o .        |
# |     . + .       |
# |      S + .      |
# |     . . .       |
# |      .          |
# +----[SHA256]-----+

The ssh-keygen -t ed25519 -C "user@host" is the generation’s, and the generation’s is the pair’s. The -t ed25519 is the algorithm’s, and the -C "user@host" is the comment’s. The two are the pair, and the pair is the modern’s.

Why the ssh-keygen matters. The ssh-keygen is the generation’s, and the generation’s is the pair’s. The ssh-keygen is the prompt’s, and the prompt’s is the file’s, the passphrase’s, the confirmation’s. The two are the pair, and the pair is the design’s.

The algorithm’s choice. The -t ed25519 is the modern’s, the -t rsa is the legacy’s, the -t ecdsa is the alternative’s.

ssh-keygen -t ed25519  # the modern's
ssh-keygen -t rsa -b 4096  # the legacy's
ssh-keygen -t ecdsa -b 521  # the alternative's

The -t ed25519 is the modern’s, the -t rsa -b 4096 is the legacy’s, the -t ecdsa -b 521 is the alternative’s. The three are the algorithms’s, and the algorithms’s is the choice’s. The two are the pair, and the pair is the design’s.

Why the algorithm’s choice matters. The algorithm’s choice is the security’s, and the security’s is the key’s length’s. The Ed25519’s is the 256-bit’s, the RSA’s is the 2048-bit’s or the 4096-bit’s. The two are the pair, and the pair is the modern’s.

Why the Ed25519’s is the recommended. The Ed25519’s is the modern’s, and the modern’s is the recommended’s. The Ed25519’s is the fast’s, the small’s, the secure’s. The two are the pair, and the pair is the design’s.

Why the RSA’s is the legacy. The RSA’s is the legacy’s, and the legacy’s is the compatibility’s. The RSA’s is the older’s, and the older’s is the system’s. The two are the pair, and the pair is the design’s.

Why the RSA’s key size matters. The RSA’s key size is the 2048’s or the 4096’s, and the 4096’s is the larger’s. The 2048’s is the minimum’s, and the minimum’s is the acceptable’s. The two are the pair, and the pair is the design’s.

Why the ECDSA’s matters. The ECDSA’s is the alternative’s, and the alternative’s is the NIST’s. The ECDSA’s is the specific’s, and the specific’s is the concern’s. The two are the pair, and the pair is the design’s.


The key’s files

The ~/.ssh/id_ed25519 is the private’s, and the ~/.ssh/id_ed25519.pub is the public’s.

ls -la ~/.ssh/
# -rw------- 1 user user  411 id_ed25519       โ† the private's
# -rw-r--r-- 1 user user  100 id_ed25519.pub   โ† the public's

The id_ed25519 is the private’s, and the private’s is the 600’s. The id_ed25519.pub is the public’s, and the public’s is the 644’s. The two are the pair, and the pair is the permission’s.

Why the private’s permission matters. The private’s permission is the 600’s, and the 600’s is the owner’s only. The sshd refuses the loose’s permission, and the refuse’s is the safety’s. The two are the pair, and the pair is the design’s.

Why the public’s permission matters. The public’s permission is the 644’s, and the 644’s is the world’s readable’s. The public’s is the shareable’s, and the shareable’s is the public’s. The two are the pair, and the pair is the design’s.

The private’s content. The -----BEGIN OPENSSH PRIVATE KEY----- is the private’s, and the private’s is the base64’s.

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
...
-----END OPENSSH PRIVATE KEY-----

The -----BEGIN OPENSSH PRIVATE KEY----- is the private’s, and the private’s is the base64’s. The private’s is the secret’s, and the secret’s is the never’s. The two are the pair, and the pair is the design’s.

Why the private’s content matters. The private’s content is the secret’s, and the secret’s is the never’s. The private’s is the never’s shared’s, and the shared’s is the compromise’s. The two are the pair, and the pair is the security’s.

The public’s content. The ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host is the public’s, and the public’s is the one-line’s.

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host

The ssh-ed25519 is the type’s, the AAAAC3... is the key’s, the user@host is the comment’s. The three are the public’s, and the public’s is the one-line’s. The two are the pair, and the pair is the design’s.

Why the public’s content matters. The public’s content is the one-line’s, and the one-line’s is the authorized_keys‘s. The public’s is the copyable’s, and the copyable’s is the easy’s. The two are the pair, and the pair is the design’s.

Why the public’s fingerprint matters. The public’s fingerprint is the SHA256:...‘s, and the SHA256:...‘s is the identity’s.

ssh-keygen -lf ~/.ssh/id_ed25519.pub
# 256 SHA256:abcdef... user@host (ED25519)

The ssh-keygen -lf ~/.ssh/id_ed25519.pub is the fingerprint’s, and the fingerprint’s is the identity’s. The 256 SHA256:... is the fingerprint’s, and the fingerprint’s is the verification’s. The two are the pair, and the pair is the design’s.

Why the public’s fingerprint matters. The public’s fingerprint is the identity’s, and the identity’s is the verification’s. The fingerprint’s is the short’s, and the short’s is the human’s. The two are the pair, and the pair is the design’s.


The ssh-copy-id

The ssh-copy-id user@host is the copy’s, and the copy’s is the authorized_keys‘s.

ssh-copy-id user@example.com
# /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub"
# /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
# /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
# user@example.com's password:
# Number of key(s) added: 1
# Now try logging into the machine, with: "ssh 'user@example.com'"
# and check to make sure that only the key(s) you wanted were added.

The ssh-copy-id user@example.com is the copy’s, and the copy’s is the authorized_keys‘s. The Number of key(s) added: 1 is the confirmation’s, and the confirmation’s is the success’s. The two are the pair, and the pair is the design’s.

Why the ssh-copy-id matters. The ssh-copy-id is the copy’s, and the copy’s is the authorized_keys‘s. The ssh-copy-id is the one-command’s, and the one-command’s is the convenient’s. The two are the pair, and the pair is the design’s.

The ssh-copy-id‘s options. The -i is the key’s, and the -p is the port’s, and the -o is the ssh’s option’s.

ssh-copy-id -i ~/.ssh/my_key.pub user@example.com
ssh-copy-id -p 2222 user@example.com

The -i ~/.ssh/my_key.pub is the key’s, and the -p 2222 is the port’s. The two are the pair, and the pair is the option’s.

Why the ssh-copy-id‘s options matter. The ssh-copy-id‘s options are the -i, the -p, the -o. The three are the specific’s, and the specific’s is the design’s. The two are the pair, and the pair is the design’s.

The ssh-copy-id‘s mechanism. The ssh-copy-id is the ssh’s, and the ssh’s is the cat >> ~/.ssh/authorized_keys‘s. The ssh-copy-id is the password’s, and the password’s is the last’s. The two are the pair, and the pair is the design’s.

Why the ssh-copy-id‘s mechanism matters. The ssh-copy-id‘s mechanism is the password’s, and the password’s is the last’s. The ssh-copy-id‘s is the authorized_keys‘s, and the authorized_keys‘s is the append’s. The two are the pair, and the pair is the design’s.

The manual’s method. The manual’s method is the cat‘s and the >>‘s.

# On the client:
cat ~/.ssh/id_ed25519.pub

# On the server:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "paste_the_public_key_here" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

The cat ~/.ssh/id_ed25519.pub is the client’s, and the client’s is the read’s. The mkdir -p ~/.ssh, the chmod 700, the echo >> ~/.ssh/authorized_keys, the chmod 600 are the server’s, and the server’s is the manual’s. The two are the pair, and the pair is the design’s.

Why the manual’s method matters. The manual’s method is the fallback’s, and the fallback’s is the ssh-copy-id‘s missing’s. The manual’s is the portable’s, and the portable’s is the universal’s. The two are the pair, and the pair is the design’s.


The authorized_keys

The ~/.ssh/authorized_keys is the server’s, and the server’s is the public’s keys’s.

cat ~/.ssh/authorized_keys
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... another@host

The ssh-ed25519 AAAAC3... is the one-key’s, and the one-key’s is the one-line’s. The two-lines are the two-keys’s, and the two-keys’s is the multiple’s. The two are the pair, and the pair is the design’s.

Why the authorized_keys matters. The authorized_keys is the server’s, and the server’s is the public’s. The authorized_keys is the one-per-line’s, and the one-per-line’s is the format’s. The two are the pair, and the pair is the design’s.

The authorized_keys‘s permission. The 600‘s is the permission’s, and the permission’s is the requirement’s.

chmod 600 ~/.ssh/authorized_keys

The chmod 600 ~/.ssh/authorized_keys is the permission’s, and the permission’s is the requirement’s. The two are the pair, and the pair is the design’s.

Why the authorized_keys‘s permission matters. The authorized_keys‘s permission is the requirement’s, and the requirement’s is the sshd‘s. The sshd refuses the loose’s, and the loose’s is the security’s. The two are the pair, and the pair is the design’s.

The authorized_keys‘s options. The from=, the command=, the no-pty, the no-port-forwarding, the restrict‘s are the common’s.

from="192.168.1.0/24" ssh-ed25519 AAAA... user@host
command="/usr/bin/backup" ssh-ed25519 AAAA... backup@host
no-pty,no-port-forwarding ssh-ed25519 AAAA... restricted@host

The from="192.168.1.0/24" is the source’s, the command="/usr/bin/backup" is the command’s, the no-pty,no-port-forwarding is the restriction’s. The three are the options’s, and the options’s is the restriction’s. The two are the pair, and the pair is the security’s.

Why the authorized_keys‘s options matter. The authorized_keys‘s options are the security’s, and the security’s is the least’s privilege’s. The from= is the source’s, and the command= is the command’s. The two are the pair, and the pair is the design’s.

The restrict‘s option. The restrict is the modern’s, and the modern’s is the all’s disabling’s.

restrict ssh-ed25519 AAAA... user@host

The restrict ssh-ed25519 AAAA... is the modern’s, and the modern’s is the all’s. The restrict is the shorthand’s, and the shorthand’s is the no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-user-rc‘s. The two are the pair, and the pair is the design’s.

Why the restrict matters. The restrict is the modern’s, and the modern’s is the recommended’s. The restrict is the explicit’s, and the explicit’s is the secure’s. The two are the pair, and the pair is the design’s.

The authorized_keys‘s command‘s. The command="/usr/bin/backup" is the specific’s, and the specific’s is the restriction’s.

command="/usr/bin/backup",no-pty ssh-ed25519 AAAA... backup@host

The command="/usr/bin/backup",no-pty is the specific’s, and the specific’s is the restriction’s. The two are the pair, and the pair is the design’s.

Why the command matters. The command is the specific’s, and the specific’s is the automation’s. The command is the backup’s, and the backup’s is the safe’s. The two are the pair, and the pair is the design’s.


The ssh-agent

The ssh-agent is the passphrase’s cache’s, and the cache’s is the session’s.

eval "$(ssh-agent -s)"
# Agent pid 12345
ssh-add ~/.ssh/id_ed25519
# Enter passphrase for /home/user/.ssh/id_ed25519:
# Identity added: /home/user/.ssh/id_ed25519 (user@host)

The eval "$(ssh-agent -s)" is the agent’s start’s, and the start’s is the pid’s. The ssh-add ~/.ssh/id_ed25519 is the addition’s, and the addition’s is the passphrase’s. The two are the pair, and the pair is the design’s.

Why the ssh-agent matters. The ssh-agent is the passphrase’s cache’s, and the cache’s is the convenience’s. The ssh-agent is the once’s, and the once’s is the many’s. The two are the pair, and the pair is the design’s.

The ssh-add‘s options. The -l is the list’s, the -d is the delete’s, the -D is the clear’s, the -t is the timeout’s.

ssh-add -l         # the list's
ssh-add -d ~/.ssh/id_ed25519  # the delete's
ssh-add -D         # the clear's
ssh-add -t 1h ~/.ssh/id_ed25519  # the 1-hour's

The ssh-add -l is the list’s, the ssh-add -d is the delete’s, the ssh-add -D is the clear’s, the ssh-add -t 1h is the timeout’s. The four are the options’s, and the options’s is the control’s. The two are the pair, and the pair is the design’s.

Why the ssh-add‘s options matter. The ssh-add‘s options are the control’s, and the control’s is the management’s. The -l is the audit’s, and the -D is the cleanup’s. The two are the pair, and the pair is the design’s.

The agent’s forwarding. The ForwardAgent yes is the forwarding’s, and the forwarding’s is the risk’s.

Host example
    ForwardAgent yes

The ForwardAgent yes is the forwarding’s, and the forwarding’s is the risk’s. The two are the pair, and the pair is the security’s.

Why the agent’s forwarding matters. The agent’s forwarding is the risk’s, and the risk’s is the remote’s root’s. The remote’s root can use the agent’s, and the agent’s is the keys’s. The two are the pair, and the pair is the security’s.

Why the agent’s forwarding should be the sparing. The agent’s forwarding should be the sparing, and the sparing’s is the trusted’s. The ForwardAgent yes should be the trusted’s, and the trusted’s is the specific’s. The two are the pair, and the pair is the design’s.

The agent’s the desktop’s. The agent’s the desktop’s is the auto-start’s, and the auto-start’s is the graphical’s.

# The desktop's auto-start:
# The ssh-agent is started with the graphical session.
# The ssh-add is called on the first use.

The ssh-agent‘s is the desktop’s, and the desktop’s is the auto-start’s. The two are the pair, and the pair is the convenience’s.

Why the agent’s the desktop’s matters. The agent’s the desktop’s is the auto-start’s, and the auto-start’s is the graphical’s. The macOS’s is the Keychain’s, and the Keychain’s is the automatic’s. The two are the pair, and the pair is the design’s.


The known_hosts

The ~/.ssh/known_hosts is the server’s identity’s, and the identity’s is the trust’s.

cat ~/.ssh/known_hosts
# example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
# |1|abcdef...= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...

The example.com ssh-ed25519 AAAA... is the entry’s, and the entry’s is the host’s key’s. The |1|abcdef...= is the hashed’s, and the hashed’s is the HashKnownHosts‘s. The two are the pair, and the pair is the design’s.

Why the known_hosts matters. The known_hosts is the server’s identity’s, and the identity’s is the MITM’s prevention’s. The known_hosts is the client’s record’s, and the record’s is the verification’s. The two are the pair, and the pair is the security’s.

The known_hosts‘s warning. The WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! is the warning’s, and the warning’s is the MITM’s.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

The WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! is the warning’s, and the warning’s is the MITM’s. The two are the pair, and the pair is the security’s.

Why the known_hosts‘s warning matters. The known_hosts‘s warning is the MITM’s, and the MITM’s is the security’s. The warning’s is the legitimate’s or the attack’s, and the attack’s is the serious’s. The two are the pair, and the pair is the design’s.

The known_hosts‘s removal. The ssh-keygen -R host is the removal’s, and the removal’s is the entry’s.

ssh-keygen -R example.com
# # Host example.com found: line 1
# /home/user/.ssh/known_hosts updated.
# Original contents retained as /home/user/.ssh/known_hosts.old

The ssh-keygen -R example.com is the removal’s, and the removal’s is the entry’s. The Original contents retained as ...old is the backup’s, and the backup’s is the safety’s. The two are the pair, and the pair is the design’s.

Why the known_hosts‘s removal matters. The known_hosts‘s removal is the legitimate’s, and the legitimate’s is the server’s reinstall’s. The removal’s is the old’s, and the old’s is the stale’s. The two are the pair, and the pair is the design’s.

The StrictHostKeyChecking‘s. The StrictHostKeyChecking=yes is the strict’s, and the strict’s is the refuse’s.

ssh -o StrictHostKeyChecking=yes user@example.com

The ssh -o StrictHostKeyChecking=yes is the strict’s, and the strict’s is the refuse’s. The two are the pair, and the pair is the security’s.

Why the StrictHostKeyChecking‘s matters. The StrictHostKeyChecking‘s is the strict’s, and the strict’s is the security’s. The accept-new is the modern’s, and the modern’s is the balance’s. The two are the pair, and the pair is the design’s.

The HashKnownHosts‘s. The HashKnownHosts yes is the hash’s, and the hash’s is the privacy’s.

HashKnownHosts yes

The HashKnownHosts yes is the hash’s, and the hash’s is the privacy’s. The two are the pair, and the pair is the design’s.

Why the HashKnownHosts‘s matters. The HashKnownHosts‘s is the hash’s, and the hash’s is the host’s names’s. The hash’s is the local’s, and the local’s is the privacy’s. The two are the pair, and the pair is the design’s.


The key’s rotation

The key’s rotation is the lifecycle’s, and the lifecycle’s is the periodic’s.

The rotation’s reasons. The rotation’s reasons are the compromise’s, the employee’s departure’s, the policy’s. The three are the common’s, and the common’s is the reason’s.

The rotation’s process. The rotation’s process is the generate’s, the copy’s, the test’s, the remove’s. The four are the steps’s, and the steps’s is the process’s.

# 1. Generate the new key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "user@host"

# 2. Copy the new key
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@example.com

# 3. Test the new key
ssh -i ~/.ssh/id_ed25519_new user@example.com

# 4. Remove the old key
# On the server, edit ~/.ssh/authorized_keys

The ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new, the ssh-copy-id -i ~/.ssh/id_ed25519_new.pub, the ssh -i ~/.ssh/id_ed25519_new, the remove the old key are the four, and the four are the rotation’s. The two are the pair, and the pair is the process’s.

Why the rotation’s process matters. The rotation’s process is the four’s, and the four’s is the safe’s. The generate’s is the first’s, and the first’s is the new’s. The two are the pair, and the pair is the design’s.

The rotation’s no-downtime’s. The rotation’s no-downtime’s is the both’s, and the both’s is the temporary’s.

# The both keys are the authorized_keys's
# The old's is removed after the new's is tested.

The both keys’s is the authorized_keys’s, and the authorized_keys’s is the both’s. The two are the pair, and the pair is the design’s.

Why the rotation’s no-downtime’s matters. The rotation’s no-downtime’s is the both’s, and the both’s is the safe’s. The old’s is the removed’s, and the removed’s is the after’s. The two are the pair, and the pair is the design’s.

The rotation’s automation’s. The rotation’s automation’s is the ansible’s, and the ansible’s is the fleet’s.

# Ansible's:
- name: Rotate SSH keys
  ansible.posix.authorized_key:
    user: "{{ item.user }}"
    state: present
    key: "{{ lookup('file', item.key) }}"

The ansible.posix.authorized_key is the ansible’s, and the ansible’s is the fleet’s. The two are the pair, and the pair is the scale’s.

Why the rotation’s automation’s matters. The rotation’s automation’s is the scale’s, and the scale’s is the fleet’s. The rotation’s is the periodic’s, and the periodic’s is the policy’s. The two are the pair, and the pair is the design’s.

The rotation’s the audit’s. The rotation’s the audit’s is the who’s, and the who’s is the when’s.

# The audit's:
# The authorized_keys's is the who's.
# The file's mtime's is the when's.

The who's is the authorized_keys’s, and the when's is the mtime’s. The two are the pair, and the pair is the audit’s.

Why the rotation’s the audit’s matters. The rotation’s the audit’s is the compliance’s, and the compliance’s is the review’s. The audit’s is the periodic’s, and the periodic’s is the policy’s. The two are the pair, and the pair is the design’s.


Complete Example Session

# ============================================
# PART 1: THE KEY'S GENERATION
# ============================================

ssh-keygen -t ed25519 -C "user@host"
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase):
# Your identification has been saved in /home/user/.ssh/id_ed25519
# Your public key has been saved in /home/user/.ssh/id_ed25519.pub

# ============================================
# PART 2: THE KEY'S FILES
# ============================================

ls -la ~/.ssh/
# -rw------- 1 user user  411 id_ed25519
# -rw-r--r-- 1 user user  100 id_ed25519.pub

cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host

# ============================================
# PART 3: THE SSH-COPY-ID
# ============================================

ssh-copy-id user@example.com
# Number of key(s) added: 1

# ============================================
# PART 4: THE MANUAL'S METHOD
# ============================================

# On the client:
cat ~/.ssh/id_ed25519.pub

# On the server:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "paste_the_public_key_here" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# ============================================
# PART 5: THE TEST
# ============================================

ssh user@example.com
# The passwordless's login.

# ============================================
# PART 6: THE SSH-AGENT
# ============================================

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Enter passphrase for /home/user/.ssh/id_ed25519:
# Identity added: /home/user/.ssh/id_ed25519 (user@host)

ssh-add -l
# 256 SHA256:abcdef... user@host (ED25519)

# ============================================
# PART 7: THE AUTHORIZED_KEYS'S OPTIONS
# ============================================

# ~/.ssh/authorized_keys
# from="192.168.1.0/24" ssh-ed25519 AAAA... user@host
# command="/usr/bin/backup",no-pty ssh-ed25519 AAAA... backup@host
# restrict ssh-ed25519 AAAA... restricted@host

# ============================================
# PART 8: THE KNOWN_HOSTS
# ============================================

cat ~/.ssh/known_hosts
# example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...

ssh-keygen -R example.com
# /home/user/.ssh/known_hosts updated.

# ============================================
# PART 9: THE ROTATION
# ============================================

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "user@host"
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@example.com
ssh -i ~/.ssh/id_ed25519_new user@example.com
# The old's is removed after the new's is tested.

# ============================================
# PART 10: WHAT NOT TO DO
# ============================================

# Don't share the private's key
# The private's is the secret's.                              // โš ๏ธ

# Don't use the loose's permission
chmod 644 ~/.ssh/id_ed25519  # โŒ                            // โš ๏ธ

# Don't use the RSA's 1024-bit's
ssh-keygen -t rsa -b 1024  # โŒ the weak's                   // โš ๏ธ

# Don't forget the authorized_keys's permission
chmod 644 ~/.ssh/authorized_keys  # โŒ                       // โš ๏ธ

# Don't use the agent's forwarding on the untrusted's
ForwardAgent yes  # โŒ the risk's                            // โš ๏ธ

# Don't ignore the known_hosts's warning
# The MITM's.                                               // โš ๏ธ

The ten parts cover the key’s generation, the key’s files, the ssh-copy-id, the manual’s method, the test, the ssh-agent, the authorized_keys‘s options, the known_hosts, the rotation, and the anti-patterns.


Quick Reference

The Key’s Generation

CommandPurpose
ssh-keygen -t ed25519The modern’s
ssh-keygen -t rsa -b 4096The legacy’s
ssh-keygen -t ecdsa -b 521The alternative’s
ssh-keygen -f FILEThe custom’s file
ssh-keygen -C "comment"The comment’s
ssh-keygen -lf FILEThe fingerprint’s

The Key’s Files

FilePurpose
~/.ssh/id_ed25519The private’s
~/.ssh/id_ed25519.pubThe public’s
~/.ssh/authorized_keysThe server’s keys
~/.ssh/known_hostsThe client’s record
~/.ssh/configThe client’s config

The Key’s Permissions

FilePermission
~/.ssh700
~/.ssh/id_ed25519600
~/.ssh/id_ed25519.pub644
~/.ssh/authorized_keys600

The ssh-copy-id‘s Options

OptionPurpose
-i FILEThe specific’s key
-p PORTThe port’s
-o OPTIONThe ssh’s option
-fThe force’s

The ssh-agent‘s Commands

CommandPurpose
eval "$(ssh-agent -s)"The start’s
ssh-add ~/.ssh/id_ed25519The addition’s
ssh-add -lThe list’s
ssh-add -d KEYThe delete’s
ssh-add -DThe clear’s
ssh-add -t 1h KEYThe timeout’s

The authorized_keys‘s Options

OptionPurpose
from="..."The source’s
command="..."The command’s
no-ptyThe no-tty’s
no-port-forwardingThe no-forward’s
no-agent-forwardingThe no-agent’s
restrictThe all’s disabling’s

The Algorithms

AlgorithmStatus
Ed25519The modern’s
RSA 4096The acceptable’s
RSA 2048The minimum’s
ECDSAThe alternative’s

Best Practices

โœ… Do This:

# Use the ed25519's key
ssh-keygen -t ed25519 -C "user@host"                           # โœ…
# Copy the public's key
ssh-copy-id user@example.com                                   # โœ…
# Set the permission
chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519                # โœ…
# Use the ssh-agent
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519            # โœ…
# Use the restrict's option
restrict ssh-ed25519 AAAA... user@host                         # โœ…
# Use the fingerprint's verification
ssh-keygen -lf ~/.ssh/id_ed25519.pub                           # โœ…
# Rotate the keys periodically
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new                 # โœ…
# Use the known_hosts's removal for the legitimate's
ssh-keygen -R example.com                                      # โœ…

โŒ Don’t Do This:

# Don't share the private's key
cat ~/.ssh/id_ed25519  # โŒ the secret's                       // โš ๏ธ
# Don't use the loose's permission
chmod 644 ~/.ssh/id_ed25519  # โŒ                             // โš ๏ธ
# Don't use the RSA's 1024-bit's
ssh-keygen -t rsa -b 1024  # โŒ the weak's                     // โš ๏ธ
# Don't forget the authorized_keys's permission
chmod 644 ~/.ssh/authorized_keys  # โŒ                        // โš ๏ธ
# Don't use the agent's forwarding on the untrusted's
ForwardAgent yes  # โŒ the risk's                              // โš ๏ธ
# Don't ignore the known_hosts's warning
# The MITM's.                                                // โš ๏ธ

Common Pitfalls

PitfallProblemSolution
The shared privateThe compromiseThe never’s
The loose’s permissionThe sshd‘s refusalThe chmod 600
The RSA’s 1024-bit’sThe weakThe Ed25519’s
The authorized_keys‘s loose’sThe refusalThe chmod 600
The agent’s forwardingThe riskThe no or the trusted’s
The known_hosts’s warningThe MITM’sThe investigate’s
The missing ssh-copy-idThe manual’sThe cat‘s and the >>‘s
The no passphrase’sThe compromise’sThe agent’s

Real-World Examples

1. The generation

ssh-keygen -t ed25519 -C "user@host"

2. The copy

ssh-copy-id user@example.com

3. The manual

cat ~/.ssh/id_ed25519.pub
echo "..." >> ~/.ssh/authorized_keys

4. The permission

chmod 600 ~/.ssh/id_ed25519

5. The agent

ssh-add ~/.ssh/id_ed25519

6. The authorized_keys‘s options

from="192.168.1.0/24" ssh-ed25519 AAAA... user@host

7. The known_hosts

ssh-keygen -R example.com

8. The rotation

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new

9. The fingerprint

ssh-keygen -lf ~/.ssh/id_ed25519.pub

10. The test

ssh user@example.com

Visual: The Key’s Pair

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE CLIENT                                  โ”‚
โ”‚    ~/.ssh/id_ed25519  โ† the private's        โ”‚
โ”‚    ~/.ssh/id_ed25519.pub โ† the public's      โ”‚
โ”‚                                              โ”‚
โ”‚         โ”‚  The ssh-copy-id                    โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  THE SERVER                                  โ”‚
โ”‚    ~/.ssh/authorized_keys  โ† the public's    โ”‚
โ”‚                                              โ”‚
โ”‚  The private's never leaves the client's.    โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Visual: The Authentication’s Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  1. The client's โ†’ the server's               โ”‚
โ”‚  2. The server's โ†’ the challenge's            โ”‚
โ”‚  3. The client's signs the challenge's with   โ”‚
โ”‚     the private's key's                       โ”‚
โ”‚  4. The server's verifies with the public's   โ”‚
โ”‚  5. The access's is granted's                 โ”‚
โ”‚                                              โ”‚
โ”‚  The private's key's never crosses the       โ”‚
โ”‚  network's.                                  โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Visual: The Key’s Files

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ~/.ssh/                                     โ”‚
โ”‚    โ”œโ”€โ”€ id_ed25519        600  the private's  โ”‚
โ”‚    โ”œโ”€โ”€ id_ed25519.pub    644  the public's   โ”‚
โ”‚    โ”œโ”€โ”€ authorized_keys   600  the server's   โ”‚
โ”‚    โ”œโ”€โ”€ known_hosts       644  the record's   โ”‚
โ”‚    โ””โ”€โ”€ config            600  the config's   โ”‚
โ”‚                                              โ”‚
โ”‚  The private's and the server's are the      โ”‚
โ”‚  600's, and the public's is the 644's.       โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Visual: The authorized_keys‘s Options

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  from="192.168.1.0/24"                       โ”‚
โ”‚    The source's restriction's                โ”‚
โ”‚                                              โ”‚
โ”‚  command="/usr/bin/backup"                   โ”‚
โ”‚    The command's restriction's               โ”‚
โ”‚                                              โ”‚
โ”‚  no-pty                                      โ”‚
โ”‚    The no-terminal's                         โ”‚
โ”‚                                              โ”‚
โ”‚  restrict                                    โ”‚
โ”‚    The all's disabling's                     โ”‚
โ”‚                                              โ”‚
โ”‚  The options's is the least's privilege's.   โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Visual: The Rotation’s Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  1. The new's key's generation's             โ”‚
โ”‚       ssh-keygen -f ~/.ssh/id_ed25519_new    โ”‚
โ”‚                                              โ”‚
โ”‚  2. The new's public's copy's                โ”‚
โ”‚       ssh-copy-id -i ..._new.pub             โ”‚
โ”‚                                              โ”‚
โ”‚  3. The new's key's test's                   โ”‚
โ”‚       ssh -i ~/.ssh/id_ed25519_new           โ”‚
โ”‚                                              โ”‚
โ”‚  4. The old's key's removal's                โ”‚
โ”‚       The authorized_keys's edit's           โ”‚
โ”‚                                              โ”‚
โ”‚  The both's is the no-downtime's.            โ”‚
โ”‚                                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
The algorithmThe Ed25519’s
The private’sThe ~/.ssh/id_ed25519
The public’sThe ~/.ssh/id_ed25519.pub
The server’sThe ~/.ssh/authorized_keys
The copy’sThe ssh-copy-id
The private’s permissionThe 600‘s
The authorized_keys‘s permissionThe 600‘s
The agent’sThe ssh-agent‘s
The agent’s add’sThe ssh-add‘s
The record’sThe ~/.ssh/known_hosts
The removal’sThe ssh-keygen -R‘s
The rotation’sThe periodic’s

Key takeaways:

  • The SSH keys are the modern’s authentication’s โ€” the private’s stays on the client, the public’s goes to the server, and the proof never sends the private’s
  • The ssh-keygen -t ed25519 -C "comment" is the generation’s โ€” the Ed25519 is the modern’s, and the RSA is the legacy’s
  • The ssh-copy-id user@host is the copy’s โ€” it is the one-command’s, and the manual’s is the cat‘s and the >>‘s
  • The private’s permission is the 600‘s, the ~/.ssh‘s is the 700‘s, and the authorized_keys‘s is the 600‘s โ€” the sshd refuses the loose’s
  • The ssh-agent is the passphrase’s cache’s โ€” the ssh-add‘s is the addition’s, and the -l, the -d, the -D, the -t are the management’s
  • The authorized_keys‘s options are the from=, the command=, the no-pty, the no-port-forwarding, the restrict‘s โ€” the options’s is the least’s privilege’s
  • The known_hosts is the server’s identity’s โ€” the ssh-keygen -R host is the removal’s, and the HashKnownHosts is the privacy’s
  • The key’s rotation is the periodic’s โ€” the new’s generation’s, the copy’s, the test’s, the old’s removal’s
  • The passphrase’s is the extra’s โ€” the ssh-agent‘s is the convenience’s, and the no-passphrase’s is the risk’s
  • The agent’s forwarding is the risk’s โ€” the ForwardAgent yes should be the trusted’s only

Remember: The SSH keys are the pair’s, and the pair’s is the private’s and the public’s. The ssh-keygen‘s is the generation’s, and the ssh-copy-id‘s is the copy’s. The ssh-agent‘s is the passphrase’s cache’s, and the authorized_keys‘s options are the restriction’s. The private’s permission is the 600’s, and the server’s is the requirement’s. The keys’s is the modern’s, and the modern’s is the secure’s.


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!