vincenthz / hs-cipher-aes

DEPRECATED - use cryptonite - a comprehensive fast AES implementation for haskell that supports aesni and advanced cryptographic modes.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CTR mode is not idempotent (breaks referential transparency)

matthewleon opened this issue · comments

Every time I run CTR encryption in GHCi, I get a different output...

*Main> encryptCTR (initAES ("YELLOW SUBMARINE" :: ByteString)) ("" :: ByteString) "something"
"\206\174\US\210v%@\188\DEL"
*Main> encryptCTR (initAES ("YELLOW SUBMARINE" :: ByteString)) ("" :: ByteString) "something"
"\210\142\144\179\DC3|M\\\132"
*Main> encryptCTR (initAES ("YELLOW SUBMARINE" :: ByteString)) ("" :: ByteString) "something"
"V\215\DEL\137\193\227f\235\226"

The problem seems to be in keystream generation:

*Main> genCTR (initAES ("YELLOW SUBMARINE" :: ByteString)) ("" :: ByteString) 32
"\152X\254\176\238\135\194\b@\150c\US\149\234\242\SI!R\255\SOH\253\208\182\170\176J\218s\ETX\239\161\191"
*Main> genCTR (initAES ("YELLOW SUBMARINE" :: ByteString)) ("" :: ByteString) 32
"\247\165\EOT\184\156\182\234\152\SO\222\225\244j\197C\207W\136\210\133Aa\166B\226\215ZB;\145\NUL{"

an AES IV is 16 bytes, and you're giving a 0 bytes IV. so basically it used random piece of memory, which is why you got random output. use crypto-cipher-types:

ctrCombine :: cipher -> IV cipher -> ByteString -> ByteString

which doesn't allow this.

Hi Vincent. I appreciate the clarification. Nevertheless, it seems to me that this still is something that shouldn't happen in safe code. Either an error should be thrown or the type signature for the CTR functions should be tightened, no?