gpg: demo for subkeys decoding

This commit is contained in:
Roman Zeyde 2016-04-26 15:30:18 +03:00
parent d9862ae0e1
commit 9875c9927e
2 changed files with 62 additions and 1 deletions

View 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()

View File

@ -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()