git-annex/doc/bugs/encryption_key_is_surprising.mdwn
Joey Hess 89f973a6bd cloe
2013-03-03 20:50:03 -04:00

24 lines
1.7 KiB
Markdown

Crypto.hs seems to imply that the cipher key it's acting upon is 512 bytes long. Because of a probable programming mistake the key that's actually used is a bit surprising. The random key is generated by this snippet in Utility/Gpg.hs:
{- Creates a block of high-quality random data suitable to use as a cipher.
- It is armored, to avoid newlines, since gpg only reads ciphers up to the
- first newline. -}
genRandom :: Int -> IO String
genRandom size = readStrict
[ Params "--gen-random --armor"
, Param $ show randomquality
, Param $ show size
]
where
-- 1 is /dev/urandom; 2 is /dev/random
randomquality = 1 :: Int
This lets GPG generate the randomness and by passing armor, it avoids newlines. However, this base64 encoding is never undone on the way to Crypto.hs. Hence what cipherPassphrase and cipherHmac do is dropping or skipping the first 256 bytes of the base64 value. Base64, with its 6 bit per byte encoding, causes the Hmac function to operate on 192 bytes instead of 256 bytes. The key used by GPG will be larger. Some assertions that the resulting functions really operate on strings of the right length would've been helpful. Also GPG and HMAC get tested, the encryption/decryption part are not tested AFAICS.
The encryption wiki page could have had more information. Enough code (sadly in Python, not reusing the Haskell code) to operate on the resulting files can be found in [this Gist](https://gist.github.com/pkern/5078559).
-- Philipp Kern
> In addition to the comment below, I have added a check that gpg outputs
> the expected quantity of data, and the storage of the cipher is now
> documented in [[internals]]. Think I can call this [[done]]. --[[Joey]]