1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
#!/usr/bin/python3
# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
# this script generates a set of static objects for the sopv test suite:
# - expired.cert: minimal expired OpenPGP signing-capable certificate
# - valid-from-expired.sig: signature over `msg.binary` from setup-sopv-test,
# made within cert validity window
# - invalid-from-expired.sig: signature over `msg.binary` from setup-sopv-test,
# made after cert validity window
# - timetravel-from-expired.sig: signature over `msg.binary` from setup-sopv-test,
# made before cert validity window
# - baseline.cert: certificate that will be revoked
# - baseline.sig: signature over `msg.binary` from setup-sopv-test
# - baseline-revoked.cert: baseline certificate, with revocation
# Their output ends up embedded statically in setup-sopv-test.
# License: CC0
from typing import Set, Union, Optional
from pgpy import PGPKey, PGPUID, PGPMessage
from pgpy.constants import KeyFlags, PubKeyAlgorithm, EllipticCurveOID, SignatureType
from datetime import datetime, timezone, timedelta
start = datetime(2020, 1, 1, tzinfo=timezone.utc)
pkey = PGPKey.new(PubKeyAlgorithm.EdDSA, EllipticCurveOID.Ed25519, created=start)
uid = PGPUID.new('this cert is expired')
pkey.add_uid(uid,
usage=set([KeyFlags.Certify, KeyFlags.Sign]),
key_expiration=timedelta(365.25*3),
features=set(), # signing-only, no need for feature advertisement
created=start)
print(f"cat > expired.cert <<EOF\n{pkey.pubkey}EOF\n")
# This is the same as msg.binary generated from setup-sopv-test
msg = bytes(range(0,0x61)) + \
'SOPV is the Stateless OpenPGP Verification Subset♥'.encode() + \
bytes(range(0x61,0x100))
insig = pkey.sign(msg, created=start+timedelta(365.25*2))
print(f"cat > valid-from-expired.sig <<EOF\n{insig}EOF\n")
aftersig = pkey.sign(msg, created=start+timedelta(365.25*4))
print(f"cat > invalid-from-expired.sig <<EOF\n{aftersig}EOF\n")
beforesig = pkey.sign(msg, created=start-timedelta(365.25*1))
print(f"cat > timetravel-from-expired-sig <<EOF\n{beforesig}EOF\n")
bkey = PGPKey.new(PubKeyAlgorithm.EdDSA, EllipticCurveOID.Ed25519, created=start)
uid = PGPUID.new('baseline certificate, will be revoked')
bkey.add_uid(uid,
usage=set([KeyFlags.Certify, KeyFlags.Sign]),
features=set(), # signing-only, no need for feature advertisement
created=start)
print(f"cat > baseline.cert <<EOF\n{bkey.pubkey}EOF\n")
bsig = bkey.sign(msg, creaed=start+timedelta(365.25*1))
print(f"cat > baseline.sig <<EOF\n{bsig}EOF\n")
revsig = bkey.revoke(bkey,
sigtype=SignatureType.KeyRevocation,
created=start+timedelta(365.25*2))
bkey |= revsig
print(f"cat > baseline-revoked.cert <<EOF\n{bkey.pubkey}EOF\n")
|