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

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 [email protected] 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 [email protected]
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 [email protected] [email protected]
# Jump from jumpbox to jumpbox2 to jumpbox3 to destination
ssh -J [email protected],[email protected],[email protected] [email protected]

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 [email protected] -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.

[email protected] [email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPEroRTKtLMu9EXxFXXNm8bzA1w/c4v7gFKeFPXmHII1AAAABHNzaDo= Yubikey 5
[email protected] 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

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