Tools · Cryptography and passwords in practice · 15 / 20
Digital signatures with Ed25519: sign, verify, and publish a public key
Create Ed25519 signatures in Python and with ssh-keygen, verify them, and understand what a signature proves and how to distribute the public key safely.
What a signature proves
A valid signature shows that the holder of a specific private key signed exactly these bytes. It provides integrity and origin, and, if the private key is well protected, non-repudiation. It says nothing about whether the content is good, and it is only meaningful if you trust that the public key belongs to the claimed signer.
Ed25519 is a modern signature scheme with small keys and signatures (32 and 64 bytes), deterministic signing that avoids random-number failures, and fast verification.
In Python
Serialize the public key to share it, keep the private key in a protected file or KMS, and verify by catching InvalidSignature.
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
from cryptography.exceptions import InvalidSignature
priv = Ed25519PrivateKey.generate()
pub_pem = priv.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo)
message = open('release.tar.gz', 'rb').read()
sig = priv.sign(message)
pub = serialization.load_pem_public_key(pub_pem)
try:
pub.verify(sig, message)
print('valid')
pub.verify(sig, message + b'x')
except InvalidSignature:
print('invalid after change')Lab: sign files with SSH keys
OpenSSH can sign arbitrary files with ssh-keygen -Y. Create an allowed_signers file mapping an identity to your public key, sign a file, verify it, then modify the file and verify again. Git can use the same mechanism to sign commits with gpg.format ssh.
ssh-keygen -t ed25519 -f lab_sign -N '' -C 'lab signer' echo "lab@example.org $(cat lab_sign.pub)" > allowed_signers ssh-keygen -Y sign -f lab_sign -n file release.tar.gz # writes release.tar.gz.sig ssh-keygen -Y verify -f allowed_signers -I lab@example.org -n file -s release.tar.gz.sig < release.tar.gz git config gpg.format ssh && git config user.signingkey ~/lab_sign.pub && git commit -S -m 'signed lab commit'
Distributing the public key
Publish the public key or its fingerprint in several independent places: your website, repository README, and a profile on a code hosting site. Users who compare at least two sources make it much harder for an attacker to substitute a key.
Diagram
Signature valid versus signature meaningful
Math and trust are separate questions.
Shows. The matching private key signed these exact bytes
Requires. The public key and signature
Does not show. Who owns the key
Shows. The expected person or project signed it
Requires. A public key obtained and verified independently
Adds. Trust in the key’s identity
Check yourself
1. What does a valid Ed25519 signature prove?
2. Which command verifies a file signed with ssh-keygen -Y sign?
3. Why does Ed25519 avoid a class of failures seen in some ECDSA implementations?