Signing Documents With SSH Key

It turns out you can use openssh keys to sign and verify files and documents.

The sender needs to do this:

  • Create a file /tmp/whatever with the text to verify, then sign it with:
openssl dgst -sha512 -sign ~/.ssh/id_rsa /tmp/whatever > /tmp/whatever.sig
  • Then base64-encode the sig and the whatever file:
base64 /tmp/whatever >/tmp/whatever.b64
base64 /tmp/whatever.sig >/tmp/whatever.sig.b64

generate checksums: sha512sum whatever* > checksums

And send the whatever.b64, whatever.sig.b64, and checksums files.

The checksum files allow verification that the content didn’t get mangled, because it’s easy for it to get borked in transit and this technique doesn’t provide a lot of integrity validation like e.g. GPG would.

Then the verifier does:

  • Obtain the ssh key in question. I use this technique with Launchpad public keys, so this works:
curl | grep "" > /tmp/
  • Convert the key to an openssl-compatible key:
ssh-keygen -e -f /tmp/ -m pkcs8 > /tmp/
  • Finally verify the documents (which you previously integrity-checked using sha512sum and the checksums file you received):
openssl dgst -sha512 -verify /tmp/ -signature /tmp/whatever.sig

A single script to demo the technique against my public Launchpad key:

KEY_IDENTIFIER="name of the key"

mkdir ssh-attestation
pushd ssh-attestation

# Signing procedure
echo "This is me" > attest
openssl dgst -sha512 -sign $KEY_ON_DISK attest > attest.sig
base64 attest > attest.b64
base64 attest.sig > attest.sig.b64
sha512sum attest* > shasums

# Verification procedure
echo "Verifying"
sha512sum -c shasums
# Brittle - maybe select by line number instead?
curl "$LAUNCHPAD_USER/+sshkeys" | grep "$KEY_IDENTIFIER" | grep -v "$KEY_EXCLUDER" >
ssh-keygen -e -f -m pkcs8 >
openssl dgst -sha512 -verify -signature attest.sig attest