From: W. Trevor King Date: Sun, 22 Dec 2013 00:43:35 +0000 (-0800) Subject: Add iterated-and-salted string-to-key support to PGPPacket._string_to_key X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=a9034f3bbe7f86913a5f24de59814cf5c8585365;p=gpg-migrate.git Add iterated-and-salted string-to-key support to PGPPacket._string_to_key From RFC 4880 [1]: Iterated-Salted S2K hashes the passphrase and salt data multiple times. The total number of octets to be hashed is specified in the encoded count in the S2K specifier. Note that the resulting count value is an octet count of how many octets will be hashed, not an iteration count. Initially, one or more hash contexts are set up as with the other S2K algorithms, depending on how many octets of key data are needed. Then the salt, followed by the passphrase data, is repeatedly hashed until the number of octets specified by the octet count has been hashed. The one exception is that if the octet count is less than the size of the salt plus passphrase, the full salt plus passphrase will be hashed even though that is greater than the octet count. After the hashing is done, the data is unloaded from the hash context(s) as with the other S2K algorithms. [1]: http://tools.ietf.org/search/rfc4880#section-3.7.1.3 --- diff --git a/gpg-migrate.py b/gpg-migrate.py index b5050da..1dba898 100755 --- a/gpg-migrate.py +++ b/gpg-migrate.py @@ -878,8 +878,15 @@ class PGPPacket (dict): key = b'' if self['string-to-key-type'] == 'simple': update_bytes = string - elif self['string-to-key-type'] == 'salted': + elif self['string-to-key-type'] in [ + 'salted', + 'iterated and salted', + ]: update_bytes = self['string-to-key-salt'] + string + if self['string-to-key-type'] == 'iterated and salted': + count = self['string-to-key-count'] + if count < len(update_bytes): + count = len(update_bytes) else: raise NotImplementedError( 'key calculation for string-to-key type {}'.format( @@ -892,6 +899,11 @@ class PGPPacket (dict): 'salted', ]: string_hash.update(update_bytes) + elif self['string-to-key-type'] == 'iterated and salted': + remaining = count + while remaining > 0: + string_hash.update(update_bytes[:remaining]) + remaining -= len(update_bytes) key += string_hash.digest() key = key[:key_size_bytes] return key