Background: I'm writing a GPL Python OpenPGP to JSON parser which I'm testing on files generated with GPG 1.4.16.
If given a passphrase, the parser will generate keys using the string-to-key methods and ultimately decrypt messages.
I'm starting off with symmetric encryption messages:
echo "hello" | gpg --s2k-mode=0 --symmetric > symmetric.simples2k.gpg
... and using "foo" as the passphrase.
This generates a packet with a SymmetricKeyEncryptedSessionKeyPacket
and a SymmetricEncryptedandIntegrityProtectedDataPacket
packet, as expected.
The S2K paramters that GPG created are: Simple S2K (http://ift.tt/1ocZkzF) with SHA1 hash and AES256 symmetric cipher.
Problem: When I derive the key from the passphrase foo
using SimpleS2K then attempt to decrypt with AES256, it doesn't decrypt correctly. So part 1 of my investigation is verifying that I'm doing the S2K correctly.
Here's my understanding of how to generate the key from the passphrase foo
using SimpleS2K
- Create two SHA1 hashers (because AES256 needs 32-byte key, SHA1 produces 20-byte hash)
- Don't preload hashers[0]
- Update
hashers[1]
with 0x00
- Update
hashers[0]
with UTF-8 encoded foo
- Update
hashers[0]
with UTF-8 encoded foo
- Concatenate
hashers[0].digest
plus hashers[1].digest
- Take first 32 bytes of result (ie drop last 8 bytes)
Here's a minimal implementation in Python 3:
import hashlib
hasher_0 = hashlib.sha1()
hasher_1 = hashlib.sha1()
hasher_1.update(bytes([0x0]))
hasher_0.update('foo'.encode('utf-8'))
hasher_1.update('foo'.encode('utf-8'))
key = (hasher_0.digest() + hasher_1.digest())[0:32]
print(' '.join(['{:02x}'.format(x) for x in key]))
Which outputs
0b ee c7 b5 ea 3f 0f db c9 5d 0d d4 7f 3c 5b c2 75 da 8a 33 5a 8c aa 40 39 fd bc 02 c0 1a 64 9c
The full JSON output is here: http://ift.tt/1IDM8Au
Hopefully we can rule out the S2K part and get onto the AES part :)
Thanks!