Add optional PGPKey-wide passphrase caching
authorW. Trevor King <wking@tremily.us>
Sun, 22 Dec 2013 22:04:22 +0000 (14:04 -0800)
committerW. Trevor King <wking@tremily.us>
Mon, 23 Dec 2013 21:41:06 +0000 (13:41 -0800)
Entering your passphrase for each secret key packet is annoying.  The
cache_passphrase option lets you cache that passphrase once, and reuse
it for every secret key PGPPacket in the key.

gpg-migrate.py

index 42905513c9236db2330977908e899e4846259300..de00b49d16dc92b5ec7d650d4767578ba9ff1855 100755 (executable)
@@ -927,9 +927,14 @@ class PGPPacket (dict):
         padding = segment_size_bytes - len(data) % segment_size_bytes
         if padding:
             data += b'\x00' * padding
         padding = segment_size_bytes - len(data) % segment_size_bytes
         if padding:
             data += b'\x00' * padding
-        passphrase = _getpass.getpass(
-            'passphrase for {}: '.format(self['fingerprint'][-8:]))
-        passphrase = passphrase.encode('ascii')
+        if self.key and self.key._cache_passphrase and self.key._passphrase:
+            passphrase = self.key._passphrase
+        else:
+            passphrase = _getpass.getpass(
+                'passphrase for {}: '.format(self['fingerprint'][-8:]))
+            passphrase = passphrase.encode('ascii')
+            if self.key and self.key._cache_passphrase:
+                self.key._passphrase = passphrase
         key = self._string_to_key(string=passphrase, key_size=key_size)
         cipher = module.new(
             key=key,
         key = self._string_to_key(string=passphrase, key_size=key_size)
         cipher = module.new(
             key=key,
@@ -978,8 +983,10 @@ class PGPKey (object):
     [1]: http://tools.ietf.org/search/rfc4880#section-11.1
     [2]: http://tools.ietf.org/search/rfc4880#section-11.2
     """
     [1]: http://tools.ietf.org/search/rfc4880#section-11.1
     [2]: http://tools.ietf.org/search/rfc4880#section-11.2
     """
-    def __init__(self, fingerprint):
+    def __init__(self, fingerprint, cache_passphrase=False):
         self.fingerprint = fingerprint
         self.fingerprint = fingerprint
+        self._cache_passphrase = cache_passphrase
+        self._passphrase = None
         self.public_packets = None
         self.secret_packets = None
 
         self.public_packets = None
         self.secret_packets = None
 
@@ -1032,16 +1039,16 @@ class PGPKey (object):
         pass
 
 
         pass
 
 
-def migrate(old_key, new_key):
+def migrate(old_key, new_key, cache_passphrase=False):
     """Add the old key and sub-keys to the new key
 
     For example, to upgrade your master key, while preserving old
     signatures you'd made.  You will lose signature *on* your old key
     though, since sub-keys can't be signed (I don't think).
     """
     """Add the old key and sub-keys to the new key
 
     For example, to upgrade your master key, while preserving old
     signatures you'd made.  You will lose signature *on* your old key
     though, since sub-keys can't be signed (I don't think).
     """
-    old_key = PGPKey(fingerprint=old_key)
+    old_key = PGPKey(fingerprint=old_key, cache_passphrase=cache_passphrase)
     old_key.import_from_gpg()
     old_key.import_from_gpg()
-    new_key = PGPKey(fingerprint=new_key)
+    new_key = PGPKey(fingerprint=new_key, cache_passphrase=cache_passphrase)
     new_key.import_from_gpg()
     new_key.import_from_key(key=old_key)
 
     new_key.import_from_gpg()
     new_key.import_from_key(key=old_key)
 
@@ -1053,4 +1060,4 @@ if __name__ == '__main__':
     import sys as _sys
 
     old_key, new_key = _sys.argv[1:3]
     import sys as _sys
 
     old_key, new_key = _sys.argv[1:3]
-    migrate(old_key=old_key, new_key=new_key)
+    migrate(old_key=old_key, new_key=new_key, cache_passphrase=True)