Add PGPPacket._str_generic_key_packet and fingerprint calculation
authorW. Trevor King <wking@tremily.us>
Fri, 20 Dec 2013 19:54:13 +0000 (11:54 -0800)
committerW. Trevor King <wking@tremily.us>
Fri, 20 Dec 2013 23:18:13 +0000 (15:18 -0800)
From RFC 4880 [1]:

  A V4 fingerprint is the 160-bit SHA-1 hash of the octet 0x99,
  followed by the two-octet packet length, followed by the entire
  Public-Key packet starting with the version field.  The Key ID is
  the low-order 64 bits of the fingerprint.

Since all key types (public/private and primary/subkey) have the same
generic public key portion, we can use the same stringification method
for all types.

[1]: http://tools.ietf.org/search/rfc4880#section-12.2

gpg-migrate.py

index 5b9ef10f5e2cada317096032b66201c7af4c032e..a2519f8b8355d4a3d0dd6041790867bdd0c41e08 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+import hashlib as _hashlib
 import re as _re
 import subprocess as _subprocess
 import struct as _struct
@@ -198,6 +199,21 @@ class PGPPacket (dict):
         details = method()
         return '{}: {}'.format(self['type'], details)
 
+    def _str_public_key_packet(self):
+        return self._str_generic_key_packet()
+
+    def _str_public_subkey_packet(self):
+        return self._str_generic_key_packet()
+
+    def _str_secret_key_packet(self):
+        return self._str_generic_key_packet()
+
+    def _str_secret_subkey_packet(self):
+        return self._str_generic_key_packet()
+
+    def _str_generic_key_packet(self):
+        return self['fingerprint'][-8:].upper()
+
     def _str_user_id_packet(self):
         return self['user']
 
@@ -337,6 +353,11 @@ class PGPPacket (dict):
             raise NotImplementedError(
                 'algorithm-specific key fields for {}'.format(
                     self['public-key-algorithm']))
+        fingerprint = _hashlib.sha1()
+        fingerprint.update(b'\x99')
+        fingerprint.update(_struct.pack('>H', len(data)))
+        fingerprint.update(data)
+        self['fingerprint'] = fingerprint.hexdigest()
         return offset
 
     def _parse_secret_key_packet(self, data):