gpg: demo for subkeys decoding
This commit is contained in:
parent
d9862ae0e1
commit
9875c9927e
46
trezor_agent/gpg/debug_subkeys.py
Normal file
46
trezor_agent/gpg/debug_subkeys.py
Normal file
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
"""Check GPG v2 signature for a given public key."""
|
||||
import argparse
|
||||
import base64
|
||||
import io
|
||||
import logging
|
||||
import pprint
|
||||
|
||||
from . import decode
|
||||
from .. import util
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('pubkey')
|
||||
p.add_argument('-v', '--verbose', action='store_true', default=False)
|
||||
args = p.parse_args()
|
||||
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO,
|
||||
format='%(asctime)s %(levelname)-10s %(message)s')
|
||||
stream = open(args.pubkey, 'rb')
|
||||
parser = decode.Parser(util.Reader(stream))
|
||||
pubkey, userid, sig1, subkey, sig2 = parser
|
||||
|
||||
digest = decode.digest_packets([pubkey, userid, sig1])
|
||||
assert sig1['hash_prefix'] == digest[:2]
|
||||
decode.verify_digest(
|
||||
pubkey=pubkey, digest=digest,
|
||||
signature=sig1['sig'], label='GPG public key (self sig)')
|
||||
|
||||
digest = decode.digest_packets([pubkey, subkey, sig2])
|
||||
assert sig2['hash_prefix'] == digest[:2]
|
||||
decode.verify_digest(
|
||||
pubkey=pubkey, digest=digest,
|
||||
signature=sig2['sig'], label='GPG subkey (1st sig)')
|
||||
|
||||
sig3, = sig2['embedded']
|
||||
digest = decode.digest_packets([pubkey, subkey, sig3])
|
||||
decode.verify_digest(
|
||||
pubkey=subkey, digest=digest,
|
||||
signature=sig3['sig'], label='GPG subkey (2nd sig)')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -103,6 +103,15 @@ class Parser(object):
|
||||
p['_to_hash'] = p['content']
|
||||
return p
|
||||
|
||||
def _embedded_signatures(self, subpackets):
|
||||
for packet in subpackets:
|
||||
data = bytearray(packet)
|
||||
if data[0] == 32:
|
||||
# https://tools.ietf.org/html/rfc4880#section-5.2.3.26
|
||||
stream = io.BytesIO(data[1:])
|
||||
yield self.signature(util.Reader(stream))
|
||||
|
||||
|
||||
def signature(self, stream):
|
||||
"""See https://tools.ietf.org/html/rfc4880#section-5.2 for details."""
|
||||
p = {'type': 'signature'}
|
||||
@ -121,6 +130,10 @@ class Parser(object):
|
||||
p['_to_hash'] = to_hash.getvalue() + tail_to_hash
|
||||
|
||||
p['unhashed_subpackets'] = parse_subpackets(stream)
|
||||
embedded = list(self._embedded_signatures(p['unhashed_subpackets']))
|
||||
if embedded:
|
||||
p['embedded'] = embedded
|
||||
|
||||
p['hash_prefix'] = stream.readfmt('2s')
|
||||
p['sig'] = (parse_mpi(stream), parse_mpi(stream))
|
||||
assert not stream.read()
|
||||
@ -174,7 +187,9 @@ class Parser(object):
|
||||
mpi = parse_mpi(stream)
|
||||
log.debug('mpi: %x (%d bits)', mpi, mpi.bit_length())
|
||||
p['verifier'] = parser(mpi)
|
||||
p['leftover'] = stream.read() # TBD: what is this?
|
||||
leftover = stream.read() # TBD: what is this?
|
||||
if leftover:
|
||||
log.warning('unexpected subkey leftover: %r', leftover)
|
||||
|
||||
# https://tools.ietf.org/html/rfc4880#section-12.2
|
||||
packet_data = packet.getvalue()
|
||||
|
Loading…
Reference in New Issue
Block a user