Skip to content

SSH

Creating a Ssh Key

Linux / MacOS

Example

ssh-keygen -t ed25519 -C "userid and/or email here"

Once your key is created you should find it located in ~/.ssh using the default options it the path would be ~/.ssh/id_ed25519 for the private key and ~/.ssh/id_ed25519.pub for the public key.

Putty

Attention:

Make sure you have putty installed for this to work.
If you do not have it installed use the package manager of your choice

[!example] Using winget to install Putty

winget install -e --id PuTTY.PuTTY

[!example] Creating a new putty key

puttygen -t ed25519 -C "userid and/or email here" -o putty_key.ppk

Extracting Keys

To use your putty key on without putty you will need to extract the keys. Keep track of where you extra the key too and the file names created, you will need this information later. Also treat these keys like you would a password, they're sensitive information that needs to be protected.

Public Key

To get your public key from your putty key you will need to extract it

Extracting Public Key

puttygen putty_key.ppk -O public-openssh -o putty_key.pub
Private Key

To get your private key from your putty key you will need to extract it

Extracting Private Key

puttygen putty_key.ppk -O private-openssh -o putty_key

Convert Openssh Key to Putty Key

To convert an openssh key to putty key you will need the private key file as well as any passwords that may or may not be securing that key. This will most likely not apply to anyone unless they want to take an existing key and use in putty

Converting the key

puttygen id_ed25519 -o putty_key.ppk

TPM

WIP

Getting Started

Check to see if you have /dev/tpm0 on your system. If you do make sure you have tpm2-pkcs11 installed. This is needed to act as a smart card interface. This will allow us to generate and store the private key in the TPM. Making it way more secure than just leaving a private key in your ~/.ssh directory.

Next check the group on /dev/tpmrm0 and add that group to your user, most likely it will be tss so do sudo usermod -a -G tss "$(whoami)" and then relogin.

Create the Keys

tpm2_ptool init
tpm2_ptool addtoken --pid=1 --label=ssh --userpin=PASSWORDHERE --sopin=RECOVERYPASSWORDHERE
tpm2_ptool addkey --label=ssh --userpin=PASSWORD --algorithm=ecc256

Reading the Public Key

ssh-keygen -D /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so | tee ~/.ssh/id_tpm.pub

Take the output from here and add that to the authorized keys file on whatever system you need to connect to.

Using the TPM Key

You'll need to point ssh to the identiy file that is the tpm using -I /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so. This is easier done in your ~/.ssh/config file. To set it for everything add this at the bottom of your config

 Host *
   PKCS11Provider /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so

Using Your SSH Key

To use your key, simply ssh to a server. It should instantly allow you in without prompting. Putty users will have to enter their user name depending on how they have their connection configured.

If you're having problems you may need to add the keys to your ssh-agent. ssh-agent -a ~/.ssh/id_ed25519
Putty should do this for you, you may have to go into the connection settings and tell it to use the key. I believe moba works the same way.

Agent Forwarding

For MacOS you will need to do ssh-add --apple-use-keychain to add your keys to the keychain for Agent Forwarding to work correctly

When you use agent forwarding it will allow your keys to be used on a remote system that you're connected too. You do this with the -A flag so ssh -A user@host however you can configure your ssh config to do this for you automatically. Make sure you place this at the END of your config

~/.ssh/config

host *
 Compression yes
 StrictHostKeyChecking no
 ForwardAgent yes

host * says use these options on anything that matches. This is why we put it at the bottom of ~/.ssh/confg because it works on a first match priceable. compression yes means that it will use compression, this is helpful for low-bandwidth connections and data transfers. StrictHostKeyChecking no says don't alert me to accept keys. Not a great idea for most things, but not something we can avoid with our current setup. ForwardAgent yes means that it will forward the ssh-agent to the destination connection. This is the main thing we want, the other options are helpful but not required.

SSH Agent Forwarding via Sudo

Now that you're forwarding your agent and you're able to ssh into other systems from the system you're connected to, let's assume you need to become root or another user. To do this you will need to forward your shell and environment. Do do this you will do sudo -E -s or sudo -E -s -u username. this will allow you to forward your agent from your system, to a remote system, over sudo, and use your keys that way. The -E flag forwards your environment and the -s forwards your shell.

This example forwards your agent, connects to a host, then drops you into root with your agent forwarded

ssh -A user@hostname
sudo -E -s

SSH Host Jumping

To use another host as a jumpbox you have to use the -J flag. You can combine this with the -A to forward your agent too.

# Use a system to connect to another system
ssh -J user@jump-box user@destination-server
# Jump from jumpbox to jumpbox2 to jumpbox3 to destination
ssh -J user@jumpbox,user@jumpbox2,user@jumpbox3 user@destination

If you're forwarding your agent and your public key is on the various servers you can jump to all of them adding the -A flag.

Faster SSH

Getting faster ssh connections is simple and easy, you can use the ControlMaster option!

host *
  ControlMaster auto
  ControlPath ~/.ssh/sockets/%r@%h-%p
  ControlPersist 600

This tells ssh to use a socket to reconnect to ssh and hold it open for 600 seconds. This is really helpful if you're bouncing around to different systems and have to reconnect to them. It can cause some problems if you're opening a lot of connections at once. In practice I've only hit a problem a handful of times though and I make A LOT of connections via ssh. So YMMV. If you have problems just remove, comment out, or place it on specific connections rather than all (*) connections

SSH Key Signing

Signing Data

Now let's take a step further! How about signing files, data, etc? You can do that with your ssh key! Why would you want to do this? You can ensure data integrity and prove that the data came from you.

ssh-keygen -Y sign -f ~/.ssh/id_ed25519 -n file FILENAMEHERE

So lets break this down -Y sign is telling it that you're going to sign something, then comes the path to your private key, next is the name space, since we're signing a file we tell it -n file.

Verifying Data

Okay, so we signed a file, but how do we verify it?

ssh-keygen -Y verify -f allowed_signers -I hugh.smalley@lexisnexisrisk.com -n file -s FILENAMEHERE.sig <FILENAMEHERE

Just like signing -Y verify is telling it that we want to verify something. -f allow_signers is telling it the name of the file with the information to lookup public keys. Much like the authorized_keys file lets ssh know they's keys are allowed to connect.

For example here's my keys in the allowed_signers file.

hugh.smalley@lexisnexisrisk.com sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPEroRTKtLMu9EXxFXXNm8bzA1w/c4v7gFKeFPXmHII1AAAABHNzaDo= Yubikey 5
hugh.smalley@lexisnexisrisk.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuAYj8uDz7o5qJzHrEohvfpX/RWBoqudHRoaD+6dR+X Macbook Pro

The first section is a comma delineated list of identifiers eg email addresses. The next section is the type of key, eg ssh-ed25519, ssh-rsa, etc. Lastly the public key.

To continue the -I says the name of the identity to check in the allowed_signers file.-n file is again the name space, -sis the signature file and <FILENAMEHEREis the file we're checking.

You can wrap this up in some functions to throw into your .bashrc,.zshrc,etc..

ssh_sign () {
  ssh-keygen -Y sign -f ~/.ssh/id_ed25519 -n file "${1}"
}

ssh_verify () {
  ssh-keygen -Y verify -f allowed_signers -I "${1}" -n file -s "${2}.sig" <"${2}"
}

Code Signing

Now configure git so it knows about your signing key

git config --global gpg.format ssh
git config --global user.signingkey "${HOME}/.ssh/id_ed25519.pub"

Now when you commit on git add a -S to sign it!

git commit -Sam "Adding, Signing, and Commenting!"

If you want to skip adding the S then set:

git config --global commit.gpgsign true

Now you can sign commits and other data with ssh!

SSH Certificates

WIP

A SSH CA is a certificate authority that can issue and sign SSH certificates for authentication. SSH certificates are similar to SSH keys, but they have additional features such as expiration dates and identity information. To create a SSH CA, you need to generate a SSH key pair using the ssh-keygen command and specify a file name and a comment for the CA key¹². For example:

$ ssh-keygen -t rsa -b 4096 -f host_ca -C host_ca
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in host_ca.
Your public key has been saved in host_ca.pub.

This will create a private key file host_ca and a public key file host_ca.pub. The public key file can be used to verify certificates issued by the CA, while the private key file should be kept secure and only used by the CA to sign certificates¹².

Source: Conversation with Bing, 5/3/2023
(1) How to configure SSH Certificate-Based Authentication - goteleport.com. https://goteleport.com/blog/how-to-configure-ssh-certificate-based-authentication/.
(2) 14.3.3. Creating SSH CA Certificate Signing Keys. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-creating_ssh_ca_certificate_signing-keys.
(3) GitHub - cloudtools/ssh-ca: Management utilities to support a …. https://github.com/cloudtools/ssh-ca.
(4) Using a CA with SSH - lorier.net. https://www.lorier.net/docs/ssh-ca.html.
(5) How to configure and setup SSH certificates for SSH authentication. https://dev.to/gvelrajan/how-to-configure-and-setup-ssh-certificates-for-ssh-authentication-b52.

To use the CA to sign certificates, you need to have the public keys of the hosts or users that you want to issue certificates for. Then you can use the ssh-keygen command with the -s option to specify the CA private key and the -I option to specify a certificate identity²³. For example, to sign a user's public key and create a user certificate, you can use a command like this:

$ ssh-keygen -s ca_user_key -I user@example.com id_rsa.pub

This will create a file named id_rsa-cert.pub that contains the user certificate. The certificate identity can be any alphanumeric value, but it is recommended to use the user name or host name for clarity²³. To sign a host's public key and create a host certificate, you need to add the -h option²³. For example:

$ ssh-keygen -s ca_host_key -I host.example.com -h ssh_host_rsa_key.pub

This will create a file named ssh_host_rsa_key-cert.pub that contains the host certificate.

Source: Conversation with Bing, 5/3/2023
(1) 14.3.3. Creating SSH CA Certificate Signing Keys Red Hat Enterprise …. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-creating_ssh_ca_certificate_signing-keys.
(2) How to configure and setup SSH certificates for SSH authentication. https://dev.to/gvelrajan/how-to-configure-and-setup-ssh-certificates-for-ssh-authentication-b52.
(3) SSH Best Practices using Certificates, 2FA and Bastions. https://goteleport.com/blog/how-to-ssh-properly/.

To configure SSH to trust the CA, you need to copy the CA's public key to the hosts or users that you want to trust the certificates issued by the CA. For user authentication, you need to create a file named /etc/ssh/trusted_user_ca_keys on the SSH server and paste the CA's public key in it¹³⁴. For example:

$ echo "cert-authority $(cat host_ca.pub)" >> /etc/ssh/trusted_user_ca_keys

This will tell the SSH server to trust any user certificate signed by the CA. For host authentication, you need to create or update a file named /etc/ssh/ssh_known_hosts on the SSH client and paste the CA's public key in it with a @cert-authority prefix⁵. For example:

$ echo "@cert-authority *.example.com $(cat host_ca.pub)" >> /etc/ssh/ssh_known_hosts

This will tell the SSH client to trust any host certificate signed by the CA for any host under the example.com domain.

Source: Conversation with Bing, 5/3/2023
(1) Configuring your OpenSSH servers to trust your SSH CA hosted by. https://docs.venafi.com/Docs/22.4/TopNav/Content/SSH/SSHCertificates/t-ssh-certificate-configure-openssh-trust-venafi-ca.php.
(2) How to configure SSH Certificate-Based Authentication - goteleport.com. https://goteleport.com/blog/how-to-configure-ssh-certificate-based-authentication/.
(3) How to configure and visualize an SSH CA · GitHub - Gist. https://gist.github.com/seanw2020/924c50e4c8428ad2d030db99cc819e20.
(4) Scalable and secure access with SSH - Engineering at Meta. https://engineering.fb.com/2016/09/12/security/scalable-and-secure-access-with-ssh/.
(5) How to configure and setup SSH certificates for SSH authentication. https://dev.to/gvelrajan/how-to-configure-and-setup-ssh-certificates-for-ssh-authentication-b52.

To revoke a certificate issued by the CA, you need to add the certificate to a file named /etc/ssh/revoked_keys on the SSH server and specify the file name in the sshd_config file as follows:

RevokedKeys /etc/ssh/revoked_keys

This will tell the SSH server to reject any authentication attempt using the revoked certificate¹. To test if a certificate has been revoked, you can use the ssh-keygen command with the -Qf option to query the revocation list for the presence of the certificate¹. For example:

$ ssh-keygen -Qf /etc/ssh/revoked_keys id_rsa-cert.pub

This will return either id_rsa-cert.pub: revoked or id_rsa-cert.pub: valid depending on the status of the certificate. Alternatively, you can revoke a CA certificate by changing the cert-authority directive to revoke in the known_hosts file¹. For example:

@revoke *.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC0g+ZTxC7weoIJLUafOgrm+h…

This will tell the SSH client to reject any host certificate signed by the revoked CA for any host under the example.com domain.

Source: Conversation with Bing, 5/3/2023
(1) 14.3.8. Revoking an SSH CA Certificate - Red Hat Customer Portal. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-revoking_an_ssh_ca_certificate.
(2) How to Revoke SSH Certificates - CybersecurityHQ.io. https://www.cybersecurityhq.io/blog/how-to-revoke-ssh-certificates.
(3) Hashicorp Vault revoke SSH signed certificate - Stack Overflow. https://stackoverflow.com/questions/68812537/hashicorp-vault-revoke-ssh-signed-certificate.

You can specify additional options for the certificates when you sign them using the ssh-keygen command. Some of the options are:

  • -V to specify the validity interval of the certificate. For example, -V +1h means the certificate is valid for one hour from now²⁴.
  • -n to specify the principals (user names or host names) that are allowed to use the certificate. For example, -n darren means only the user named darren can use the certificate²⁴.
  • -z to specify a serial number for the certificate. For example, -z 1 means the certificate has a serial number of 1²⁴.
  • -O to specify one or more certificate options that can restrict or permit certain features. For example, -O no-agent-forwarding means the certificate cannot be used to forward an authentication agent²³.

For example, to sign a user's public key and create a user certificate that is valid for one hour, allows only the user named darren to use it, has a serial number of 1, and does not allow agent forwarding, you can use a command like this:

$ ssh-keygen -s ca_user_key -I darren -n darren -V +1h -z 1 -O no-agent-forwarding id_rsa.pub

This will create a file named id_rsa-cert.pub that contains the user certificate with the specified options⁴.

Source: Conversation with Bing, 5/3/2023
(1) How to configure and setup SSH certificates for SSH authentication. https://dev.to/gvelrajan/how-to-configure-and-setup-ssh-certificates-for-ssh-authentication-b52.
(2) How to configure SSH Certificates And User Principals - CottonLinux. https://cottonlinux.com/ssh-certificates/.
(3) 14.3.5. Creating SSH Certificates - Red Hat Customer Portal. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-signing_ssh_certificates.
(4) How do I specify the key exchange method in OpenSSH?. https://superuser.com/questions/744816/how-do-i-specify-the-key-exchange-method-in-openssh.
(5) Get self signed certificate of remote server - Stack Overflow. https://stackoverflow.com/questions/9072376/configure-git-to-accept-a-particular-self-signed-server-certificate-for-a-partic.
(6) How to configure SSH Certificate-Based Authentication - goteleport.com. https://goteleport.com/blog/how-to-configure-ssh-certificate-based-authentication/.

Certificate Authority

WIP

Host Certificates

WIP

Client Certificates

WIP

Congrats

⭐ you did it!

See Also

Github has a guide for creating, using, and adding ssh keys. I suggest you read that if you want to know more or add your keys to github.
Ledger's guide to TPM2 on Debian is really good and provided a lot of information on how to do TPM ssh
Pandasauce guide on smart cards