AES.hs (2281B)
1 module Cryptopals.AES ( 2 encryptCbcAES128 3 , encryptEcbAES128 4 5 , decryptCbcAES128 6 , decryptEcbAES128 7 8 , encryptCtrAES128 9 , decryptCtrAES128 10 ) where 11 12 import qualified Crypto.Cipher.AES as CAES 13 import qualified Crypto.Cipher.Types as CT 14 import qualified Crypto.Error as CE 15 import qualified Cryptopals.Util as CU 16 import qualified Data.Binary.Get as BG 17 import qualified Data.Binary.Put as BP 18 import qualified Data.ByteString as BS 19 import qualified Data.ByteString.Lazy as BSL 20 import GHC.Word (Word64) 21 22 initAES128 :: BS.ByteString -> CAES.AES128 23 initAES128 = CE.throwCryptoError . CT.cipherInit 24 25 encryptEcbAES128 :: BS.ByteString -> BS.ByteString -> BS.ByteString 26 encryptEcbAES128 key = CT.ecbEncrypt (initAES128 key) 27 28 decryptEcbAES128 :: BS.ByteString -> BS.ByteString -> BS.ByteString 29 decryptEcbAES128 key = CT.ecbDecrypt (initAES128 key) 30 31 encryptCbcAES128 32 :: BS.ByteString -> BS.ByteString -> BS.ByteString -> BS.ByteString 33 encryptCbcAES128 iv key plaintext = loop iv iv (BS.splitAt 16 plaintext) 34 where 35 loop las !acc (b, bs) = 36 let xed = CU.fixedXor las b 37 enc = encryptEcbAES128 key xed 38 nacc = acc <> enc 39 in if BS.null bs 40 then nacc 41 else loop enc nacc (BS.splitAt 16 bs) 42 43 decryptCbcAES128 44 :: BS.ByteString -> BS.ByteString -> BS.ByteString 45 decryptCbcAES128 key ciphertext = 46 let (iv, cip) = BS.splitAt 16 ciphertext 47 in loop iv mempty (BS.splitAt 16 cip) 48 where 49 loop !las !acc (b, bs) = 50 let dec = decryptEcbAES128 key b 51 nacc = acc <> CU.fixedXor dec las 52 niv = b 53 in if BS.null bs 54 then nacc 55 else loop b nacc (BS.splitAt 16 bs) 56 57 encryptCtrAES128 :: Word64 -> BS.ByteString -> BS.ByteString -> BS.ByteString 58 encryptCtrAES128 nonce key plaintext = loop mempty 0 bs where 59 bs = CU.chunks 16 plaintext 60 iv = BS.replicate 16 0 61 no = BP.runPut (BP.putWord64le nonce) 62 63 loop !acc !ctr cs = case cs of 64 [] -> acc 65 (h:t) -> 66 let bc = BP.runPut (BP.putWord64le ctr) 67 pt = BSL.toStrict (no <> bc) 68 ks = BS.drop 16 $ encryptCbcAES128 iv key pt 69 in loop (acc <> CU.fixedXor h ks) (ctr + 1) t 70 71 decryptCtrAES128 :: Word64 -> BS.ByteString -> BS.ByteString -> BS.ByteString 72 decryptCtrAES128 = encryptCtrAES128 73