Verify Signature Tutorial
Objective
In this tutorial, you will verify a signature against a list of allowed signing keys. You will see the distinction between merely checking a signature, as shown in the Check Signature Tutorial, and verifying a signature, as demonstrated in this tutorial.
Prerequisites
You need to install the sshsig
Python package.
A popular way to do this is by running:
pip install sshsig
This tutorial involves executing lines of Python code within a Python interpreter. A popular way to run the Python interpreter is to run:
python3
in the command line.
Steps
1. Get the message and plain-text encoded signature
To verify (or check) a signature, we need the message that was signed and its corresponding signature.
message = """\
tree 8d602ce92adf2a598552736e97f07e5b8ab2b0a8
parent 06b3e55161aae343d23453f7443904512599a513
author Castedo Ellerman <castedo@castedo.com> 1736017937 -0500
committer Castedo Ellerman <castedo@castedo.com> 1736017937 -0500
add py.typed marker
"""
This message is from a Git commit, as demonstrated in the
Check a Git Commit how-to guide
using the raw_without_sig()
function from
dulwich
.
This Git commit includes an identity in the form of a personal name
and email address.
signature = """\
-----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAghB1C63jrmh3eWRXJVbrTfw9wP/
BIZf/aKPdFxBlMCq0AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQMroG89bt34Civt2ftnKSDj/qpskASeCBHUfc8KQCUl1LAq4gAy4xQ1orAtiEaj5EM
yMvtlcxbEImHo4KtbOewA=
-----END SSH SIGNATURE-----
"""
2. Get and check the signing public key
We get the public key from the signature and check that it was used to sign the message.
import sshsig
pub_key = sshsig.check_signature(message, signature)
print(pub_key)
Although check_signature
confirms that the public key was used to sign the message,
it does not validate whether the person identified by name and email
address in the commit is the same person who holds the signing key and used it to
sign the message.
3. An allowed signers file
One of many possible forms of additional verification is to only accept signatures that are performed with a signing key listed in an allow list of acceptable public keys.
The utility ssh-keygen uses an "allowed signers" file as an allow list for signature verification. Git uses this utility to verify commits with SSH signatures.
The sshsig.allowed_signers
module supports a limited sub-format of the ssh-keygen
allowed
signers file format. This sub-format only supports lines starting with
* namespaces="git"
preceding public keys in OpenSSH format.
Below, we create such a file:
import io
file = io.StringIO(f"""\
* namespaces="git" {pub_key}
* namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlKQFTcI28lrqcq8goeL2p1cxdHhm4/reBgjKDp1Ise
""")
4. Load an allow list
Next, we get an allow list of public keys by loading the example file.
from sshsig.allowed_signers import load_allowed_signers_file, for_git_allowed_keys
allow_list = for_git_allowed_keys(load_allowed_signers_file(file))
print(*allow_list, sep="\n")
Note that in this example, we've included the public key found in the signature.
5. Verify the key in the allow list
Checking whether the returned public key is in the returned allow list is a trivial one-liner.
pub_key in allow_list
Alternatively, one can use the trivial helper function verify
to call
check_signature
and verify whether the returned public key is in the allow list.
pub_key = sshsig.verify(message, signature, allow_list)