cryptocipher 0.3.0 → 0.3.1
raw patch · 19 files changed
+2126/−1676 lines, 19 filesdep +cpudep +cryptocipherdep +entropydep −HUnitdep ~crypto-apidep ~vectorPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: cpu, cryptocipher, entropy, test-framework, test-framework-quickcheck2
Dependencies removed: HUnit
Dependency ranges changed: crypto-api, vector
API changes (from Hackage documentation)
- Crypto.Cipher.AES: data AES128
- Crypto.Cipher.AES: data AES192
- Crypto.Cipher.AES: data AES256
- Crypto.Cipher.AES: data Key
- Crypto.Cipher.AES: decrypt :: Key -> ByteString -> ByteString
- Crypto.Cipher.AES: decryptCBC :: Key -> IV -> ByteString -> ByteString
- Crypto.Cipher.AES: encrypt :: Key -> ByteString -> ByteString
- Crypto.Cipher.AES: encryptCBC :: Key -> IV -> ByteString -> ByteString
- Crypto.Cipher.AES: initKey128, initKey256, initKey192 :: ByteString -> Either String Key
- Crypto.Cipher.AES: instance BlockCipher AES128
- Crypto.Cipher.AES: instance BlockCipher AES192
- Crypto.Cipher.AES: instance BlockCipher AES256
- Crypto.Cipher.AES: instance Eq Key
- Crypto.Cipher.AES: instance Serialize AES128
- Crypto.Cipher.AES: instance Serialize AES192
- Crypto.Cipher.AES: instance Serialize AES256
- Crypto.Cipher.AES: instance Show Key
- Crypto.Cipher.AES: type IV = ByteString
- Crypto.Cipher.Camellia: initKey :: ByteString -> Either String Key
+ Crypto.Cipher.AES.Haskell: data AES128
+ Crypto.Cipher.AES.Haskell: data AES192
+ Crypto.Cipher.AES.Haskell: data AES256
+ Crypto.Cipher.AES.Haskell: data Key
+ Crypto.Cipher.AES.Haskell: decrypt :: Key -> ByteString -> ByteString
+ Crypto.Cipher.AES.Haskell: decryptCBC :: Key -> IV -> ByteString -> ByteString
+ Crypto.Cipher.AES.Haskell: encrypt :: Key -> ByteString -> ByteString
+ Crypto.Cipher.AES.Haskell: encryptCBC :: Key -> IV -> ByteString -> ByteString
+ Crypto.Cipher.AES.Haskell: initKey128 :: ByteString -> Either String Key
+ Crypto.Cipher.AES.Haskell: initKey192 :: ByteString -> Either String Key
+ Crypto.Cipher.AES.Haskell: initKey256 :: ByteString -> Either String Key
+ Crypto.Cipher.AES.Haskell: instance BlockCipher AES128
+ Crypto.Cipher.AES.Haskell: instance BlockCipher AES192
+ Crypto.Cipher.AES.Haskell: instance BlockCipher AES256
+ Crypto.Cipher.AES.Haskell: instance Eq Key
+ Crypto.Cipher.AES.Haskell: instance Serialize AES128
+ Crypto.Cipher.AES.Haskell: instance Serialize AES192
+ Crypto.Cipher.AES.Haskell: instance Serialize AES256
+ Crypto.Cipher.AES.Haskell: instance Show Key
+ Crypto.Cipher.AES.Haskell: type IV = ByteString
+ Crypto.Cipher.Camellia: initKey128 :: ByteString -> Either String Key
Files
- Benchmarks.hs +0/−85
- Benchmarks/Benchmarks.hs +108/−0
- Crypto/Cipher/AES.hs +12/−1014
- Crypto/Cipher/AES/Haskell.hs +1014/−0
- Crypto/Cipher/AES/X86NI.hs +80/−0
- Crypto/Cipher/Camellia.hs +3/−3
- Crypto/Cipher/DH.hs +3/−3
- Crypto/Cipher/DSA.hs +2/−2
- Crypto/Cipher/RSA.hs +2/−2
- Number/ModArithmetic.hs +11/−0
- Number/Polynomial.hs +13/−2
- Number/Prime.hs +17/−3
- System/Endian.hs +0/−17
- Tests.hs +0/−518
- Tests/AES.hs +75/−0
- Tests/KAT.hs +241/−0
- Tests/tests.hs +321/−0
- cbits/aes/x86ni.c +191/−0
- cryptocipher.cabal +33/−27
− Benchmarks.hs
@@ -1,85 +0,0 @@-import Criterion-import Criterion.Environment-import Criterion.Config-import Criterion.Monad-import Criterion.Analysis-import Criterion.Measurement--import Text.Printf--import Control.Monad.Trans--import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as L--import qualified Crypto.Cipher.AES as AES-import qualified Crypto.Cipher.RC4 as RC4-import qualified Crypto.Cipher.Camellia as Camellia--(Right key128) = AES.initKey128 $ B.replicate 16 0-aesEncrypt128 = AES.encrypt key128-aesEncrypt128CBC = AES.encryptCBC key128 (B.replicate 16 0)-(Right key192) = AES.initKey192 $ B.replicate 24 0-aesEncrypt192 = AES.encrypt key192-aesEncrypt192CBC = AES.encryptCBC key192 (B.replicate 16 0)-(Right key256) = AES.initKey256 $ B.replicate 32 0-aesEncrypt256 = AES.encrypt key256-aesEncrypt256CBC = AES.encryptCBC key256 (B.replicate 16 0)--(Right camelliaKey128) = Camellia.initKey $ B.replicate 16 0-camelliaEncrypt128 = Camellia.encrypt camelliaKey128--rc4Key = RC4.initCtx $ replicate 16 0-rc4Encrypt = snd . RC4.encrypt rc4Key --b16 f = whnf f $ B.replicate 16 0-b32 f = whnf f $ B.replicate 32 0-b128 f = whnf f $ B.replicate 128 0-b512 f = whnf f $ B.replicate 512 0-b1024 f = whnf f $ B.replicate 1024 0-b4096 f = whnf f $ B.replicate 4096 0--doCipher env f = do- mean16 <- runBenchmark env (b16 f) >>= \sample -> analyseMean sample 100- mean32 <- runBenchmark env (b32 f) >>= \sample -> analyseMean sample 100- mean128 <- runBenchmark env (b128 f) >>= \sample -> analyseMean sample 100- mean512 <- runBenchmark env (b512 f) >>= \sample -> analyseMean sample 100- mean1024 <- runBenchmark env (b1024 f) >>= \sample -> analyseMean sample 100- mean4096 <- runBenchmark env (b4096 f) >>= \sample -> analyseMean sample 100- return (mean16, mean32, mean128, mean512, mean1024, mean4096)--norm :: Int -> Double -> Double-norm n time- | n < 1024 = 1.0 / (time * (1024 / fromIntegral n))- | n == 1024 = 1.0 / time- | n > 1024 = 1.0 / (time / (fromIntegral n / 1024))--pn :: Int -> Double -> String-pn n time = printf "%.1f K/s" (norm n time)--doOne env (cipherName, f) = do- (mean16, mean32, mean128, mean512, mean1024, mean4096) <- doCipher env f- let s = printf "%12s: %12s %12s %12s %12s %12s %12s\n %12s %12s %12s %12s %12s %12s"- cipherName- (secs mean16) (secs mean32) (secs mean128)- (secs mean512) (secs mean1024) (secs mean4096)- (pn 16 mean16) (pn 32 mean32) (pn 128 mean128)- (pn 512 mean512) (pn 1024 mean1024) (pn 4096 mean4096)- return s--main = withConfig defaultConfig $ do- env <- measureEnvironment- l <- mapM (doOne env)- [ ("RC4" , rc4Encrypt)- , ("Camellia128", camelliaEncrypt128)- , ("AES128" , aesEncrypt128)- , ("AES128-CBC" , aesEncrypt128CBC)- , ("AES192" , aesEncrypt192)- , ("AES192-CBC" , aesEncrypt192CBC)- , ("AES256" , aesEncrypt256)- , ("AES256-CBC" , aesEncrypt256CBC)- ]- liftIO $ printf "%12s| %12s %12s %12s %12s %12s %12s\n"- "cipher" "16 bytes" "32 bytes" "64 bytes" "512 bytes" "1024 bytes" "4096 bytes"- liftIO $ printf "=============================================================================================\n"- mapM_ (liftIO . putStrLn) l
+ Benchmarks/Benchmarks.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE CPP #-}+import Criterion+import Criterion.Environment+import Criterion.Config+import Criterion.Monad+import Criterion.Analysis+import Criterion.Measurement++import Text.Printf++import Control.Monad.Trans++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L++import qualified Crypto.Cipher.AES.Haskell as AES+#ifdef HAVE_AESNI+import qualified Crypto.Cipher.AES.X86NI as AESNI+#endif+import qualified Crypto.Cipher.RC4 as RC4+import qualified Crypto.Cipher.Camellia as Camellia++import Crypto.Classes+import qualified Crypto.Modes as CAPI++(Right key128) = AES.initKey128 $ B.replicate 16 0+aesEncrypt128 = AES.encrypt key128+aesEncrypt128CBC = AES.encryptCBC key128 (B.replicate 16 0)++(Right key192) = AES.initKey192 $ B.replicate 24 0+aesEncrypt192 = AES.encrypt key192+aesEncrypt192CBC = AES.encryptCBC key192 (B.replicate 16 0)+(Right key256) = AES.initKey256 $ B.replicate 32 0+aesEncrypt256 = AES.encrypt key256+aesEncrypt256CBC = AES.encryptCBC key256 (B.replicate 16 0)++(Just capi_key128) = buildKey (B.replicate 16 0) :: Maybe AES.AES128+aesEncrypt128CBC_capi = fst . CAPI.cbc' capi_key128 CAPI.zeroIV++#ifdef HAVE_AESNI+key128_ni = AESNI.initKey128 $ B.replicate 16 0+aesniEncrypt128 = AESNI.encrypt key128_ni++aesniEncrypt128CBC = AESNI.encryptCBC key128_ni (B.replicate 16 0)+#endif++(Right camelliaKey128) = Camellia.initKey128 $ B.replicate 16 0+camelliaEncrypt128 = Camellia.encrypt camelliaKey128++rc4Key = RC4.initCtx $ replicate 16 0+rc4Encrypt = snd . RC4.encrypt rc4Key ++b16 f = whnf f $ B.replicate 16 0+b32 f = whnf f $ B.replicate 32 0+b128 f = whnf f $ B.replicate 128 0+b512 f = whnf f $ B.replicate 512 0+b1024 f = whnf f $ B.replicate 1024 0+b4096 f = whnf f $ B.replicate 4096 0++doCipher env f = do+ mean16 <- runBenchmark env (b16 f) >>= \sample -> analyseMean sample 100+ mean32 <- runBenchmark env (b32 f) >>= \sample -> analyseMean sample 100+ mean128 <- runBenchmark env (b128 f) >>= \sample -> analyseMean sample 100+ mean512 <- runBenchmark env (b512 f) >>= \sample -> analyseMean sample 100+ mean1024 <- runBenchmark env (b1024 f) >>= \sample -> analyseMean sample 100+ mean4096 <- runBenchmark env (b4096 f) >>= \sample -> analyseMean sample 100+ return (mean16, mean32, mean128, mean512, mean1024, mean4096)++norm :: Int -> Double -> Double+norm n time+ | n < 1024 = 1.0 / (time * (1024 / fromIntegral n))+ | n == 1024 = 1.0 / time+ | n > 1024 = 1.0 / (time / (fromIntegral n / 1024))++pn :: Int -> Double -> String+pn n time = printf "%.1f K/s" (norm n time)++doOne env (cipherName, f) = do+ (mean16, mean32, mean128, mean512, mean1024, mean4096) <- doCipher env f+ let s = printf "%12s: %12s %12s %12s %12s %12s %12s\n %12s %12s %12s %12s %12s %12s"+ cipherName+ (secs mean16) (secs mean32) (secs mean128)+ (secs mean512) (secs mean1024) (secs mean4096)+ (pn 16 mean16) (pn 32 mean32) (pn 128 mean128)+ (pn 512 mean512) (pn 1024 mean1024) (pn 4096 mean4096)+ return s++main = withConfig defaultConfig $ do+ env <- measureEnvironment+ l <- mapM (doOne env)+ [ ("RC4" , rc4Encrypt)+ , ("Camellia128", camelliaEncrypt128)+ , ("AES128" , aesEncrypt128)+ , ("AES128-CBC" , aesEncrypt128CBC)+#ifdef HAVE_AESNI+ , ("AES128-ni" , aesniEncrypt128)+ , ("AES128ni-CBC" , aesniEncrypt128CBC)+#endif+ -- , ("AES128-CBC-capi", aesEncrypt128CBC_capi)+ , ("AES192" , aesEncrypt192)+ , ("AES192-CBC" , aesEncrypt192CBC)+ , ("AES256" , aesEncrypt256)+ , ("AES256-CBC" , aesEncrypt256CBC)+ ]+ liftIO $ printf "%12s| %12s %12s %12s %12s %12s %12s\n"+ "cipher" "16 bytes" "32 bytes" "64 bytes" "512 bytes" "1024 bytes" "4096 bytes"+ liftIO $ printf "=============================================================================================\n"+ mapM_ (liftIO . putStrLn) l
Crypto/Cipher/AES.hs view
@@ -1,1014 +1,12 @@-{-# LANGUAGE BangPatterns, MagicHash #-}--- |--- Module : Crypto.Cipher.AES--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good--module Crypto.Cipher.AES- ( Key- , IV- -- * Basic encryption and decryption- , encrypt- , decrypt- -- * CBC encryption and decryption- , encryptCBC- , decryptCBC- -- * key building mechanism- , initKey128- , initKey192- , initKey256- -- * Wrappers for "crypto-api" instances- , AES128- , AES192- , AES256- ) where--import Data.Word-import Data.Vector.Unboxed (Vector)-import qualified Data.Vector.Unboxed as V-import Data.Bits-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Unsafe as B-import qualified Data.ByteString.Internal as B--import GHC.Prim (indexWord8OffAddr#, indexWord32OffAddr#, word2Int#, Addr#, remInt#)-import GHC.Word-import GHC.Types--import Foreign.Ptr-import Foreign.Storable--import Data.Tagged (Tagged(..))-import Crypto.Classes (BlockCipher(..))-import Data.Serialize (Serialize(..), getByteString, putByteString)--import Control.Monad (forM_)-import Control.Monad.Primitive--import Data.Primitive.ByteArray--import System.Endian (littleEndian)--newtype AES128 = A128 { unA128 :: Key }-newtype AES192 = A192 { unA192 :: Key }-newtype AES256 = A256 { unA256 :: Key }--instance BlockCipher AES128 where- blockSize = Tagged 128- encryptBlock = encrypt . unA128- decryptBlock = decrypt . unA128- buildKey b = either (const Nothing) (Just . A128) $ initKey128 b- keyLength = Tagged 128--instance BlockCipher AES192 where- blockSize = Tagged 128- encryptBlock = encrypt . unA192- decryptBlock = decrypt . unA192- buildKey b = either (const Nothing) (Just . A192) $ initKey192 b- keyLength = Tagged 192--instance BlockCipher AES256 where- blockSize = Tagged 128- encryptBlock = encrypt . unA256- decryptBlock = decrypt . unA256- buildKey b = either (const Nothing) (Just . A256) $ initKey256 b- keyLength = Tagged 256--serializeKey :: Key -> ByteString-serializeKey (Key v)- | V.length v == 176 = B.pack $ map (V.unsafeIndex v) [0..15]- | V.length v == 208 = B.pack $ map (V.unsafeIndex v) [0..23]- | otherwise = B.pack $ map (V.unsafeIndex v) [0..31]--instance Serialize AES128 where- put = putByteString . serializeKey . unA128- get = do- raw <- getByteString (128 `div` 8)- case buildKey raw of- Nothing -> fail "Invalid raw key material."- Just k -> return k--instance Serialize AES192 where- put = putByteString . serializeKey . unA192- get = do- raw <- getByteString (192 `div` 8)- case buildKey raw of- Nothing -> fail "Invalid raw key material."- Just k -> return k--instance Serialize AES256 where- put = putByteString . serializeKey . unA256- get = do- raw <- getByteString (256 `div` 8)- case buildKey raw of- Nothing -> fail "Invalid raw key material."- Just k -> return k--data Key = Key (Vector Word8)- deriving (Show,Eq)--type IV = B.ByteString--type AESState = MutableByteArray RealWorld--{- | encrypt using CBC mode- - IV need to be 16 bytes and the data to encrypt a multiple of 16 bytes -}-encryptCBC :: Key -> IV -> B.ByteString -> B.ByteString-encryptCBC key iv b- | B.length iv /= 16 = error "invalid IV length"- | B.length b `mod` 16 /= 0 = error "invalid data length"- | otherwise = B.concat $ encryptIter iv (makeChunks b)- where- encryptIter _ [] = []- encryptIter iv' (x:xs) =- let r = coreEncrypt key $ B.pack $ B.zipWith xor iv' x in- r : encryptIter r xs--{- | encrypt using simple EBC mode -}-encrypt :: Key -> B.ByteString -> B.ByteString-encrypt key b- | B.length b `mod` 16 /= 0 = error "invalid data length"- | otherwise = B.concat $ doChunks (coreEncrypt key) b--{- | decrypt using CBC mode- - IV need to be 16 bytes and the data to decrypt a multiple of 16 bytes -}-decryptCBC :: Key -> IV -> B.ByteString -> B.ByteString-decryptCBC key iv b- | B.length iv /= 16 = error "invalid IV length"- | B.length b `mod` 16 /= 0 = error "invalid data length"- | otherwise = B.concat $ decryptIter iv (makeChunks b)- where- decryptIter _ [] = []- decryptIter iv' (x:xs) =- let r = B.pack $ B.zipWith xor iv' $ coreDecrypt key x in- r : decryptIter x xs--{- | decrypt using simple EBC mode -}-decrypt :: Key -> B.ByteString -> B.ByteString-decrypt key b- | B.length b `mod` 16 /= 0 = error "invalid data length"- | otherwise = B.concat $ doChunks (coreDecrypt key) b--doChunks :: (B.ByteString -> B.ByteString) -> B.ByteString -> [B.ByteString]-doChunks f b =- let (x, rest) = B.splitAt 16 b in- if B.length rest >= 16- then f x : doChunks f rest- else [ f x ]--makeChunks :: B.ByteString -> [B.ByteString]-makeChunks = doChunks id--newAESState :: IO AESState-newAESState = newAlignedPinnedByteArray 16 16--coreEncrypt :: Key -> ByteString -> ByteString-coreEncrypt key input = B.unsafeCreate (B.length input) $ \ptr -> do- st <- newAESState- swapBlock input st- aesMain (getNbr key) key st- swapBlockInv st ptr--coreDecrypt :: Key -> ByteString -> ByteString-coreDecrypt key input = B.unsafeCreate (B.length input) $ \ptr -> do- st <- newAESState- swapBlock input st- aesMainInv (getNbr key) key st- swapBlockInv st ptr--getNbr :: Key -> Int-getNbr (Key v)- | V.length v == 176 = 10- | V.length v == 208 = 12- | otherwise = 14--initKey128, initKey192, initKey256 :: ByteString -> Either String Key--initKey128 = initKey 16-initKey192 = initKey 24-initKey256 = initKey 32--initKey :: Int -> ByteString -> Either String Key-initKey sz b- | B.length b == sz = Right $ coreExpandKey (V.generate sz $ B.unsafeIndex b)- | otherwise = Left "wrong key size"--aesMain :: Int -> Key -> AESState -> IO ()-aesMain nbr key blk = do- addRoundKey key 0 blk- forM_ [1..nbr-1] $ \i -> do- shiftRows blk >> mixColumns blk >> addRoundKey key i blk- shiftRows blk >> addRoundKey key nbr blk--aesMainInv :: Int -> Key -> AESState -> IO ()-aesMainInv nbr key blk = do- addRoundKey key nbr blk- forM_ (reverse [1..nbr-1]) $ \i -> do- shiftRowsInv blk >> addRoundKey key i blk >> mixColumnsInv blk- shiftRowsInv blk >> addRoundKey key 0 blk--{-# INLINE swapIndex #-}-swapIndex :: Int -> Int-swapIndex 0 = 0-swapIndex 1 = 4-swapIndex 2 = 8-swapIndex 3 = 12-swapIndex 4 = 1-swapIndex 5 = 5-swapIndex 6 = 9-swapIndex 7 = 13-swapIndex 8 = 2-swapIndex 9 = 6-swapIndex 10 = 10-swapIndex 11 = 14-swapIndex 12 = 3-swapIndex 13 = 7-swapIndex 14 = 11-swapIndex 15 = 15-swapIndex _ = 0--coreExpandKey :: Vector Word8 -> Key-coreExpandKey vkey- | V.length vkey == 16 = Key (V.concat (ek0 : ekN16))- | V.length vkey == 24 = Key (V.concat (ek0 : ekN24))- | V.length vkey == 32 = Key (V.concat (ek0 : ekN32))- | otherwise = Key (V.empty)- where- ek0 = vkey- ekN16 = reverse $ snd $ foldl (generateFold generate16) (ek0, []) [1..10]-- ekN24 =- let (lk, acc) = foldl (generateFold generate24) (ek0, []) [1..7] in- let nk = generate16 lk 8 in- reverse (nk : acc)-- ekN32 =- let (lk, acc) = foldl (generateFold generate32) (ek0, []) [1..6] in- let nk = generate16 lk 7 in- reverse (nk : acc)-- generateFold gen (prevk, accK) it = let nk = gen prevk it in (nk, nk : accK)-- generate16 prevk it =- let len = V.length prevk in- let v0 = cR0 it (V.unsafeIndex prevk $ len - 4)- (V.unsafeIndex prevk $ len - 3)- (V.unsafeIndex prevk $ len - 2)- (V.unsafeIndex prevk $ len - 1) in- let eg0@(e0,e1,e2,e3) = xorVector prevk 0 v0 in- let eg1@(e4,e5,e6,e7) = xorVector prevk 4 eg0 in- let eg2@(e8,e9,e10,e11) = xorVector prevk 8 eg1 in- let (e12,e13,e14,e15) = xorVector prevk 12 eg2 in- V.fromList [e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15]-- generate24 prevk it =- let len = V.length prevk in- let v0 = cR0 it (V.unsafeIndex prevk $ len - 4)- (V.unsafeIndex prevk $ len - 3)- (V.unsafeIndex prevk $ len - 2)- (V.unsafeIndex prevk $ len - 1) in- let eg0@(e0,e1,e2,e3) = xorVector prevk 0 v0 in- let eg1@(e4,e5,e6,e7) = xorVector prevk 4 eg0 in- let eg2@(e8,e9,e10,e11) = xorVector prevk 8 eg1 in- let eg3@(e12,e13,e14,e15) = xorVector prevk 12 eg2 in- let eg4@(e16,e17,e18,e19) = xorVector prevk 16 eg3 in- let (e20,e21,e22,e23) = xorVector prevk 20 eg4 in- V.fromList [e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e20,e21,e22,e23]-- generate32 prevk it =- let len = V.length prevk in- let v0 = cR0 it (V.unsafeIndex prevk $ len - 4)- (V.unsafeIndex prevk $ len - 3)- (V.unsafeIndex prevk $ len - 2)- (V.unsafeIndex prevk $ len - 1) in- let eg0@(e0,e1,e2,e3) = xorVector prevk 0 v0 in- let eg1@(e4,e5,e6,e7) = xorVector prevk 4 eg0 in- let eg2@(e8,e9,e10,e11) = xorVector prevk 8 eg1 in- let eg3@(e12,e13,e14,e15) = xorVector prevk 12 eg2 in- let eg4@(e16,e17,e18,e19) = xorSboxVector prevk 16 eg3 in- let eg5@(e20,e21,e22,e23) = xorVector prevk 20 eg4 in- let eg6@(e24,e25,e26,e27) = xorVector prevk 24 eg5 in- let (e28,e29,e30,e31) = xorVector prevk 28 eg6 in- V.fromList [e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16- ,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31]-- xorVector k i (t0,t1,t2,t3) =- ( V.unsafeIndex k (i+0) `xor` t0- , V.unsafeIndex k (i+1) `xor` t1- , V.unsafeIndex k (i+2) `xor` t2- , V.unsafeIndex k (i+3) `xor` t3- )-- xorSboxVector k i (t0,t1,t2,t3) =- ( V.unsafeIndex k (i+0) `xor` sbox t0- , V.unsafeIndex k (i+1) `xor` sbox t1- , V.unsafeIndex k (i+2) `xor` sbox t2- , V.unsafeIndex k (i+3) `xor` sbox t3- )-- cR0 it r0 r1 r2 r3 =- (sbox r1 `xor` rcon it, sbox r2, sbox r3, sbox r0)--{-# INLINE shiftRows #-}-shiftRows :: AESState -> IO ()-shiftRows blk = do- r32 blk 0 >>= w32 blk 0 . msbox32- r32 blk 1 >>= \t1 -> w32 blk 1 $ rotateR (msbox32 t1) 8- r32 blk 2 >>= \t2 -> w32 blk 2 $ rotateR (msbox32 t2) 16- r32 blk 3 >>= \t3 -> w32 blk 3 $ rotateR (msbox32 t3) 24--{-# INLINE addRoundKey #-}-addRoundKey :: Key -> Int -> AESState -> IO ()-addRoundKey (Key key) i blk = forM_ [0..15] $ \n -> do- r8 blk n >>= \v1 -> w8 blk n $ v1 `xor` V.unsafeIndex key (16 * i + swapIndex n)--{-# INLINE mixColumns #-}-mixColumns :: AESState -> IO ()-mixColumns state = pr 0 >> pr 1 >> pr 2 >> pr 3- where- {-# INLINE pr #-}- pr i = do- cpy0 <- r8 state (0 * 4 + i)- cpy1 <- r8 state (1 * 4 + i)- cpy2 <- r8 state (2 * 4 + i)- cpy3 <- r8 state (3 * 4 + i)-- let state0 = gm2 cpy0 `xor` gm1 cpy3 `xor` gm1 cpy2 `xor` gm3 cpy1- let state4 = gm2 cpy1 `xor` gm1 cpy0 `xor` gm1 cpy3 `xor` gm3 cpy2- let state8 = gm2 cpy2 `xor` gm1 cpy1 `xor` gm1 cpy0 `xor` gm3 cpy3- let state12 = gm2 cpy3 `xor` gm1 cpy2 `xor` gm1 cpy1 `xor` gm3 cpy0-- w8 state (0 * 4 + i) state0- w8 state (1 * 4 + i) state4- w8 state (2 * 4 + i) state8- w8 state (3 * 4 + i) state12- {-# INLINE gm1 #-}- gm1 a = a--{-# INLINE shiftRowsInv #-}-shiftRowsInv :: AESState -> IO ()-shiftRowsInv blk = do- r32 blk 0 >>= w32 blk 0 . mrsbox32- r32 blk 1 >>= \t1 -> w32 blk 1 $ mrsbox32 $ rotateL t1 8- r32 blk 2 >>= \t2 -> w32 blk 2 $ mrsbox32 $ rotateL t2 16- r32 blk 3 >>= \t3 -> w32 blk 3 $ mrsbox32 $ rotateL t3 24--{-# INLINE mixColumnsInv #-}-mixColumnsInv :: AESState -> IO ()-mixColumnsInv state = pr 0 >> pr 1 >> pr 2 >> pr 3- where- {-# INLINE pr #-}- pr i = do- cpy0 <- r8 state (0 * 4 + i)- cpy1 <- r8 state (1 * 4 + i)- cpy2 <- r8 state (2 * 4 + i)- cpy3 <- r8 state (3 * 4 + i)-- let state0 = gm14 cpy0 `xor` gm9 cpy3 `xor` gm13 cpy2 `xor` gm11 cpy1- let state4 = gm14 cpy1 `xor` gm9 cpy0 `xor` gm13 cpy3 `xor` gm11 cpy2- let state8 = gm14 cpy2 `xor` gm9 cpy1 `xor` gm13 cpy0 `xor` gm11 cpy3- let state12 = gm14 cpy3 `xor` gm9 cpy2 `xor` gm13 cpy1 `xor` gm11 cpy0-- w8 state (0 * 4 + i) state0- w8 state (1 * 4 + i) state4- w8 state (2 * 4 + i) state8- w8 state (3 * 4 + i) state12--{-# INLINE r8 #-}-r8 :: AESState -> Int -> IO Word8-r8 = readByteArray--{-# INLINE w8 #-}-w8 :: AESState -> Int -> Word8 -> IO ()-w8 = writeByteArray--{-# INLINE r32 #-}-r32 :: AESState -> Int -> IO Word32-r32 = readByteArray--{-# INLINE w32 #-}-w32 :: AESState -> Int -> Word32 -> IO ()-w32 = writeByteArray--msbox32 :: Word32 -> Word32-msbox32 w = sbox4 a .|. sbox3 b .|. sbox2 c .|. sbox1 d- where- a = fromIntegral (w `shiftR` 24)- b = fromIntegral (w `shiftR` 16)- c = fromIntegral (w `shiftR` 8)- d = fromIntegral w--mrsbox32 :: Word32 -> Word32-mrsbox32 w = fromIntegral (rsbox a) `shiftL` 24 .|.- fromIntegral (rsbox b) `shiftL` 16 .|.- fromIntegral (rsbox c) `shiftL` 8 .|.- fromIntegral (rsbox d)- where- a = fromIntegral (w `shiftR` 24)- b = fromIntegral (w `shiftR` 16)- c = fromIntegral (w `shiftR` 8)- d = fromIntegral w---{-# INLINE swapBlock #-}-swapBlock :: ByteString -> AESState -> IO ()-swapBlock b blk = do -- V.generate 16 (\i -> B.unsafeIndex b $ swapIndex i)- forM_ [0..15] $ \i -> w8 blk i $ B.unsafeIndex b $ swapIndex i--{-# INLINE swapBlockInv #-}-swapBlockInv :: AESState -> Ptr Word8 -> IO ()-swapBlockInv blk ptr = forM_ [0..15] $ \i -> r8 blk (swapIndex i) >>= pokeByteOff ptr i--{-# INLINE sbox #-}-sbox :: Word8 -> Word8-sbox (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x63\x7c\x77\x7b\xf2\x6b\x6f\xc5\- \\x30\x01\x67\x2b\xfe\xd7\xab\x76\- \\xca\x82\xc9\x7d\xfa\x59\x47\xf0\- \\xad\xd4\xa2\xaf\x9c\xa4\x72\xc0\- \\xb7\xfd\x93\x26\x36\x3f\xf7\xcc\- \\x34\xa5\xe5\xf1\x71\xd8\x31\x15\- \\x04\xc7\x23\xc3\x18\x96\x05\x9a\- \\x07\x12\x80\xe2\xeb\x27\xb2\x75\- \\x09\x83\x2c\x1a\x1b\x6e\x5a\xa0\- \\x52\x3b\xd6\xb3\x29\xe3\x2f\x84\- \\x53\xd1\x00\xed\x20\xfc\xb1\x5b\- \\x6a\xcb\xbe\x39\x4a\x4c\x58\xcf\- \\xd0\xef\xaa\xfb\x43\x4d\x33\x85\- \\x45\xf9\x02\x7f\x50\x3c\x9f\xa8\- \\x51\xa3\x40\x8f\x92\x9d\x38\xf5\- \\xbc\xb6\xda\x21\x10\xff\xf3\xd2\- \\xcd\x0c\x13\xec\x5f\x97\x44\x17\- \\xc4\xa7\x7e\x3d\x64\x5d\x19\x73\- \\x60\x81\x4f\xdc\x22\x2a\x90\x88\- \\x46\xee\xb8\x14\xde\x5e\x0b\xdb\- \\xe0\x32\x3a\x0a\x49\x06\x24\x5c\- \\xc2\xd3\xac\x62\x91\x95\xe4\x79\- \\xe7\xc8\x37\x6d\x8d\xd5\x4e\xa9\- \\x6c\x56\xf4\xea\x65\x7a\xae\x08\- \\xba\x78\x25\x2e\x1c\xa6\xb4\xc6\- \\xe8\xdd\x74\x1f\x4b\xbd\x8b\x8a\- \\x70\x3e\xb5\x66\x48\x03\xf6\x0e\- \\x61\x35\x57\xb9\x86\xc1\x1d\x9e\- \\xe1\xf8\x98\x11\x69\xd9\x8e\x94\- \\x9b\x1e\x87\xe9\xce\x55\x28\xdf\- \\x8c\xa1\x89\x0d\xbf\xe6\x42\x68\- \\x41\x99\x2d\x0f\xb0\x54\xbb\x16"#--{-# INLINE sbox1 #-}-{-# INLINE sbox2 #-}-{-# INLINE sbox3 #-}-{-# INLINE sbox4 #-}-sbox1, sbox2, sbox3, sbox4 :: Word8 -> Word32-sbox1 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))- where !(Table table) = sbox1Tab-sbox2 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))- where !(Table table) = sbox2Tab-sbox3 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))- where !(Table table) = sbox3Tab-sbox4 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))- where !(Table table) = sbox4Tab--sbox1Tab, sbox2Tab, sbox3Tab, sbox4Tab :: Table-sbox1Tab = if littleEndian then sbox_x000 else sbox_000x-sbox2Tab = if littleEndian then sbox_0x00 else sbox_00x0-sbox3Tab = if littleEndian then sbox_00x0 else sbox_0x00-sbox4Tab = if littleEndian then sbox_000x else sbox_x000--data Table = Table !Addr#--sbox_000x, sbox_00x0, sbox_0x00, sbox_x000 :: Table-sbox_000x = Table- "\x00\x00\x00\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\- \\x00\x00\x00\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\- \\x00\x00\x00\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\- \\x00\x00\x00\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\- \\x00\x00\x00\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\- \\x00\x00\x00\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\- \\x00\x00\x00\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\- \\x00\x00\x00\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\- \\x00\x00\x00\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\- \\x00\x00\x00\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\- \\x00\x00\x00\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\- \\x00\x00\x00\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\- \\x00\x00\x00\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\- \\x00\x00\x00\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\- \\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\- \\x00\x00\x00\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\- \\x00\x00\x00\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\- \\x00\x00\x00\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\- \\x00\x00\x00\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\- \\x00\x00\x00\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\- \\x00\x00\x00\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\- \\x00\x00\x00\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\- \\x00\x00\x00\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\- \\x00\x00\x00\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\- \\x00\x00\x00\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\- \\x00\x00\x00\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\- \\x00\x00\x00\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\- \\x00\x00\x00\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\- \\x00\x00\x00\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\- \\x00\x00\x00\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\- \\x00\x00\x00\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\- \\x00\x00\x00\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\- \\x00\x00\x00\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\- \\x00\x00\x00\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\- \\x00\x00\x00\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\- \\x00\x00\x00\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\- \\x00\x00\x00\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\- \\x00\x00\x00\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\- \\x00\x00\x00\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\- \\x00\x00\x00\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\- \\x00\x00\x00\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\- \\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\- \\x00\x00\x00\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\- \\x00\x00\x00\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\- \\x00\x00\x00\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\- \\x00\x00\x00\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\- \\x00\x00\x00\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\- \\x00\x00\x00\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\- \\x00\x00\x00\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\- \\x00\x00\x00\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\- \\x00\x00\x00\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\- \\x00\x00\x00\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\- \\x00\x00\x00\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\- \\x00\x00\x00\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\- \\x00\x00\x00\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\- \\x00\x00\x00\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\- \\x00\x00\x00\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\- \\x00\x00\x00\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\- \\x00\x00\x00\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\- \\x00\x00\x00\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\- \\x00\x00\x00\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\- \\x00\x00\x00\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\- \\x00\x00\x00\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\- \\x00\x00\x00\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16"#--sbox_00x0 = Table- "\x00\x00\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\x00\- \\x00\x00\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\x00\- \\x00\x00\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\x00\- \\x00\x00\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\x00\- \\x00\x00\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\x00\- \\x00\x00\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\x00\- \\x00\x00\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\x00\- \\x00\x00\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\x00\- \\x00\x00\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\x00\- \\x00\x00\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\x00\- \\x00\x00\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\x00\- \\x00\x00\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\x00\- \\x00\x00\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\x00\- \\x00\x00\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\x00\- \\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\x00\- \\x00\x00\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\x00\- \\x00\x00\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\x00\- \\x00\x00\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\x00\- \\x00\x00\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\x00\- \\x00\x00\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\x00\- \\x00\x00\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\x00\- \\x00\x00\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\x00\- \\x00\x00\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\x00\- \\x00\x00\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\x00\- \\x00\x00\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\x00\- \\x00\x00\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\x00\- \\x00\x00\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\x00\- \\x00\x00\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\x00\- \\x00\x00\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\x00\- \\x00\x00\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\x00\- \\x00\x00\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\x00\- \\x00\x00\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\x00\- \\x00\x00\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\x00\- \\x00\x00\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\x00\- \\x00\x00\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\x00\- \\x00\x00\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\x00\- \\x00\x00\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\x00\- \\x00\x00\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\x00\- \\x00\x00\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\x00\- \\x00\x00\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\x00\- \\x00\x00\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\- \\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\x00\- \\x00\x00\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\x00\- \\x00\x00\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\x00\- \\x00\x00\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\x00\- \\x00\x00\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\x00\- \\x00\x00\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\x00\- \\x00\x00\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\x00\- \\x00\x00\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\x00\- \\x00\x00\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\x00\- \\x00\x00\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\x00\- \\x00\x00\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\x00\- \\x00\x00\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\x00\- \\x00\x00\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\x00\- \\x00\x00\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\x00\- \\x00\x00\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\x00\- \\x00\x00\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\x00\- \\x00\x00\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\x00\- \\x00\x00\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\x00\- \\x00\x00\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\x00\- \\x00\x00\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\x00\- \\x00\x00\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\x00\- \\x00\x00\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\x00\- \\x00\x00\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16\x00"#--sbox_0x00 = Table- "\x00\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\x00\x00\- \\x00\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\x00\x00\- \\x00\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\x00\x00\- \\x00\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\x00\x00\- \\x00\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\x00\x00\- \\x00\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\x00\x00\- \\x00\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\x00\x00\- \\x00\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\x00\x00\- \\x00\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\x00\x00\- \\x00\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\x00\x00\- \\x00\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\x00\x00\- \\x00\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\x00\x00\- \\x00\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\x00\x00\- \\x00\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\x00\x00\- \\x00\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\x00\x00\- \\x00\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\x00\x00\- \\x00\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\x00\x00\- \\x00\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\x00\x00\- \\x00\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\x00\x00\- \\x00\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\x00\x00\- \\x00\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\x00\x00\- \\x00\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\x00\x00\- \\x00\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\x00\x00\- \\x00\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\x00\x00\- \\x00\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\x00\x00\- \\x00\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\x00\x00\- \\x00\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\- \\x00\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\x00\x00\- \\x00\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\x00\x00\- \\x00\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\x00\x00\- \\x00\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\x00\x00\- \\x00\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\x00\x00\- \\x00\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\x00\x00\- \\x00\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\x00\x00\- \\x00\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\x00\x00\- \\x00\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\x00\x00\- \\x00\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\x00\x00\- \\x00\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\x00\x00\- \\x00\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\x00\x00\- \\x00\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\x00\x00\- \\x00\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\x00\- \\x00\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\x00\x00\- \\x00\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\x00\x00\- \\x00\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\x00\x00\- \\x00\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\x00\x00\- \\x00\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\x00\x00\- \\x00\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\x00\x00\- \\x00\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\x00\x00\- \\x00\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\x00\x00\- \\x00\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\x00\x00\- \\x00\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\x00\x00\- \\x00\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\x00\x00\- \\x00\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\x00\x00\- \\x00\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\x00\x00\- \\x00\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\x00\x00\- \\x00\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\x00\x00\- \\x00\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\x00\x00\- \\x00\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\x00\x00\- \\x00\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\x00\x00\- \\x00\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\x00\x00\- \\x00\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\x00\x00\- \\x00\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\x00\x00\- \\x00\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\x00\x00\- \\x00\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16\x00\x00"#--sbox_x000 = Table- "\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\x00\x00\x00\- \\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\x00\x00\x00\- \\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\x00\x00\x00\- \\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\x00\x00\x00\- \\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\x00\x00\x00\- \\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\x00\x00\x00\- \\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\x00\x00\x00\- \\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\x00\x00\x00\- \\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\x00\x00\x00\- \\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\x00\x00\x00\- \\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\x00\x00\x00\- \\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\x00\x00\x00\- \\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\x00\x00\x00\- \\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\x00\x00\x00\- \\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\x00\x00\x00\- \\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\x00\x00\x00\- \\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\x00\x00\x00\- \\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\x00\x00\x00\- \\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\x00\x00\x00\- \\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\x00\x00\x00\- \\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\x00\x00\x00\- \\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\x00\x00\x00\- \\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\x00\x00\x00\- \\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\x00\x00\x00\- \\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\x00\x00\x00\- \\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\x00\x00\x00\- \\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00\- \\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\x00\x00\x00\- \\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\x00\x00\x00\- \\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\x00\x00\x00\- \\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\x00\x00\x00\- \\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\x00\x00\x00\- \\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\x00\x00\x00\- \\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\x00\x00\x00\- \\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\x00\x00\x00\- \\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\x00\x00\x00\- \\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\x00\x00\x00\- \\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\x00\x00\x00\- \\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\x00\x00\x00\- \\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\x00\x00\x00\- \\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\x00\x00\- \\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\x00\x00\x00\- \\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\x00\x00\x00\- \\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\x00\x00\x00\- \\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\x00\x00\x00\- \\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\x00\x00\x00\- \\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\x00\x00\x00\- \\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\x00\x00\x00\- \\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\x00\x00\x00\- \\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\x00\x00\x00\- \\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\x00\x00\x00\- \\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\x00\x00\x00\- \\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\x00\x00\x00\- \\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\x00\x00\x00\- \\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\x00\x00\x00\- \\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\x00\x00\x00\- \\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\x00\x00\x00\- \\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\x00\x00\x00\- \\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\x00\x00\x00\- \\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\x00\x00\x00\- \\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\x00\x00\x00\- \\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\x00\x00\x00\- \\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\x00\x00\x00\- \\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16\x00\x00\x00"#---{-# INLINE rsbox #-}-rsbox :: Word8 -> Word8-rsbox (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x52\x09\x6a\xd5\x30\x36\xa5\x38\- \\xbf\x40\xa3\x9e\x81\xf3\xd7\xfb\- \\x7c\xe3\x39\x82\x9b\x2f\xff\x87\- \\x34\x8e\x43\x44\xc4\xde\xe9\xcb\- \\x54\x7b\x94\x32\xa6\xc2\x23\x3d\- \\xee\x4c\x95\x0b\x42\xfa\xc3\x4e\- \\x08\x2e\xa1\x66\x28\xd9\x24\xb2\- \\x76\x5b\xa2\x49\x6d\x8b\xd1\x25\- \\x72\xf8\xf6\x64\x86\x68\x98\x16\- \\xd4\xa4\x5c\xcc\x5d\x65\xb6\x92\- \\x6c\x70\x48\x50\xfd\xed\xb9\xda\- \\x5e\x15\x46\x57\xa7\x8d\x9d\x84\- \\x90\xd8\xab\x00\x8c\xbc\xd3\x0a\- \\xf7\xe4\x58\x05\xb8\xb3\x45\x06\- \\xd0\x2c\x1e\x8f\xca\x3f\x0f\x02\- \\xc1\xaf\xbd\x03\x01\x13\x8a\x6b\- \\x3a\x91\x11\x41\x4f\x67\xdc\xea\- \\x97\xf2\xcf\xce\xf0\xb4\xe6\x73\- \\x96\xac\x74\x22\xe7\xad\x35\x85\- \\xe2\xf9\x37\xe8\x1c\x75\xdf\x6e\- \\x47\xf1\x1a\x71\x1d\x29\xc5\x89\- \\x6f\xb7\x62\x0e\xaa\x18\xbe\x1b\- \\xfc\x56\x3e\x4b\xc6\xd2\x79\x20\- \\x9a\xdb\xc0\xfe\x78\xcd\x5a\xf4\- \\x1f\xdd\xa8\x33\x88\x07\xc7\x31\- \\xb1\x12\x10\x59\x27\x80\xec\x5f\- \\x60\x51\x7f\xa9\x19\xb5\x4a\x0d\- \\x2d\xe5\x7a\x9f\x93\xc9\x9c\xef\- \\xa0\xe0\x3b\x4d\xae\x2a\xf5\xb0\- \\xc8\xeb\xbb\x3c\x83\x53\x99\x61\- \\x17\x2b\x04\x7e\xba\x77\xd6\x26\- \\xe1\x69\x14\x63\x55\x21\x0c\x7d"#--{-# INLINE rcon #-}-rcon :: Int -> Word8-rcon (I# i) = W8# (indexWord8OffAddr# table (i `remInt#` 51#))- where !table =- "\x8d\x01\x02\x04\x08\x10\x20\x40\- \\x80\x1b\x36\x6c\xd8\xab\x4d\x9a\- \\x2f\x5e\xbc\x63\xc6\x97\x35\x6a\- \\xd4\xb3\x7d\xfa\xef\xc5\x91\x39\- \\x72\xe4\xd3\xbd\x61\xc2\x9f\x25\- \\x4a\x94\x33\x66\xcc\x83\x1d\x3a\- \\x74\xe8\xcb"#--{-# INLINE gm2 #-}-{-# INLINE gm3 #-}-{-# INLINE gm9 #-}-{-# INLINE gm11 #-}-{-# INLINE gm13 #-}-{-# INLINE gm14 #-}-gm2, gm3, gm9, gm11, gm13, gm14 :: Word8 -> Word8-gm2 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x00\x02\x04\x06\x08\x0a\x0c\x0e\- \\x10\x12\x14\x16\x18\x1a\x1c\x1e\- \\x20\x22\x24\x26\x28\x2a\x2c\x2e\- \\x30\x32\x34\x36\x38\x3a\x3c\x3e\- \\x40\x42\x44\x46\x48\x4a\x4c\x4e\- \\x50\x52\x54\x56\x58\x5a\x5c\x5e\- \\x60\x62\x64\x66\x68\x6a\x6c\x6e\- \\x70\x72\x74\x76\x78\x7a\x7c\x7e\- \\x80\x82\x84\x86\x88\x8a\x8c\x8e\- \\x90\x92\x94\x96\x98\x9a\x9c\x9e\- \\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\- \\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe\- \\xc0\xc2\xc4\xc6\xc8\xca\xcc\xce\- \\xd0\xd2\xd4\xd6\xd8\xda\xdc\xde\- \\xe0\xe2\xe4\xe6\xe8\xea\xec\xee\- \\xf0\xf2\xf4\xf6\xf8\xfa\xfc\xfe\- \\x1b\x19\x1f\x1d\x13\x11\x17\x15\- \\x0b\x09\x0f\x0d\x03\x01\x07\x05\- \\x3b\x39\x3f\x3d\x33\x31\x37\x35\- \\x2b\x29\x2f\x2d\x23\x21\x27\x25\- \\x5b\x59\x5f\x5d\x53\x51\x57\x55\- \\x4b\x49\x4f\x4d\x43\x41\x47\x45\- \\x7b\x79\x7f\x7d\x73\x71\x77\x75\- \\x6b\x69\x6f\x6d\x63\x61\x67\x65\- \\x9b\x99\x9f\x9d\x93\x91\x97\x95\- \\x8b\x89\x8f\x8d\x83\x81\x87\x85\- \\xbb\xb9\xbf\xbd\xb3\xb1\xb7\xb5\- \\xab\xa9\xaf\xad\xa3\xa1\xa7\xa5\- \\xdb\xd9\xdf\xdd\xd3\xd1\xd7\xd5\- \\xcb\xc9\xcf\xcd\xc3\xc1\xc7\xc5\- \\xfb\xf9\xff\xfd\xf3\xf1\xf7\xf5\- \\xeb\xe9\xef\xed\xe3\xe1\xe7\xe5"#--gm3 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x00\x03\x06\x05\x0c\x0f\x0a\x09\- \\x18\x1b\x1e\x1d\x14\x17\x12\x11\- \\x30\x33\x36\x35\x3c\x3f\x3a\x39\- \\x28\x2b\x2e\x2d\x24\x27\x22\x21\- \\x60\x63\x66\x65\x6c\x6f\x6a\x69\- \\x78\x7b\x7e\x7d\x74\x77\x72\x71\- \\x50\x53\x56\x55\x5c\x5f\x5a\x59\- \\x48\x4b\x4e\x4d\x44\x47\x42\x41\- \\xc0\xc3\xc6\xc5\xcc\xcf\xca\xc9\- \\xd8\xdb\xde\xdd\xd4\xd7\xd2\xd1\- \\xf0\xf3\xf6\xf5\xfc\xff\xfa\xf9\- \\xe8\xeb\xee\xed\xe4\xe7\xe2\xe1\- \\xa0\xa3\xa6\xa5\xac\xaf\xaa\xa9\- \\xb8\xbb\xbe\xbd\xb4\xb7\xb2\xb1\- \\x90\x93\x96\x95\x9c\x9f\x9a\x99\- \\x88\x8b\x8e\x8d\x84\x87\x82\x81\- \\x9b\x98\x9d\x9e\x97\x94\x91\x92\- \\x83\x80\x85\x86\x8f\x8c\x89\x8a\- \\xab\xa8\xad\xae\xa7\xa4\xa1\xa2\- \\xb3\xb0\xb5\xb6\xbf\xbc\xb9\xba\- \\xfb\xf8\xfd\xfe\xf7\xf4\xf1\xf2\- \\xe3\xe0\xe5\xe6\xef\xec\xe9\xea\- \\xcb\xc8\xcd\xce\xc7\xc4\xc1\xc2\- \\xd3\xd0\xd5\xd6\xdf\xdc\xd9\xda\- \\x5b\x58\x5d\x5e\x57\x54\x51\x52\- \\x43\x40\x45\x46\x4f\x4c\x49\x4a\- \\x6b\x68\x6d\x6e\x67\x64\x61\x62\- \\x73\x70\x75\x76\x7f\x7c\x79\x7a\- \\x3b\x38\x3d\x3e\x37\x34\x31\x32\- \\x23\x20\x25\x26\x2f\x2c\x29\x2a\- \\x0b\x08\x0d\x0e\x07\x04\x01\x02\- \\x13\x10\x15\x16\x1f\x1c\x19\x1a"#--gm9 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x00\x09\x12\x1b\x24\x2d\x36\x3f\- \\x48\x41\x5a\x53\x6c\x65\x7e\x77\- \\x90\x99\x82\x8b\xb4\xbd\xa6\xaf\- \\xd8\xd1\xca\xc3\xfc\xf5\xee\xe7\- \\x3b\x32\x29\x20\x1f\x16\x0d\x04\- \\x73\x7a\x61\x68\x57\x5e\x45\x4c\- \\xab\xa2\xb9\xb0\x8f\x86\x9d\x94\- \\xe3\xea\xf1\xf8\xc7\xce\xd5\xdc\- \\x76\x7f\x64\x6d\x52\x5b\x40\x49\- \\x3e\x37\x2c\x25\x1a\x13\x08\x01\- \\xe6\xef\xf4\xfd\xc2\xcb\xd0\xd9\- \\xae\xa7\xbc\xb5\x8a\x83\x98\x91\- \\x4d\x44\x5f\x56\x69\x60\x7b\x72\- \\x05\x0c\x17\x1e\x21\x28\x33\x3a\- \\xdd\xd4\xcf\xc6\xf9\xf0\xeb\xe2\- \\x95\x9c\x87\x8e\xb1\xb8\xa3\xaa\- \\xec\xe5\xfe\xf7\xc8\xc1\xda\xd3\- \\xa4\xad\xb6\xbf\x80\x89\x92\x9b\- \\x7c\x75\x6e\x67\x58\x51\x4a\x43\- \\x34\x3d\x26\x2f\x10\x19\x02\x0b\- \\xd7\xde\xc5\xcc\xf3\xfa\xe1\xe8\- \\x9f\x96\x8d\x84\xbb\xb2\xa9\xa0\- \\x47\x4e\x55\x5c\x63\x6a\x71\x78\- \\x0f\x06\x1d\x14\x2b\x22\x39\x30\- \\x9a\x93\x88\x81\xbe\xb7\xac\xa5\- \\xd2\xdb\xc0\xc9\xf6\xff\xe4\xed\- \\x0a\x03\x18\x11\x2e\x27\x3c\x35\- \\x42\x4b\x50\x59\x66\x6f\x74\x7d\- \\xa1\xa8\xb3\xba\x85\x8c\x97\x9e\- \\xe9\xe0\xfb\xf2\xcd\xc4\xdf\xd6\- \\x31\x38\x23\x2a\x15\x1c\x07\x0e\- \\x79\x70\x6b\x62\x5d\x54\x4f\x46"#--gm11 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x00\x0b\x16\x1d\x2c\x27\x3a\x31\- \\x58\x53\x4e\x45\x74\x7f\x62\x69\- \\xb0\xbb\xa6\xad\x9c\x97\x8a\x81\- \\xe8\xe3\xfe\xf5\xc4\xcf\xd2\xd9\- \\x7b\x70\x6d\x66\x57\x5c\x41\x4a\- \\x23\x28\x35\x3e\x0f\x04\x19\x12\- \\xcb\xc0\xdd\xd6\xe7\xec\xf1\xfa\- \\x93\x98\x85\x8e\xbf\xb4\xa9\xa2\- \\xf6\xfd\xe0\xeb\xda\xd1\xcc\xc7\- \\xae\xa5\xb8\xb3\x82\x89\x94\x9f\- \\x46\x4d\x50\x5b\x6a\x61\x7c\x77\- \\x1e\x15\x08\x03\x32\x39\x24\x2f\- \\x8d\x86\x9b\x90\xa1\xaa\xb7\xbc\- \\xd5\xde\xc3\xc8\xf9\xf2\xef\xe4\- \\x3d\x36\x2b\x20\x11\x1a\x07\x0c\- \\x65\x6e\x73\x78\x49\x42\x5f\x54\- \\xf7\xfc\xe1\xea\xdb\xd0\xcd\xc6\- \\xaf\xa4\xb9\xb2\x83\x88\x95\x9e\- \\x47\x4c\x51\x5a\x6b\x60\x7d\x76\- \\x1f\x14\x09\x02\x33\x38\x25\x2e\- \\x8c\x87\x9a\x91\xa0\xab\xb6\xbd\- \\xd4\xdf\xc2\xc9\xf8\xf3\xee\xe5\- \\x3c\x37\x2a\x21\x10\x1b\x06\x0d\- \\x64\x6f\x72\x79\x48\x43\x5e\x55\- \\x01\x0a\x17\x1c\x2d\x26\x3b\x30\- \\x59\x52\x4f\x44\x75\x7e\x63\x68\- \\xb1\xba\xa7\xac\x9d\x96\x8b\x80\- \\xe9\xe2\xff\xf4\xc5\xce\xd3\xd8\- \\x7a\x71\x6c\x67\x56\x5d\x40\x4b\- \\x22\x29\x34\x3f\x0e\x05\x18\x13\- \\xca\xc1\xdc\xd7\xe6\xed\xf0\xfb\- \\x92\x99\x84\x8f\xbe\xb5\xa8\xa3"#--gm13 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x00\x0d\x1a\x17\x34\x39\x2e\x23\- \\x68\x65\x72\x7f\x5c\x51\x46\x4b\- \\xd0\xdd\xca\xc7\xe4\xe9\xfe\xf3\- \\xb8\xb5\xa2\xaf\x8c\x81\x96\x9b\- \\xbb\xb6\xa1\xac\x8f\x82\x95\x98\- \\xd3\xde\xc9\xc4\xe7\xea\xfd\xf0\- \\x6b\x66\x71\x7c\x5f\x52\x45\x48\- \\x03\x0e\x19\x14\x37\x3a\x2d\x20\- \\x6d\x60\x77\x7a\x59\x54\x43\x4e\- \\x05\x08\x1f\x12\x31\x3c\x2b\x26\- \\xbd\xb0\xa7\xaa\x89\x84\x93\x9e\- \\xd5\xd8\xcf\xc2\xe1\xec\xfb\xf6\- \\xd6\xdb\xcc\xc1\xe2\xef\xf8\xf5\- \\xbe\xb3\xa4\xa9\x8a\x87\x90\x9d\- \\x06\x0b\x1c\x11\x32\x3f\x28\x25\- \\x6e\x63\x74\x79\x5a\x57\x40\x4d\- \\xda\xd7\xc0\xcd\xee\xe3\xf4\xf9\- \\xb2\xbf\xa8\xa5\x86\x8b\x9c\x91\- \\x0a\x07\x10\x1d\x3e\x33\x24\x29\- \\x62\x6f\x78\x75\x56\x5b\x4c\x41\- \\x61\x6c\x7b\x76\x55\x58\x4f\x42\- \\x09\x04\x13\x1e\x3d\x30\x27\x2a\- \\xb1\xbc\xab\xa6\x85\x88\x9f\x92\- \\xd9\xd4\xc3\xce\xed\xe0\xf7\xfa\- \\xb7\xba\xad\xa0\x83\x8e\x99\x94\- \\xdf\xd2\xc5\xc8\xeb\xe6\xf1\xfc\- \\x67\x6a\x7d\x70\x53\x5e\x49\x44\- \\x0f\x02\x15\x18\x3b\x36\x21\x2c\- \\x0c\x01\x16\x1b\x38\x35\x22\x2f\- \\x64\x69\x7e\x73\x50\x5d\x4a\x47\- \\xdc\xd1\xc6\xcb\xe8\xe5\xf2\xff\- \\xb4\xb9\xae\xa3\x80\x8d\x9a\x97"#--gm14 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))- where !table =- "\x00\x0e\x1c\x12\x38\x36\x24\x2a\- \\x70\x7e\x6c\x62\x48\x46\x54\x5a\- \\xe0\xee\xfc\xf2\xd8\xd6\xc4\xca\- \\x90\x9e\x8c\x82\xa8\xa6\xb4\xba\- \\xdb\xd5\xc7\xc9\xe3\xed\xff\xf1\- \\xab\xa5\xb7\xb9\x93\x9d\x8f\x81\- \\x3b\x35\x27\x29\x03\x0d\x1f\x11\- \\x4b\x45\x57\x59\x73\x7d\x6f\x61\- \\xad\xa3\xb1\xbf\x95\x9b\x89\x87\- \\xdd\xd3\xc1\xcf\xe5\xeb\xf9\xf7\- \\x4d\x43\x51\x5f\x75\x7b\x69\x67\- \\x3d\x33\x21\x2f\x05\x0b\x19\x17\- \\x76\x78\x6a\x64\x4e\x40\x52\x5c\- \\x06\x08\x1a\x14\x3e\x30\x22\x2c\- \\x96\x98\x8a\x84\xae\xa0\xb2\xbc\- \\xe6\xe8\xfa\xf4\xde\xd0\xc2\xcc\- \\x41\x4f\x5d\x53\x79\x77\x65\x6b\- \\x31\x3f\x2d\x23\x09\x07\x15\x1b\- \\xa1\xaf\xbd\xb3\x99\x97\x85\x8b\- \\xd1\xdf\xcd\xc3\xe9\xe7\xf5\xfb\- \\x9a\x94\x86\x88\xa2\xac\xbe\xb0\- \\xea\xe4\xf6\xf8\xd2\xdc\xce\xc0\- \\x7a\x74\x66\x68\x42\x4c\x5e\x50\- \\x0a\x04\x16\x18\x32\x3c\x2e\x20\- \\xec\xe2\xf0\xfe\xd4\xda\xc8\xc6\- \\x9c\x92\x80\x8e\xa4\xaa\xb8\xb6\- \\x0c\x02\x10\x1e\x34\x3a\x28\x26\- \\x7c\x72\x60\x6e\x44\x4a\x58\x56\- \\x37\x39\x2b\x25\x0f\x01\x13\x1d\- \\x47\x49\x5b\x55\x7f\x71\x63\x6d\- \\xd7\xd9\xcb\xc5\xef\xe1\xf3\xfd\- \\xa7\xa9\xbb\xb5\x9f\x91\x83\x8d"#+-- |+-- Module : Crypto.Cipher.AES+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : Good++module Crypto.Cipher.AES+ ( module Crypto.Cipher.AES.Haskell+ ) where++import Crypto.Cipher.AES.Haskell
+ Crypto/Cipher/AES/Haskell.hs view
@@ -0,0 +1,1014 @@+{-# LANGUAGE BangPatterns, MagicHash #-}+-- |+-- Module : Crypto.Cipher.AES.Haskell+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : Good++module Crypto.Cipher.AES.Haskell+ ( Key+ , IV+ -- * Basic encryption and decryption+ , encrypt+ , decrypt+ -- * CBC encryption and decryption+ , encryptCBC+ , decryptCBC+ -- * key building mechanism+ , initKey128+ , initKey192+ , initKey256+ -- * Wrappers for "crypto-api" instances+ , AES128+ , AES192+ , AES256+ ) where++import Data.Word+import Data.Vector.Unboxed (Vector)+import qualified Data.Vector.Unboxed as V+import Data.Bits+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Unsafe as B+import qualified Data.ByteString.Internal as B++import GHC.Prim (indexWord8OffAddr#, indexWord32OffAddr#, word2Int#, Addr#, remInt#)+import GHC.Word+import GHC.Types++import Foreign.Ptr+import Foreign.Storable++import Data.Tagged (Tagged(..))+import Crypto.Classes (BlockCipher(..))+import Data.Serialize (Serialize(..), getByteString, putByteString)++import Control.Monad (forM_)+import Control.Monad.Primitive++import Data.Primitive.ByteArray++import System.Endian (getSystemEndianness, Endianness(..))++newtype AES128 = A128 { unA128 :: Key }+newtype AES192 = A192 { unA192 :: Key }+newtype AES256 = A256 { unA256 :: Key }++instance BlockCipher AES128 where+ blockSize = Tagged 128+ encryptBlock = encrypt . unA128+ decryptBlock = decrypt . unA128+ buildKey b = either (const Nothing) (Just . A128) $ initKey128 b+ keyLength = Tagged 128++instance BlockCipher AES192 where+ blockSize = Tagged 128+ encryptBlock = encrypt . unA192+ decryptBlock = decrypt . unA192+ buildKey b = either (const Nothing) (Just . A192) $ initKey192 b+ keyLength = Tagged 192++instance BlockCipher AES256 where+ blockSize = Tagged 128+ encryptBlock = encrypt . unA256+ decryptBlock = decrypt . unA256+ buildKey b = either (const Nothing) (Just . A256) $ initKey256 b+ keyLength = Tagged 256++serializeKey :: Key -> ByteString+serializeKey (Key v)+ | V.length v == 176 = B.pack $ map (V.unsafeIndex v) [0..15]+ | V.length v == 208 = B.pack $ map (V.unsafeIndex v) [0..23]+ | otherwise = B.pack $ map (V.unsafeIndex v) [0..31]++instance Serialize AES128 where+ put = putByteString . serializeKey . unA128+ get = do+ raw <- getByteString (128 `div` 8)+ case buildKey raw of+ Nothing -> fail "Invalid raw key material."+ Just k -> return k++instance Serialize AES192 where+ put = putByteString . serializeKey . unA192+ get = do+ raw <- getByteString (192 `div` 8)+ case buildKey raw of+ Nothing -> fail "Invalid raw key material."+ Just k -> return k++instance Serialize AES256 where+ put = putByteString . serializeKey . unA256+ get = do+ raw <- getByteString (256 `div` 8)+ case buildKey raw of+ Nothing -> fail "Invalid raw key material."+ Just k -> return k++data Key = Key (Vector Word8)+ deriving (Show,Eq)++type IV = B.ByteString++type AESState = MutableByteArray RealWorld++{- | encrypt using CBC mode+ - IV need to be 16 bytes and the data to encrypt a multiple of 16 bytes -}+encryptCBC :: Key -> IV -> B.ByteString -> B.ByteString+encryptCBC key iv b+ | B.length iv /= 16 = error "invalid IV length"+ | B.length b `mod` 16 /= 0 = error "invalid data length"+ | otherwise = B.concat $ encryptIter iv (makeChunks b)+ where+ encryptIter _ [] = []+ encryptIter iv' (x:xs) =+ let r = coreEncrypt key $ B.pack $ B.zipWith xor iv' x in+ r : encryptIter r xs++{- | encrypt using simple EBC mode -}+encrypt :: Key -> B.ByteString -> B.ByteString+encrypt key b+ | B.length b `mod` 16 /= 0 = error "invalid data length"+ | otherwise = B.concat $ doChunks (coreEncrypt key) b++{- | decrypt using CBC mode+ - IV need to be 16 bytes and the data to decrypt a multiple of 16 bytes -}+decryptCBC :: Key -> IV -> B.ByteString -> B.ByteString+decryptCBC key iv b+ | B.length iv /= 16 = error "invalid IV length"+ | B.length b `mod` 16 /= 0 = error "invalid data length"+ | otherwise = B.concat $ decryptIter iv (makeChunks b)+ where+ decryptIter _ [] = []+ decryptIter iv' (x:xs) =+ let r = B.pack $ B.zipWith xor iv' $ coreDecrypt key x in+ r : decryptIter x xs++{- | decrypt using simple EBC mode -}+decrypt :: Key -> B.ByteString -> B.ByteString+decrypt key b+ | B.length b `mod` 16 /= 0 = error "invalid data length"+ | otherwise = B.concat $ doChunks (coreDecrypt key) b++doChunks :: (B.ByteString -> B.ByteString) -> B.ByteString -> [B.ByteString]+doChunks f b =+ let (x, rest) = B.splitAt 16 b in+ if B.length rest >= 16+ then f x : doChunks f rest+ else [ f x ]++makeChunks :: B.ByteString -> [B.ByteString]+makeChunks = doChunks id++newAESState :: IO AESState+newAESState = newAlignedPinnedByteArray 16 16++coreEncrypt :: Key -> ByteString -> ByteString+coreEncrypt key input = B.unsafeCreate (B.length input) $ \ptr -> do+ st <- newAESState+ swapBlock input st+ aesMain (getNbr key) key st+ swapBlockInv st ptr++coreDecrypt :: Key -> ByteString -> ByteString+coreDecrypt key input = B.unsafeCreate (B.length input) $ \ptr -> do+ st <- newAESState+ swapBlock input st+ aesMainInv (getNbr key) key st+ swapBlockInv st ptr++getNbr :: Key -> Int+getNbr (Key v)+ | V.length v == 176 = 10+ | V.length v == 208 = 12+ | otherwise = 14++initKey128, initKey192, initKey256 :: ByteString -> Either String Key++initKey128 = initKey 16+initKey192 = initKey 24+initKey256 = initKey 32++initKey :: Int -> ByteString -> Either String Key+initKey sz b+ | B.length b == sz = Right $ coreExpandKey (V.generate sz $ B.unsafeIndex b)+ | otherwise = Left "wrong key size"++aesMain :: Int -> Key -> AESState -> IO ()+aesMain nbr key blk = do+ addRoundKey key 0 blk+ forM_ [1..nbr-1] $ \i -> do+ shiftRows blk >> mixColumns blk >> addRoundKey key i blk+ shiftRows blk >> addRoundKey key nbr blk++aesMainInv :: Int -> Key -> AESState -> IO ()+aesMainInv nbr key blk = do+ addRoundKey key nbr blk+ forM_ (reverse [1..nbr-1]) $ \i -> do+ shiftRowsInv blk >> addRoundKey key i blk >> mixColumnsInv blk+ shiftRowsInv blk >> addRoundKey key 0 blk++{-# INLINE swapIndex #-}+swapIndex :: Int -> Int+swapIndex 0 = 0+swapIndex 1 = 4+swapIndex 2 = 8+swapIndex 3 = 12+swapIndex 4 = 1+swapIndex 5 = 5+swapIndex 6 = 9+swapIndex 7 = 13+swapIndex 8 = 2+swapIndex 9 = 6+swapIndex 10 = 10+swapIndex 11 = 14+swapIndex 12 = 3+swapIndex 13 = 7+swapIndex 14 = 11+swapIndex 15 = 15+swapIndex _ = 0++coreExpandKey :: Vector Word8 -> Key+coreExpandKey vkey+ | V.length vkey == 16 = Key (V.concat (ek0 : ekN16))+ | V.length vkey == 24 = Key (V.concat (ek0 : ekN24))+ | V.length vkey == 32 = Key (V.concat (ek0 : ekN32))+ | otherwise = Key (V.empty)+ where+ ek0 = vkey+ ekN16 = reverse $ snd $ foldl (generateFold generate16) (ek0, []) [1..10]++ ekN24 =+ let (lk, acc) = foldl (generateFold generate24) (ek0, []) [1..7] in+ let nk = generate16 lk 8 in+ reverse (nk : acc)++ ekN32 =+ let (lk, acc) = foldl (generateFold generate32) (ek0, []) [1..6] in+ let nk = generate16 lk 7 in+ reverse (nk : acc)++ generateFold gen (prevk, accK) it = let nk = gen prevk it in (nk, nk : accK)++ generate16 prevk it =+ let len = V.length prevk in+ let v0 = cR0 it (V.unsafeIndex prevk $ len - 4)+ (V.unsafeIndex prevk $ len - 3)+ (V.unsafeIndex prevk $ len - 2)+ (V.unsafeIndex prevk $ len - 1) in+ let eg0@(e0,e1,e2,e3) = xorVector prevk 0 v0 in+ let eg1@(e4,e5,e6,e7) = xorVector prevk 4 eg0 in+ let eg2@(e8,e9,e10,e11) = xorVector prevk 8 eg1 in+ let (e12,e13,e14,e15) = xorVector prevk 12 eg2 in+ V.fromList [e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15]++ generate24 prevk it =+ let len = V.length prevk in+ let v0 = cR0 it (V.unsafeIndex prevk $ len - 4)+ (V.unsafeIndex prevk $ len - 3)+ (V.unsafeIndex prevk $ len - 2)+ (V.unsafeIndex prevk $ len - 1) in+ let eg0@(e0,e1,e2,e3) = xorVector prevk 0 v0 in+ let eg1@(e4,e5,e6,e7) = xorVector prevk 4 eg0 in+ let eg2@(e8,e9,e10,e11) = xorVector prevk 8 eg1 in+ let eg3@(e12,e13,e14,e15) = xorVector prevk 12 eg2 in+ let eg4@(e16,e17,e18,e19) = xorVector prevk 16 eg3 in+ let (e20,e21,e22,e23) = xorVector prevk 20 eg4 in+ V.fromList [e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16,e17,e18,e19,e20,e21,e22,e23]++ generate32 prevk it =+ let len = V.length prevk in+ let v0 = cR0 it (V.unsafeIndex prevk $ len - 4)+ (V.unsafeIndex prevk $ len - 3)+ (V.unsafeIndex prevk $ len - 2)+ (V.unsafeIndex prevk $ len - 1) in+ let eg0@(e0,e1,e2,e3) = xorVector prevk 0 v0 in+ let eg1@(e4,e5,e6,e7) = xorVector prevk 4 eg0 in+ let eg2@(e8,e9,e10,e11) = xorVector prevk 8 eg1 in+ let eg3@(e12,e13,e14,e15) = xorVector prevk 12 eg2 in+ let eg4@(e16,e17,e18,e19) = xorSboxVector prevk 16 eg3 in+ let eg5@(e20,e21,e22,e23) = xorVector prevk 20 eg4 in+ let eg6@(e24,e25,e26,e27) = xorVector prevk 24 eg5 in+ let (e28,e29,e30,e31) = xorVector prevk 28 eg6 in+ V.fromList [e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15,e16+ ,e17,e18,e19,e20,e21,e22,e23,e24,e25,e26,e27,e28,e29,e30,e31]++ xorVector k i (t0,t1,t2,t3) =+ ( V.unsafeIndex k (i+0) `xor` t0+ , V.unsafeIndex k (i+1) `xor` t1+ , V.unsafeIndex k (i+2) `xor` t2+ , V.unsafeIndex k (i+3) `xor` t3+ )++ xorSboxVector k i (t0,t1,t2,t3) =+ ( V.unsafeIndex k (i+0) `xor` sbox t0+ , V.unsafeIndex k (i+1) `xor` sbox t1+ , V.unsafeIndex k (i+2) `xor` sbox t2+ , V.unsafeIndex k (i+3) `xor` sbox t3+ )++ cR0 it r0 r1 r2 r3 =+ (sbox r1 `xor` rcon it, sbox r2, sbox r3, sbox r0)++{-# INLINE shiftRows #-}+shiftRows :: AESState -> IO ()+shiftRows blk = do+ r32 blk 0 >>= w32 blk 0 . msbox32+ r32 blk 1 >>= \t1 -> w32 blk 1 $ rotateR (msbox32 t1) 8+ r32 blk 2 >>= \t2 -> w32 blk 2 $ rotateR (msbox32 t2) 16+ r32 blk 3 >>= \t3 -> w32 blk 3 $ rotateR (msbox32 t3) 24++{-# INLINE addRoundKey #-}+addRoundKey :: Key -> Int -> AESState -> IO ()+addRoundKey (Key key) i blk = forM_ [0..15] $ \n -> do+ r8 blk n >>= \v1 -> w8 blk n $ v1 `xor` V.unsafeIndex key (16 * i + swapIndex n)++{-# INLINE mixColumns #-}+mixColumns :: AESState -> IO ()+mixColumns state = pr 0 >> pr 1 >> pr 2 >> pr 3+ where+ {-# INLINE pr #-}+ pr i = do+ cpy0 <- r8 state (0 * 4 + i)+ cpy1 <- r8 state (1 * 4 + i)+ cpy2 <- r8 state (2 * 4 + i)+ cpy3 <- r8 state (3 * 4 + i)++ let state0 = gm2 cpy0 `xor` gm1 cpy3 `xor` gm1 cpy2 `xor` gm3 cpy1+ let state4 = gm2 cpy1 `xor` gm1 cpy0 `xor` gm1 cpy3 `xor` gm3 cpy2+ let state8 = gm2 cpy2 `xor` gm1 cpy1 `xor` gm1 cpy0 `xor` gm3 cpy3+ let state12 = gm2 cpy3 `xor` gm1 cpy2 `xor` gm1 cpy1 `xor` gm3 cpy0++ w8 state (0 * 4 + i) state0+ w8 state (1 * 4 + i) state4+ w8 state (2 * 4 + i) state8+ w8 state (3 * 4 + i) state12+ {-# INLINE gm1 #-}+ gm1 a = a++{-# INLINE shiftRowsInv #-}+shiftRowsInv :: AESState -> IO ()+shiftRowsInv blk = do+ r32 blk 0 >>= w32 blk 0 . mrsbox32+ r32 blk 1 >>= \t1 -> w32 blk 1 $ mrsbox32 $ rotateL t1 8+ r32 blk 2 >>= \t2 -> w32 blk 2 $ mrsbox32 $ rotateL t2 16+ r32 blk 3 >>= \t3 -> w32 blk 3 $ mrsbox32 $ rotateL t3 24++{-# INLINE mixColumnsInv #-}+mixColumnsInv :: AESState -> IO ()+mixColumnsInv state = pr 0 >> pr 1 >> pr 2 >> pr 3+ where+ {-# INLINE pr #-}+ pr i = do+ cpy0 <- r8 state (0 * 4 + i)+ cpy1 <- r8 state (1 * 4 + i)+ cpy2 <- r8 state (2 * 4 + i)+ cpy3 <- r8 state (3 * 4 + i)++ let state0 = gm14 cpy0 `xor` gm9 cpy3 `xor` gm13 cpy2 `xor` gm11 cpy1+ let state4 = gm14 cpy1 `xor` gm9 cpy0 `xor` gm13 cpy3 `xor` gm11 cpy2+ let state8 = gm14 cpy2 `xor` gm9 cpy1 `xor` gm13 cpy0 `xor` gm11 cpy3+ let state12 = gm14 cpy3 `xor` gm9 cpy2 `xor` gm13 cpy1 `xor` gm11 cpy0++ w8 state (0 * 4 + i) state0+ w8 state (1 * 4 + i) state4+ w8 state (2 * 4 + i) state8+ w8 state (3 * 4 + i) state12++{-# INLINE r8 #-}+r8 :: AESState -> Int -> IO Word8+r8 = readByteArray++{-# INLINE w8 #-}+w8 :: AESState -> Int -> Word8 -> IO ()+w8 = writeByteArray++{-# INLINE r32 #-}+r32 :: AESState -> Int -> IO Word32+r32 = readByteArray++{-# INLINE w32 #-}+w32 :: AESState -> Int -> Word32 -> IO ()+w32 = writeByteArray++msbox32 :: Word32 -> Word32+msbox32 w = sbox4 a .|. sbox3 b .|. sbox2 c .|. sbox1 d+ where+ a = fromIntegral (w `shiftR` 24)+ b = fromIntegral (w `shiftR` 16)+ c = fromIntegral (w `shiftR` 8)+ d = fromIntegral w++mrsbox32 :: Word32 -> Word32+mrsbox32 w = fromIntegral (rsbox a) `shiftL` 24 .|.+ fromIntegral (rsbox b) `shiftL` 16 .|.+ fromIntegral (rsbox c) `shiftL` 8 .|.+ fromIntegral (rsbox d)+ where+ a = fromIntegral (w `shiftR` 24)+ b = fromIntegral (w `shiftR` 16)+ c = fromIntegral (w `shiftR` 8)+ d = fromIntegral w+++{-# INLINE swapBlock #-}+swapBlock :: ByteString -> AESState -> IO ()+swapBlock b blk = do -- V.generate 16 (\i -> B.unsafeIndex b $ swapIndex i)+ forM_ [0..15] $ \i -> w8 blk i $ B.unsafeIndex b $ swapIndex i++{-# INLINE swapBlockInv #-}+swapBlockInv :: AESState -> Ptr Word8 -> IO ()+swapBlockInv blk ptr = forM_ [0..15] $ \i -> r8 blk (swapIndex i) >>= pokeByteOff ptr i++{-# INLINE sbox #-}+sbox :: Word8 -> Word8+sbox (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x63\x7c\x77\x7b\xf2\x6b\x6f\xc5\+ \\x30\x01\x67\x2b\xfe\xd7\xab\x76\+ \\xca\x82\xc9\x7d\xfa\x59\x47\xf0\+ \\xad\xd4\xa2\xaf\x9c\xa4\x72\xc0\+ \\xb7\xfd\x93\x26\x36\x3f\xf7\xcc\+ \\x34\xa5\xe5\xf1\x71\xd8\x31\x15\+ \\x04\xc7\x23\xc3\x18\x96\x05\x9a\+ \\x07\x12\x80\xe2\xeb\x27\xb2\x75\+ \\x09\x83\x2c\x1a\x1b\x6e\x5a\xa0\+ \\x52\x3b\xd6\xb3\x29\xe3\x2f\x84\+ \\x53\xd1\x00\xed\x20\xfc\xb1\x5b\+ \\x6a\xcb\xbe\x39\x4a\x4c\x58\xcf\+ \\xd0\xef\xaa\xfb\x43\x4d\x33\x85\+ \\x45\xf9\x02\x7f\x50\x3c\x9f\xa8\+ \\x51\xa3\x40\x8f\x92\x9d\x38\xf5\+ \\xbc\xb6\xda\x21\x10\xff\xf3\xd2\+ \\xcd\x0c\x13\xec\x5f\x97\x44\x17\+ \\xc4\xa7\x7e\x3d\x64\x5d\x19\x73\+ \\x60\x81\x4f\xdc\x22\x2a\x90\x88\+ \\x46\xee\xb8\x14\xde\x5e\x0b\xdb\+ \\xe0\x32\x3a\x0a\x49\x06\x24\x5c\+ \\xc2\xd3\xac\x62\x91\x95\xe4\x79\+ \\xe7\xc8\x37\x6d\x8d\xd5\x4e\xa9\+ \\x6c\x56\xf4\xea\x65\x7a\xae\x08\+ \\xba\x78\x25\x2e\x1c\xa6\xb4\xc6\+ \\xe8\xdd\x74\x1f\x4b\xbd\x8b\x8a\+ \\x70\x3e\xb5\x66\x48\x03\xf6\x0e\+ \\x61\x35\x57\xb9\x86\xc1\x1d\x9e\+ \\xe1\xf8\x98\x11\x69\xd9\x8e\x94\+ \\x9b\x1e\x87\xe9\xce\x55\x28\xdf\+ \\x8c\xa1\x89\x0d\xbf\xe6\x42\x68\+ \\x41\x99\x2d\x0f\xb0\x54\xbb\x16"#++{-# INLINE sbox1 #-}+{-# INLINE sbox2 #-}+{-# INLINE sbox3 #-}+{-# INLINE sbox4 #-}+sbox1, sbox2, sbox3, sbox4 :: Word8 -> Word32+sbox1 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))+ where !(Table table) = sbox1Tab+sbox2 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))+ where !(Table table) = sbox2Tab+sbox3 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))+ where !(Table table) = sbox3Tab+sbox4 (W8# w) = W32# (indexWord32OffAddr# table (word2Int# w))+ where !(Table table) = sbox4Tab++sbox1Tab, sbox2Tab, sbox3Tab, sbox4Tab :: Table+sbox1Tab = if getSystemEndianness == LittleEndian then sbox_x000 else sbox_000x+sbox2Tab = if getSystemEndianness == LittleEndian then sbox_0x00 else sbox_00x0+sbox3Tab = if getSystemEndianness == LittleEndian then sbox_00x0 else sbox_0x00+sbox4Tab = if getSystemEndianness == LittleEndian then sbox_000x else sbox_x000++data Table = Table !Addr#++sbox_000x, sbox_00x0, sbox_0x00, sbox_x000 :: Table+sbox_000x = Table+ "\x00\x00\x00\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\+ \\x00\x00\x00\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\+ \\x00\x00\x00\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\+ \\x00\x00\x00\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\+ \\x00\x00\x00\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\+ \\x00\x00\x00\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\+ \\x00\x00\x00\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\+ \\x00\x00\x00\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\+ \\x00\x00\x00\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\+ \\x00\x00\x00\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\+ \\x00\x00\x00\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\+ \\x00\x00\x00\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\+ \\x00\x00\x00\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\+ \\x00\x00\x00\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\+ \\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\+ \\x00\x00\x00\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\+ \\x00\x00\x00\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\+ \\x00\x00\x00\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\+ \\x00\x00\x00\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\+ \\x00\x00\x00\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\+ \\x00\x00\x00\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\+ \\x00\x00\x00\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\+ \\x00\x00\x00\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\+ \\x00\x00\x00\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\+ \\x00\x00\x00\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\+ \\x00\x00\x00\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\+ \\x00\x00\x00\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\+ \\x00\x00\x00\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\+ \\x00\x00\x00\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\+ \\x00\x00\x00\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\+ \\x00\x00\x00\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\+ \\x00\x00\x00\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\+ \\x00\x00\x00\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\+ \\x00\x00\x00\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\+ \\x00\x00\x00\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\+ \\x00\x00\x00\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\+ \\x00\x00\x00\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\+ \\x00\x00\x00\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\+ \\x00\x00\x00\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\+ \\x00\x00\x00\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\+ \\x00\x00\x00\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\+ \\x00\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\+ \\x00\x00\x00\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\+ \\x00\x00\x00\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\+ \\x00\x00\x00\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\+ \\x00\x00\x00\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\+ \\x00\x00\x00\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\+ \\x00\x00\x00\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\+ \\x00\x00\x00\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\+ \\x00\x00\x00\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\+ \\x00\x00\x00\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\+ \\x00\x00\x00\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\+ \\x00\x00\x00\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\+ \\x00\x00\x00\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\+ \\x00\x00\x00\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\+ \\x00\x00\x00\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\+ \\x00\x00\x00\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\+ \\x00\x00\x00\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\+ \\x00\x00\x00\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\+ \\x00\x00\x00\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\+ \\x00\x00\x00\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\+ \\x00\x00\x00\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\+ \\x00\x00\x00\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\+ \\x00\x00\x00\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16"#++sbox_00x0 = Table+ "\x00\x00\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\x00\+ \\x00\x00\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\x00\+ \\x00\x00\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\x00\+ \\x00\x00\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\x00\+ \\x00\x00\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\x00\+ \\x00\x00\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\x00\+ \\x00\x00\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\x00\+ \\x00\x00\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\x00\+ \\x00\x00\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\x00\+ \\x00\x00\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\x00\+ \\x00\x00\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\x00\+ \\x00\x00\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\x00\+ \\x00\x00\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\x00\+ \\x00\x00\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\x00\+ \\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\x00\+ \\x00\x00\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\x00\+ \\x00\x00\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\x00\+ \\x00\x00\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\x00\+ \\x00\x00\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\x00\+ \\x00\x00\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\x00\+ \\x00\x00\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\x00\+ \\x00\x00\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\x00\+ \\x00\x00\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\x00\+ \\x00\x00\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\x00\+ \\x00\x00\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\x00\+ \\x00\x00\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\x00\+ \\x00\x00\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\x00\+ \\x00\x00\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\x00\+ \\x00\x00\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\x00\+ \\x00\x00\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\x00\+ \\x00\x00\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\x00\+ \\x00\x00\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\x00\+ \\x00\x00\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\x00\+ \\x00\x00\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\x00\+ \\x00\x00\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\x00\+ \\x00\x00\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\x00\+ \\x00\x00\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\x00\+ \\x00\x00\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\x00\+ \\x00\x00\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\x00\+ \\x00\x00\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\x00\+ \\x00\x00\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\+ \\x00\x00\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\x00\+ \\x00\x00\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\x00\+ \\x00\x00\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\x00\+ \\x00\x00\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\x00\+ \\x00\x00\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\x00\+ \\x00\x00\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\x00\+ \\x00\x00\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\x00\+ \\x00\x00\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\x00\+ \\x00\x00\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\x00\+ \\x00\x00\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\x00\+ \\x00\x00\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\x00\+ \\x00\x00\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\x00\+ \\x00\x00\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\x00\+ \\x00\x00\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\x00\+ \\x00\x00\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\x00\+ \\x00\x00\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\x00\+ \\x00\x00\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\x00\+ \\x00\x00\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\x00\+ \\x00\x00\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\x00\+ \\x00\x00\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\x00\+ \\x00\x00\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\x00\+ \\x00\x00\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\x00\+ \\x00\x00\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16\x00"#++sbox_0x00 = Table+ "\x00\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\x00\x00\+ \\x00\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\x00\x00\+ \\x00\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\x00\x00\+ \\x00\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\x00\x00\+ \\x00\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\x00\x00\+ \\x00\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\x00\x00\+ \\x00\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\x00\x00\+ \\x00\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\x00\x00\+ \\x00\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\x00\x00\+ \\x00\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\x00\x00\+ \\x00\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\x00\x00\+ \\x00\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\x00\x00\+ \\x00\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\x00\x00\+ \\x00\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\x00\x00\+ \\x00\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\x00\x00\+ \\x00\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\x00\x00\+ \\x00\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\x00\x00\+ \\x00\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\x00\x00\+ \\x00\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\x00\x00\+ \\x00\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\x00\x00\+ \\x00\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\x00\x00\+ \\x00\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\x00\x00\+ \\x00\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\x00\x00\+ \\x00\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\x00\x00\+ \\x00\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\x00\x00\+ \\x00\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\x00\x00\+ \\x00\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\+ \\x00\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\x00\x00\+ \\x00\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\x00\x00\+ \\x00\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\x00\x00\+ \\x00\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\x00\x00\+ \\x00\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\x00\x00\+ \\x00\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\x00\x00\+ \\x00\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\x00\x00\+ \\x00\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\x00\x00\+ \\x00\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\x00\x00\+ \\x00\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\x00\x00\+ \\x00\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\x00\x00\+ \\x00\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\x00\x00\+ \\x00\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\x00\x00\+ \\x00\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\x00\+ \\x00\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\x00\x00\+ \\x00\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\x00\x00\+ \\x00\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\x00\x00\+ \\x00\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\x00\x00\+ \\x00\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\x00\x00\+ \\x00\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\x00\x00\+ \\x00\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\x00\x00\+ \\x00\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\x00\x00\+ \\x00\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\x00\x00\+ \\x00\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\x00\x00\+ \\x00\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\x00\x00\+ \\x00\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\x00\x00\+ \\x00\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\x00\x00\+ \\x00\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\x00\x00\+ \\x00\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\x00\x00\+ \\x00\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\x00\x00\+ \\x00\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\x00\x00\+ \\x00\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\x00\x00\+ \\x00\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\x00\x00\+ \\x00\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\x00\x00\+ \\x00\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\x00\x00\+ \\x00\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\x00\x00\+ \\x00\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16\x00\x00"#++sbox_x000 = Table+ "\x63\x00\x00\x00\x7c\x00\x00\x00\x77\x00\x00\x00\x7b\x00\x00\x00\+ \\xf2\x00\x00\x00\x6b\x00\x00\x00\x6f\x00\x00\x00\xc5\x00\x00\x00\+ \\x30\x00\x00\x00\x01\x00\x00\x00\x67\x00\x00\x00\x2b\x00\x00\x00\+ \\xfe\x00\x00\x00\xd7\x00\x00\x00\xab\x00\x00\x00\x76\x00\x00\x00\+ \\xca\x00\x00\x00\x82\x00\x00\x00\xc9\x00\x00\x00\x7d\x00\x00\x00\+ \\xfa\x00\x00\x00\x59\x00\x00\x00\x47\x00\x00\x00\xf0\x00\x00\x00\+ \\xad\x00\x00\x00\xd4\x00\x00\x00\xa2\x00\x00\x00\xaf\x00\x00\x00\+ \\x9c\x00\x00\x00\xa4\x00\x00\x00\x72\x00\x00\x00\xc0\x00\x00\x00\+ \\xb7\x00\x00\x00\xfd\x00\x00\x00\x93\x00\x00\x00\x26\x00\x00\x00\+ \\x36\x00\x00\x00\x3f\x00\x00\x00\xf7\x00\x00\x00\xcc\x00\x00\x00\+ \\x34\x00\x00\x00\xa5\x00\x00\x00\xe5\x00\x00\x00\xf1\x00\x00\x00\+ \\x71\x00\x00\x00\xd8\x00\x00\x00\x31\x00\x00\x00\x15\x00\x00\x00\+ \\x04\x00\x00\x00\xc7\x00\x00\x00\x23\x00\x00\x00\xc3\x00\x00\x00\+ \\x18\x00\x00\x00\x96\x00\x00\x00\x05\x00\x00\x00\x9a\x00\x00\x00\+ \\x07\x00\x00\x00\x12\x00\x00\x00\x80\x00\x00\x00\xe2\x00\x00\x00\+ \\xeb\x00\x00\x00\x27\x00\x00\x00\xb2\x00\x00\x00\x75\x00\x00\x00\+ \\x09\x00\x00\x00\x83\x00\x00\x00\x2c\x00\x00\x00\x1a\x00\x00\x00\+ \\x1b\x00\x00\x00\x6e\x00\x00\x00\x5a\x00\x00\x00\xa0\x00\x00\x00\+ \\x52\x00\x00\x00\x3b\x00\x00\x00\xd6\x00\x00\x00\xb3\x00\x00\x00\+ \\x29\x00\x00\x00\xe3\x00\x00\x00\x2f\x00\x00\x00\x84\x00\x00\x00\+ \\x53\x00\x00\x00\xd1\x00\x00\x00\x00\x00\x00\x00\xed\x00\x00\x00\+ \\x20\x00\x00\x00\xfc\x00\x00\x00\xb1\x00\x00\x00\x5b\x00\x00\x00\+ \\x6a\x00\x00\x00\xcb\x00\x00\x00\xbe\x00\x00\x00\x39\x00\x00\x00\+ \\x4a\x00\x00\x00\x4c\x00\x00\x00\x58\x00\x00\x00\xcf\x00\x00\x00\+ \\xd0\x00\x00\x00\xef\x00\x00\x00\xaa\x00\x00\x00\xfb\x00\x00\x00\+ \\x43\x00\x00\x00\x4d\x00\x00\x00\x33\x00\x00\x00\x85\x00\x00\x00\+ \\x45\x00\x00\x00\xf9\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00\+ \\x50\x00\x00\x00\x3c\x00\x00\x00\x9f\x00\x00\x00\xa8\x00\x00\x00\+ \\x51\x00\x00\x00\xa3\x00\x00\x00\x40\x00\x00\x00\x8f\x00\x00\x00\+ \\x92\x00\x00\x00\x9d\x00\x00\x00\x38\x00\x00\x00\xf5\x00\x00\x00\+ \\xbc\x00\x00\x00\xb6\x00\x00\x00\xda\x00\x00\x00\x21\x00\x00\x00\+ \\x10\x00\x00\x00\xff\x00\x00\x00\xf3\x00\x00\x00\xd2\x00\x00\x00\+ \\xcd\x00\x00\x00\x0c\x00\x00\x00\x13\x00\x00\x00\xec\x00\x00\x00\+ \\x5f\x00\x00\x00\x97\x00\x00\x00\x44\x00\x00\x00\x17\x00\x00\x00\+ \\xc4\x00\x00\x00\xa7\x00\x00\x00\x7e\x00\x00\x00\x3d\x00\x00\x00\+ \\x64\x00\x00\x00\x5d\x00\x00\x00\x19\x00\x00\x00\x73\x00\x00\x00\+ \\x60\x00\x00\x00\x81\x00\x00\x00\x4f\x00\x00\x00\xdc\x00\x00\x00\+ \\x22\x00\x00\x00\x2a\x00\x00\x00\x90\x00\x00\x00\x88\x00\x00\x00\+ \\x46\x00\x00\x00\xee\x00\x00\x00\xb8\x00\x00\x00\x14\x00\x00\x00\+ \\xde\x00\x00\x00\x5e\x00\x00\x00\x0b\x00\x00\x00\xdb\x00\x00\x00\+ \\xe0\x00\x00\x00\x32\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\x00\x00\+ \\x49\x00\x00\x00\x06\x00\x00\x00\x24\x00\x00\x00\x5c\x00\x00\x00\+ \\xc2\x00\x00\x00\xd3\x00\x00\x00\xac\x00\x00\x00\x62\x00\x00\x00\+ \\x91\x00\x00\x00\x95\x00\x00\x00\xe4\x00\x00\x00\x79\x00\x00\x00\+ \\xe7\x00\x00\x00\xc8\x00\x00\x00\x37\x00\x00\x00\x6d\x00\x00\x00\+ \\x8d\x00\x00\x00\xd5\x00\x00\x00\x4e\x00\x00\x00\xa9\x00\x00\x00\+ \\x6c\x00\x00\x00\x56\x00\x00\x00\xf4\x00\x00\x00\xea\x00\x00\x00\+ \\x65\x00\x00\x00\x7a\x00\x00\x00\xae\x00\x00\x00\x08\x00\x00\x00\+ \\xba\x00\x00\x00\x78\x00\x00\x00\x25\x00\x00\x00\x2e\x00\x00\x00\+ \\x1c\x00\x00\x00\xa6\x00\x00\x00\xb4\x00\x00\x00\xc6\x00\x00\x00\+ \\xe8\x00\x00\x00\xdd\x00\x00\x00\x74\x00\x00\x00\x1f\x00\x00\x00\+ \\x4b\x00\x00\x00\xbd\x00\x00\x00\x8b\x00\x00\x00\x8a\x00\x00\x00\+ \\x70\x00\x00\x00\x3e\x00\x00\x00\xb5\x00\x00\x00\x66\x00\x00\x00\+ \\x48\x00\x00\x00\x03\x00\x00\x00\xf6\x00\x00\x00\x0e\x00\x00\x00\+ \\x61\x00\x00\x00\x35\x00\x00\x00\x57\x00\x00\x00\xb9\x00\x00\x00\+ \\x86\x00\x00\x00\xc1\x00\x00\x00\x1d\x00\x00\x00\x9e\x00\x00\x00\+ \\xe1\x00\x00\x00\xf8\x00\x00\x00\x98\x00\x00\x00\x11\x00\x00\x00\+ \\x69\x00\x00\x00\xd9\x00\x00\x00\x8e\x00\x00\x00\x94\x00\x00\x00\+ \\x9b\x00\x00\x00\x1e\x00\x00\x00\x87\x00\x00\x00\xe9\x00\x00\x00\+ \\xce\x00\x00\x00\x55\x00\x00\x00\x28\x00\x00\x00\xdf\x00\x00\x00\+ \\x8c\x00\x00\x00\xa1\x00\x00\x00\x89\x00\x00\x00\x0d\x00\x00\x00\+ \\xbf\x00\x00\x00\xe6\x00\x00\x00\x42\x00\x00\x00\x68\x00\x00\x00\+ \\x41\x00\x00\x00\x99\x00\x00\x00\x2d\x00\x00\x00\x0f\x00\x00\x00\+ \\xb0\x00\x00\x00\x54\x00\x00\x00\xbb\x00\x00\x00\x16\x00\x00\x00"#+++{-# INLINE rsbox #-}+rsbox :: Word8 -> Word8+rsbox (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x52\x09\x6a\xd5\x30\x36\xa5\x38\+ \\xbf\x40\xa3\x9e\x81\xf3\xd7\xfb\+ \\x7c\xe3\x39\x82\x9b\x2f\xff\x87\+ \\x34\x8e\x43\x44\xc4\xde\xe9\xcb\+ \\x54\x7b\x94\x32\xa6\xc2\x23\x3d\+ \\xee\x4c\x95\x0b\x42\xfa\xc3\x4e\+ \\x08\x2e\xa1\x66\x28\xd9\x24\xb2\+ \\x76\x5b\xa2\x49\x6d\x8b\xd1\x25\+ \\x72\xf8\xf6\x64\x86\x68\x98\x16\+ \\xd4\xa4\x5c\xcc\x5d\x65\xb6\x92\+ \\x6c\x70\x48\x50\xfd\xed\xb9\xda\+ \\x5e\x15\x46\x57\xa7\x8d\x9d\x84\+ \\x90\xd8\xab\x00\x8c\xbc\xd3\x0a\+ \\xf7\xe4\x58\x05\xb8\xb3\x45\x06\+ \\xd0\x2c\x1e\x8f\xca\x3f\x0f\x02\+ \\xc1\xaf\xbd\x03\x01\x13\x8a\x6b\+ \\x3a\x91\x11\x41\x4f\x67\xdc\xea\+ \\x97\xf2\xcf\xce\xf0\xb4\xe6\x73\+ \\x96\xac\x74\x22\xe7\xad\x35\x85\+ \\xe2\xf9\x37\xe8\x1c\x75\xdf\x6e\+ \\x47\xf1\x1a\x71\x1d\x29\xc5\x89\+ \\x6f\xb7\x62\x0e\xaa\x18\xbe\x1b\+ \\xfc\x56\x3e\x4b\xc6\xd2\x79\x20\+ \\x9a\xdb\xc0\xfe\x78\xcd\x5a\xf4\+ \\x1f\xdd\xa8\x33\x88\x07\xc7\x31\+ \\xb1\x12\x10\x59\x27\x80\xec\x5f\+ \\x60\x51\x7f\xa9\x19\xb5\x4a\x0d\+ \\x2d\xe5\x7a\x9f\x93\xc9\x9c\xef\+ \\xa0\xe0\x3b\x4d\xae\x2a\xf5\xb0\+ \\xc8\xeb\xbb\x3c\x83\x53\x99\x61\+ \\x17\x2b\x04\x7e\xba\x77\xd6\x26\+ \\xe1\x69\x14\x63\x55\x21\x0c\x7d"#++{-# INLINE rcon #-}+rcon :: Int -> Word8+rcon (I# i) = W8# (indexWord8OffAddr# table (i `remInt#` 51#))+ where !table =+ "\x8d\x01\x02\x04\x08\x10\x20\x40\+ \\x80\x1b\x36\x6c\xd8\xab\x4d\x9a\+ \\x2f\x5e\xbc\x63\xc6\x97\x35\x6a\+ \\xd4\xb3\x7d\xfa\xef\xc5\x91\x39\+ \\x72\xe4\xd3\xbd\x61\xc2\x9f\x25\+ \\x4a\x94\x33\x66\xcc\x83\x1d\x3a\+ \\x74\xe8\xcb"#++{-# INLINE gm2 #-}+{-# INLINE gm3 #-}+{-# INLINE gm9 #-}+{-# INLINE gm11 #-}+{-# INLINE gm13 #-}+{-# INLINE gm14 #-}+gm2, gm3, gm9, gm11, gm13, gm14 :: Word8 -> Word8+gm2 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x00\x02\x04\x06\x08\x0a\x0c\x0e\+ \\x10\x12\x14\x16\x18\x1a\x1c\x1e\+ \\x20\x22\x24\x26\x28\x2a\x2c\x2e\+ \\x30\x32\x34\x36\x38\x3a\x3c\x3e\+ \\x40\x42\x44\x46\x48\x4a\x4c\x4e\+ \\x50\x52\x54\x56\x58\x5a\x5c\x5e\+ \\x60\x62\x64\x66\x68\x6a\x6c\x6e\+ \\x70\x72\x74\x76\x78\x7a\x7c\x7e\+ \\x80\x82\x84\x86\x88\x8a\x8c\x8e\+ \\x90\x92\x94\x96\x98\x9a\x9c\x9e\+ \\xa0\xa2\xa4\xa6\xa8\xaa\xac\xae\+ \\xb0\xb2\xb4\xb6\xb8\xba\xbc\xbe\+ \\xc0\xc2\xc4\xc6\xc8\xca\xcc\xce\+ \\xd0\xd2\xd4\xd6\xd8\xda\xdc\xde\+ \\xe0\xe2\xe4\xe6\xe8\xea\xec\xee\+ \\xf0\xf2\xf4\xf6\xf8\xfa\xfc\xfe\+ \\x1b\x19\x1f\x1d\x13\x11\x17\x15\+ \\x0b\x09\x0f\x0d\x03\x01\x07\x05\+ \\x3b\x39\x3f\x3d\x33\x31\x37\x35\+ \\x2b\x29\x2f\x2d\x23\x21\x27\x25\+ \\x5b\x59\x5f\x5d\x53\x51\x57\x55\+ \\x4b\x49\x4f\x4d\x43\x41\x47\x45\+ \\x7b\x79\x7f\x7d\x73\x71\x77\x75\+ \\x6b\x69\x6f\x6d\x63\x61\x67\x65\+ \\x9b\x99\x9f\x9d\x93\x91\x97\x95\+ \\x8b\x89\x8f\x8d\x83\x81\x87\x85\+ \\xbb\xb9\xbf\xbd\xb3\xb1\xb7\xb5\+ \\xab\xa9\xaf\xad\xa3\xa1\xa7\xa5\+ \\xdb\xd9\xdf\xdd\xd3\xd1\xd7\xd5\+ \\xcb\xc9\xcf\xcd\xc3\xc1\xc7\xc5\+ \\xfb\xf9\xff\xfd\xf3\xf1\xf7\xf5\+ \\xeb\xe9\xef\xed\xe3\xe1\xe7\xe5"#++gm3 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x00\x03\x06\x05\x0c\x0f\x0a\x09\+ \\x18\x1b\x1e\x1d\x14\x17\x12\x11\+ \\x30\x33\x36\x35\x3c\x3f\x3a\x39\+ \\x28\x2b\x2e\x2d\x24\x27\x22\x21\+ \\x60\x63\x66\x65\x6c\x6f\x6a\x69\+ \\x78\x7b\x7e\x7d\x74\x77\x72\x71\+ \\x50\x53\x56\x55\x5c\x5f\x5a\x59\+ \\x48\x4b\x4e\x4d\x44\x47\x42\x41\+ \\xc0\xc3\xc6\xc5\xcc\xcf\xca\xc9\+ \\xd8\xdb\xde\xdd\xd4\xd7\xd2\xd1\+ \\xf0\xf3\xf6\xf5\xfc\xff\xfa\xf9\+ \\xe8\xeb\xee\xed\xe4\xe7\xe2\xe1\+ \\xa0\xa3\xa6\xa5\xac\xaf\xaa\xa9\+ \\xb8\xbb\xbe\xbd\xb4\xb7\xb2\xb1\+ \\x90\x93\x96\x95\x9c\x9f\x9a\x99\+ \\x88\x8b\x8e\x8d\x84\x87\x82\x81\+ \\x9b\x98\x9d\x9e\x97\x94\x91\x92\+ \\x83\x80\x85\x86\x8f\x8c\x89\x8a\+ \\xab\xa8\xad\xae\xa7\xa4\xa1\xa2\+ \\xb3\xb0\xb5\xb6\xbf\xbc\xb9\xba\+ \\xfb\xf8\xfd\xfe\xf7\xf4\xf1\xf2\+ \\xe3\xe0\xe5\xe6\xef\xec\xe9\xea\+ \\xcb\xc8\xcd\xce\xc7\xc4\xc1\xc2\+ \\xd3\xd0\xd5\xd6\xdf\xdc\xd9\xda\+ \\x5b\x58\x5d\x5e\x57\x54\x51\x52\+ \\x43\x40\x45\x46\x4f\x4c\x49\x4a\+ \\x6b\x68\x6d\x6e\x67\x64\x61\x62\+ \\x73\x70\x75\x76\x7f\x7c\x79\x7a\+ \\x3b\x38\x3d\x3e\x37\x34\x31\x32\+ \\x23\x20\x25\x26\x2f\x2c\x29\x2a\+ \\x0b\x08\x0d\x0e\x07\x04\x01\x02\+ \\x13\x10\x15\x16\x1f\x1c\x19\x1a"#++gm9 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x00\x09\x12\x1b\x24\x2d\x36\x3f\+ \\x48\x41\x5a\x53\x6c\x65\x7e\x77\+ \\x90\x99\x82\x8b\xb4\xbd\xa6\xaf\+ \\xd8\xd1\xca\xc3\xfc\xf5\xee\xe7\+ \\x3b\x32\x29\x20\x1f\x16\x0d\x04\+ \\x73\x7a\x61\x68\x57\x5e\x45\x4c\+ \\xab\xa2\xb9\xb0\x8f\x86\x9d\x94\+ \\xe3\xea\xf1\xf8\xc7\xce\xd5\xdc\+ \\x76\x7f\x64\x6d\x52\x5b\x40\x49\+ \\x3e\x37\x2c\x25\x1a\x13\x08\x01\+ \\xe6\xef\xf4\xfd\xc2\xcb\xd0\xd9\+ \\xae\xa7\xbc\xb5\x8a\x83\x98\x91\+ \\x4d\x44\x5f\x56\x69\x60\x7b\x72\+ \\x05\x0c\x17\x1e\x21\x28\x33\x3a\+ \\xdd\xd4\xcf\xc6\xf9\xf0\xeb\xe2\+ \\x95\x9c\x87\x8e\xb1\xb8\xa3\xaa\+ \\xec\xe5\xfe\xf7\xc8\xc1\xda\xd3\+ \\xa4\xad\xb6\xbf\x80\x89\x92\x9b\+ \\x7c\x75\x6e\x67\x58\x51\x4a\x43\+ \\x34\x3d\x26\x2f\x10\x19\x02\x0b\+ \\xd7\xde\xc5\xcc\xf3\xfa\xe1\xe8\+ \\x9f\x96\x8d\x84\xbb\xb2\xa9\xa0\+ \\x47\x4e\x55\x5c\x63\x6a\x71\x78\+ \\x0f\x06\x1d\x14\x2b\x22\x39\x30\+ \\x9a\x93\x88\x81\xbe\xb7\xac\xa5\+ \\xd2\xdb\xc0\xc9\xf6\xff\xe4\xed\+ \\x0a\x03\x18\x11\x2e\x27\x3c\x35\+ \\x42\x4b\x50\x59\x66\x6f\x74\x7d\+ \\xa1\xa8\xb3\xba\x85\x8c\x97\x9e\+ \\xe9\xe0\xfb\xf2\xcd\xc4\xdf\xd6\+ \\x31\x38\x23\x2a\x15\x1c\x07\x0e\+ \\x79\x70\x6b\x62\x5d\x54\x4f\x46"#++gm11 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x00\x0b\x16\x1d\x2c\x27\x3a\x31\+ \\x58\x53\x4e\x45\x74\x7f\x62\x69\+ \\xb0\xbb\xa6\xad\x9c\x97\x8a\x81\+ \\xe8\xe3\xfe\xf5\xc4\xcf\xd2\xd9\+ \\x7b\x70\x6d\x66\x57\x5c\x41\x4a\+ \\x23\x28\x35\x3e\x0f\x04\x19\x12\+ \\xcb\xc0\xdd\xd6\xe7\xec\xf1\xfa\+ \\x93\x98\x85\x8e\xbf\xb4\xa9\xa2\+ \\xf6\xfd\xe0\xeb\xda\xd1\xcc\xc7\+ \\xae\xa5\xb8\xb3\x82\x89\x94\x9f\+ \\x46\x4d\x50\x5b\x6a\x61\x7c\x77\+ \\x1e\x15\x08\x03\x32\x39\x24\x2f\+ \\x8d\x86\x9b\x90\xa1\xaa\xb7\xbc\+ \\xd5\xde\xc3\xc8\xf9\xf2\xef\xe4\+ \\x3d\x36\x2b\x20\x11\x1a\x07\x0c\+ \\x65\x6e\x73\x78\x49\x42\x5f\x54\+ \\xf7\xfc\xe1\xea\xdb\xd0\xcd\xc6\+ \\xaf\xa4\xb9\xb2\x83\x88\x95\x9e\+ \\x47\x4c\x51\x5a\x6b\x60\x7d\x76\+ \\x1f\x14\x09\x02\x33\x38\x25\x2e\+ \\x8c\x87\x9a\x91\xa0\xab\xb6\xbd\+ \\xd4\xdf\xc2\xc9\xf8\xf3\xee\xe5\+ \\x3c\x37\x2a\x21\x10\x1b\x06\x0d\+ \\x64\x6f\x72\x79\x48\x43\x5e\x55\+ \\x01\x0a\x17\x1c\x2d\x26\x3b\x30\+ \\x59\x52\x4f\x44\x75\x7e\x63\x68\+ \\xb1\xba\xa7\xac\x9d\x96\x8b\x80\+ \\xe9\xe2\xff\xf4\xc5\xce\xd3\xd8\+ \\x7a\x71\x6c\x67\x56\x5d\x40\x4b\+ \\x22\x29\x34\x3f\x0e\x05\x18\x13\+ \\xca\xc1\xdc\xd7\xe6\xed\xf0\xfb\+ \\x92\x99\x84\x8f\xbe\xb5\xa8\xa3"#++gm13 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x00\x0d\x1a\x17\x34\x39\x2e\x23\+ \\x68\x65\x72\x7f\x5c\x51\x46\x4b\+ \\xd0\xdd\xca\xc7\xe4\xe9\xfe\xf3\+ \\xb8\xb5\xa2\xaf\x8c\x81\x96\x9b\+ \\xbb\xb6\xa1\xac\x8f\x82\x95\x98\+ \\xd3\xde\xc9\xc4\xe7\xea\xfd\xf0\+ \\x6b\x66\x71\x7c\x5f\x52\x45\x48\+ \\x03\x0e\x19\x14\x37\x3a\x2d\x20\+ \\x6d\x60\x77\x7a\x59\x54\x43\x4e\+ \\x05\x08\x1f\x12\x31\x3c\x2b\x26\+ \\xbd\xb0\xa7\xaa\x89\x84\x93\x9e\+ \\xd5\xd8\xcf\xc2\xe1\xec\xfb\xf6\+ \\xd6\xdb\xcc\xc1\xe2\xef\xf8\xf5\+ \\xbe\xb3\xa4\xa9\x8a\x87\x90\x9d\+ \\x06\x0b\x1c\x11\x32\x3f\x28\x25\+ \\x6e\x63\x74\x79\x5a\x57\x40\x4d\+ \\xda\xd7\xc0\xcd\xee\xe3\xf4\xf9\+ \\xb2\xbf\xa8\xa5\x86\x8b\x9c\x91\+ \\x0a\x07\x10\x1d\x3e\x33\x24\x29\+ \\x62\x6f\x78\x75\x56\x5b\x4c\x41\+ \\x61\x6c\x7b\x76\x55\x58\x4f\x42\+ \\x09\x04\x13\x1e\x3d\x30\x27\x2a\+ \\xb1\xbc\xab\xa6\x85\x88\x9f\x92\+ \\xd9\xd4\xc3\xce\xed\xe0\xf7\xfa\+ \\xb7\xba\xad\xa0\x83\x8e\x99\x94\+ \\xdf\xd2\xc5\xc8\xeb\xe6\xf1\xfc\+ \\x67\x6a\x7d\x70\x53\x5e\x49\x44\+ \\x0f\x02\x15\x18\x3b\x36\x21\x2c\+ \\x0c\x01\x16\x1b\x38\x35\x22\x2f\+ \\x64\x69\x7e\x73\x50\x5d\x4a\x47\+ \\xdc\xd1\xc6\xcb\xe8\xe5\xf2\xff\+ \\xb4\xb9\xae\xa3\x80\x8d\x9a\x97"#++gm14 (W8# w) = W8# (indexWord8OffAddr# table (word2Int# w))+ where !table =+ "\x00\x0e\x1c\x12\x38\x36\x24\x2a\+ \\x70\x7e\x6c\x62\x48\x46\x54\x5a\+ \\xe0\xee\xfc\xf2\xd8\xd6\xc4\xca\+ \\x90\x9e\x8c\x82\xa8\xa6\xb4\xba\+ \\xdb\xd5\xc7\xc9\xe3\xed\xff\xf1\+ \\xab\xa5\xb7\xb9\x93\x9d\x8f\x81\+ \\x3b\x35\x27\x29\x03\x0d\x1f\x11\+ \\x4b\x45\x57\x59\x73\x7d\x6f\x61\+ \\xad\xa3\xb1\xbf\x95\x9b\x89\x87\+ \\xdd\xd3\xc1\xcf\xe5\xeb\xf9\xf7\+ \\x4d\x43\x51\x5f\x75\x7b\x69\x67\+ \\x3d\x33\x21\x2f\x05\x0b\x19\x17\+ \\x76\x78\x6a\x64\x4e\x40\x52\x5c\+ \\x06\x08\x1a\x14\x3e\x30\x22\x2c\+ \\x96\x98\x8a\x84\xae\xa0\xb2\xbc\+ \\xe6\xe8\xfa\xf4\xde\xd0\xc2\xcc\+ \\x41\x4f\x5d\x53\x79\x77\x65\x6b\+ \\x31\x3f\x2d\x23\x09\x07\x15\x1b\+ \\xa1\xaf\xbd\xb3\x99\x97\x85\x8b\+ \\xd1\xdf\xcd\xc3\xe9\xe7\xf5\xfb\+ \\x9a\x94\x86\x88\xa2\xac\xbe\xb0\+ \\xea\xe4\xf6\xf8\xd2\xdc\xce\xc0\+ \\x7a\x74\x66\x68\x42\x4c\x5e\x50\+ \\x0a\x04\x16\x18\x32\x3c\x2e\x20\+ \\xec\xe2\xf0\xfe\xd4\xda\xc8\xc6\+ \\x9c\x92\x80\x8e\xa4\xaa\xb8\xb6\+ \\x0c\x02\x10\x1e\x34\x3a\x28\x26\+ \\x7c\x72\x60\x6e\x44\x4a\x58\x56\+ \\x37\x39\x2b\x25\x0f\x01\x13\x1d\+ \\x47\x49\x5b\x55\x7f\x71\x63\x6d\+ \\xd7\xd9\xcb\xc5\xef\xe1\xf3\xfd\+ \\xa7\xa9\xbb\xb5\x9f\x91\x83\x8d"#
+ Crypto/Cipher/AES/X86NI.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Crypto.Cipher.AES.X86NI+ ( encrypt+ , decrypt+ , encryptCBC+ , decryptCBC+ , initKey128+ ) where++import Foreign.Storable+import Foreign.Marshal.Alloc (alloca, allocaBytes)+import Foreign.Ptr+import Foreign.C.String+import Foreign.C.Types+import Data.ByteString (ByteString)+import Data.ByteString.Unsafe (unsafeUseAsCString)+import Data.ByteString.Internal (create, memcpy)+import Data.Bits (shiftR)+import qualified Data.ByteString as B++import System.IO.Unsafe++type IV = ByteString+newtype Key = Key ByteString++instance Storable Key where+ sizeOf _ = 16 * 11 * 2+ alignment _ = 16+ poke ptr (Key b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (16 * 11 * 2))+ peek ptr = Key `fmap` create (16*11*2) (\bptr -> memcpy bptr (castPtr ptr) (16 * 11 * 2))++foreign import ccall safe "aes.h aes_generate_key128"+ c_aes_generate_key128 :: Ptr Key -> CString -> IO ()++foreign import ccall safe "aes.h aes_encrypt"+ c_aes_encrypt :: CString -> Ptr Key -> CString -> CUInt -> IO ()++foreign import ccall safe "aes.h aes_decrypt"+ c_aes_decrypt :: CString -> Ptr Key -> CString -> CUInt -> IO ()++foreign import ccall safe "aes.h aes_encrypt_cbc"+ c_aes_encrypt_cbc :: CString -> Ptr Key -> CString -> CString -> CUInt -> IO ()++foreign import ccall safe "aes.h aes_decrypt_cbc"+ c_aes_decrypt_cbc :: CString -> Ptr Key -> CString -> CString -> CUInt -> IO ()++withKey :: Key -> (Ptr Key -> IO a) -> IO a+withKey k f = alloca (\ikey -> poke ikey k >> f ikey)++{-# NOINLINE initKey128 #-}+initKey128 :: ByteString -> Key+initKey128 b = unsafePerformIO $ unsafeUseAsCString b (\ikey ->+ alloca (\key -> c_aes_generate_key128 key ikey >> peek key))++{-# NOINLINE encrypt #-}+encrypt :: Key -> ByteString -> ByteString+encrypt key input = unsafePerformIO $ allocateAndMapBlocks input $ \blocks o i ->+ withKey key $ \k -> c_aes_encrypt o k i blocks++{-# NOINLINE decrypt #-}+decrypt :: Key -> ByteString -> ByteString+decrypt key input = unsafePerformIO $ allocateAndMapBlocks input $ \blocks o i ->+ withKey key $ \k -> c_aes_decrypt o k i blocks++{-# NOINLINE encryptCBC #-}+encryptCBC :: Key -> IV -> ByteString -> ByteString+encryptCBC key iv input = unsafePerformIO $ allocateAndMapBlocks input $ \blocks o i ->+ withKey key $ \k -> unsafeUseAsCString iv $ \ivptr -> c_aes_encrypt_cbc o k ivptr i blocks++{-# NOINLINE decryptCBC #-}+decryptCBC :: Key -> IV -> ByteString -> ByteString+decryptCBC key iv input = unsafePerformIO $ allocateAndMapBlocks input $ \blocks o i ->+ withKey key $ \k -> unsafeUseAsCString iv $ \ivptr -> c_aes_decrypt_cbc o k ivptr i blocks++allocateAndMapBlocks :: ByteString -> (CUInt -> Ptr CChar -> CString -> IO ()) -> IO ByteString+allocateAndMapBlocks input f = allocaBytes len (\output -> do unsafeUseAsCString input (f nbBlocks output)+ B.packCStringLen (output, len))+ where len = B.length input+ nbBlocks = fromIntegral (len `shiftR` 4)+
Crypto/Cipher/Camellia.hs view
@@ -10,7 +10,7 @@ module Crypto.Cipher.Camellia ( Key(..)- , initKey+ , initKey128 , encrypt , decrypt ) where@@ -177,8 +177,8 @@ in (w64tow128 kL, w64tow128 kR, w64tow128 kA, w64tow128 kB) -initKey :: B.ByteString -> Either String Key-initKey keyseed+initKey128 :: B.ByteString -> Either String Key+initKey128 keyseed | B.length keyseed /= 16 = Left "wrong key size" | otherwise = let (kL, _, kA, _) = setKeyInterim keyseed in
Crypto/Cipher/DH.hs view
@@ -18,7 +18,7 @@ , getShared ) where -import Number.ModArithmetic (exponantiation_rtl_binary)+import Number.ModArithmetic (exponantiation) import Number.Prime (generateSafePrime) import Number.Generate (generateOfSize) import Crypto.Types.PubKey.DH@@ -39,8 +39,8 @@ -- | generate a public number that is for the other party benefits. -- this number is usually called Y in DH text. generatePublic :: Params -> PrivateNumber -> PublicNumber-generatePublic (p,g) (PrivateNumber x) = PublicNumber $ exponantiation_rtl_binary g x p+generatePublic (p,g) (PrivateNumber x) = PublicNumber $ exponantiation g x p -- | generate a shared key using our private number and the other party public number getShared :: Params -> PrivateNumber -> PublicNumber -> SharedKey-getShared (p,_) (PrivateNumber x) (PublicNumber y) = SharedKey $ exponantiation_rtl_binary y x p+getShared (p,_) (PrivateNumber x) (PublicNumber y) = SharedKey $ exponantiation y x p
Crypto/Cipher/DSA.hs view
@@ -19,7 +19,7 @@ import Crypto.Random import Data.Maybe import Data.ByteString (ByteString)-import Number.ModArithmetic (exponantiation_rtl_binary, inverse)+import Number.ModArithmetic (exponantiation, inverse) import Number.Serialize import Number.Generate import Crypto.Types.PubKey.DSA@@ -64,4 +64,4 @@ v = ((expmod g u1 p) * (expmod y u2 p)) `mod` p `mod` q expmod :: Integer -> Integer -> Integer -> Integer-expmod = exponantiation_rtl_binary+expmod = exponantiation
Crypto/Cipher/RSA.hs view
@@ -25,7 +25,7 @@ import Crypto.Types.PubKey.RSA import Data.ByteString (ByteString) import qualified Data.ByteString as B-import Number.ModArithmetic (exponantiation_rtl_binary, inverse)+import Number.ModArithmetic (exponantiation, inverse) import Number.Prime (generatePrime) import Number.Serialize import Data.Maybe (fromJust)@@ -178,4 +178,4 @@ bytes = i2osp m expmod :: Integer -> Integer -> Integer -> Integer-expmod = exponantiation_rtl_binary+expmod = exponantiation
Number/ModArithmetic.hs view
@@ -8,6 +8,7 @@ module Number.ModArithmetic ( exponantiation_rtl_binary+ , exponantiation , inverse ) where @@ -27,6 +28,16 @@ sq x = (x * x) `mod` m loop !0 _ !a = a `mod` m loop !i !s !a = loop (i `shiftR` 1) (sq s) (if odd i then a * s else a)++-- | exponantiation computes modular exponantiation as b^e mod m+-- using repetitive squaring.+exponantiation :: Integer -> Integer -> Integer -> Integer+exponantiation b e m+ | e == 0 = 1+ | e == 1 = b `mod` m+ | even e = let p = (exponantiation b (e `div` 2) m) `mod` m+ in (p^(2::Integer)) `mod` m+ | otherwise = (b * exponantiation b (e-1) m) `mod` m -- | inverse computes the modular inverse as in g^(-1) mod m inverse :: Integer -> Integer -> Maybe Integer
Number/Polynomial.hs view
@@ -44,12 +44,15 @@ instance Show Polynomial where show (Polynomial p) = intercalate "+" $ map show $ V.toList p +toList :: Polynomial -> [Monomial] toList (Polynomial p) = V.toList p +fromList :: [Monomial] -> Polynomial fromList = Polynomial . V.fromList . reverse . sort . filterZero where filterZero = filter (\(Monomial _ v) -> v /= 0) +getWeight :: Polynomial -> Int -> Maybe Integer getWeight (Polynomial p) n = look 0 where plen = V.length p@@ -63,6 +66,7 @@ GT -> look (i+1) +mergePoly :: (Integer -> Integer -> Integer) -> Polynomial -> Polynomial -> Polynomial mergePoly f (Polynomial p1) (Polynomial p2) = fromList $ loop 0 0 where l1 = V.length p1@@ -74,18 +78,23 @@ | otherwise = let (coef, i1inc, i2inc) = addCoef (p1 ! i1) (p2 ! i2) in coef : loop (i1+i1inc) (i2+i2inc)- addCoef m1@(Monomial w1 v1) m2@(Monomial w2 v2) =+ addCoef m1@(Monomial w1 v1) (Monomial w2 v2) = case compare w1 w2 of LT -> (Monomial w2 (f 0 v2), 0, 1) EQ -> (Monomial w1 (f v1 v2), 1, 1) GT -> (m1, 1, 0) +addPoly :: Polynomial -> Polynomial -> Polynomial addPoly = mergePoly (+)++subPoly :: Polynomial -> Polynomial -> Polynomial subPoly = mergePoly (-) +negPoly :: Polynomial -> Polynomial negPoly (Polynomial p) = Polynomial $ V.map negateMonomial p where negateMonomial (Monomial w v) = Monomial w (-v) +mulPoly :: Polynomial -> Polynomial -> Polynomial mulPoly p1@(Polynomial v1) p2@(Polynomial v2) = fromList $ filter (\(Monomial _ v) -> v /= 0) $ map (\i -> Monomial i (c i)) $ reverse [0..(m+n)] where@@ -96,9 +105,11 @@ a = maybe 0 id . getWeight p1 b = maybe 0 id . getWeight p2 +squarePoly :: Polynomial -> Polynomial squarePoly p = p `mulPoly` p -expPoly p e = loop e+expPoly :: Polynomial -> Integer -> Polynomial+expPoly p e = loop p e where loop t 0 = t loop t n = loop (squarePoly t) (n-1)
Number/Prime.hs view
@@ -14,6 +14,7 @@ , findPrimeFromWith , primalityTestNaive , primalityTestMillerRabin+ , primalityTestFermat , isCoprime ) where @@ -21,15 +22,17 @@ import Data.Bits import Number.Generate import Number.Basic (sqrti, gcde_binary)-import Number.ModArithmetic (exponantiation_rtl_binary)+import Number.ModArithmetic (exponantiation) -- | returns if the number is probably prime. -- first a list of small primes are implicitely tested for divisibility,+-- then a fermat primality test is used with arbitrary numbers and -- then the Miller Rabin algorithm is used with an accuracy of 30 recursions isProbablyPrime :: CryptoRandomGen g => g -> Integer -> Either GenError (Bool, g) isProbablyPrime rng !n | any (\p -> p `divides` n) (filter (< n) smallPrimes) = Right (False, rng)- | otherwise = primalityTestMillerRabin rng 30 n+ | primalityTestFermat 50 (n`div`2) n = primalityTestMillerRabin rng 30 n+ | otherwise = Right (False, rng) -- | generate a prime number of the required bitsize generatePrime :: CryptoRandomGen g => g -> Int -> Either GenError (Integer, g)@@ -79,7 +82,7 @@ factorise !s !v | v `testBit` 0 = (s, v) | otherwise = factorise (s+1) (v `shiftR` 1)- expmod = exponantiation_rtl_binary+ expmod = exponantiation -- when iteration reach zero, we have a probable prime loop g _ 0 = Right (True, g) loop g t@(_,d) k = case generateBetween g 2 (n-2) of@@ -95,6 +98,17 @@ | x2 == 1 = Right (False, g) | x2 /= (n-1) = loop' g t km1 ((x2*x2) `mod` n) (r+1) | otherwise = loop g t km1++-- | Probabilitic Test using Fermat primility test.+-- Beware of Carmichael numbers that are Fermat liars, i.e. this test+-- is useless for them. always combines with some other test.+primalityTestFermat :: Int -- ^ number of iterations of the algorithm+ -> Integer -- ^ starting a+ -> Integer -- ^ number to test for primality+ -> Bool+primalityTestFermat n a p = and $ map expTest [a..(a+fromIntegral n)]+ where !pm1 = p-1+ expTest i = exponantiation i pm1 p == 1 -- | Test naively is integer is prime. -- while naive, we skip even number and stop iteration at i > sqrt(n)
− System/Endian.hs
@@ -1,17 +0,0 @@-{-# LANGUAGE CPP #-}-module System.Endian (littleEndian) where---#ifdef BIG_ENDIAN-littleEndian :: Bool-littleEndian = False-#elif defined(LITTLE_ENDIAN)-littleEndian :: Bool-littleEndian = True-#else--import System.Info (arch)--littleEndian :: Bool-littleEndian = arch /= "sparc" && arch /= "ppc"-#endif
− Tests.hs
@@ -1,518 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--import Test.HUnit ((~:), (~=?))-import qualified Test.HUnit as Unit--import Test.QuickCheck-import Test.QuickCheck.Test-import System.IO (hFlush, stdout)--import Control.Monad-import Control.Arrow (first)-import Control.Applicative ((<$>))--import Data.List (intercalate)-import Data.Char-import Data.Bits-import Data.Word-import qualified Data.Vector.Unboxed as V-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC--- for DSA-import qualified Crypto.Hash.SHA1 as SHA1---- numbers-import Number.ModArithmetic-import Number.Basic-import Number.Prime-import Number.Serialize--- ciphers/Kexch-import qualified Crypto.Cipher.AES as AES-import qualified Crypto.Cipher.RC4 as RC4-import qualified Crypto.Cipher.Camellia as Camellia-import qualified Crypto.Cipher.RSA as RSA-import qualified Crypto.Cipher.DSA as DSA-import qualified Crypto.Cipher.DH as DH-import Crypto.Random--encryptStream fi fc key plaintext = B.unpack $ snd $ fc (fi key) plaintext--encryptBlock fi fc key plaintext =- let e = fi (B.pack key) in- case e of- Right k -> B.unpack $ fc k plaintext- Left e -> error e--wordify :: [Char] -> [Word8]-wordify = map (toEnum . fromEnum)--vectors_aes128_enc =- [- ( [0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3,0x74,0xcf,0x86,0x7c,0xfb,0x47,0x38,0x59]- , B.replicate 16 0- , [0x6d,0x25,0x1e,0x69,0x44,0xb0,0x51,0xe0,0x4e,0xaa,0x6f,0xb4,0xdb,0xf7,0x84,0x65]- )- , ( replicate 16 0- , B.replicate 16 0- , [0x66,0xe9,0x4b,0xd4,0xef,0x8a,0x2c,0x3b,0x88,0x4c,0xfa,0x59,0xca,0x34,0x2b,0x2e]- )- , ( replicate 16 0- , B.replicate 16 1- , [0xe1,0x4d,0x5d,0x0e,0xe2,0x77,0x15,0xdf,0x08,0xb4,0x15,0x2b,0xa2,0x3d,0xa8,0xe0]- )- , ( replicate 16 1- , B.replicate 16 2- , [0x17,0xd6,0x14,0xf3,0x79,0xa9,0x35,0x90,0x77,0xe9,0x55,0x77,0xfd,0x31,0xc2,0x0a]- )- , ( replicate 16 2- , B.replicate 16 1- , [0x8f,0x42,0xc2,0x4b,0xee,0x6e,0x63,0x47,0x2b,0x16,0x5a,0xa9,0x41,0x31,0x2f,0x7c]- )- , ( replicate 16 3- , B.replicate 16 2- , [0x90,0x98,0x85,0xe4,0x77,0xbc,0x20,0xf5,0x8a,0x66,0x97,0x1d,0xa0,0xbc,0x75,0xe3]- )- ]--vectors_aes192_enc =- [- ( replicate 24 0- , B.replicate 16 0- , [0xaa,0xe0,0x69,0x92,0xac,0xbf,0x52,0xa3,0xe8,0xf4,0xa9,0x6e,0xc9,0x30,0x0b,0xd7]- )- , ( replicate 24 0- , B.replicate 16 1- , [0xcf,0x1e,0xce,0x3c,0x44,0xb0,0x78,0xfb,0x27,0xcb,0x0a,0x3e,0x07,0x1b,0x08,0x20]- )- , ( replicate 24 1- , B.replicate 16 2- , [0xeb,0x8c,0x17,0x30,0x90,0xc7,0x5b,0x77,0xd6,0x72,0xb4,0x57,0xa7,0x78,0xd9,0xd0]- )- , ( replicate 24 2- , B.replicate 16 1- , [0xf2,0xf0,0xae,0xd8,0xcd,0xc9,0x21,0xca,0x4b,0x55,0x84,0x5d,0xa4,0x15,0x21,0xc2]- )- , ( replicate 24 3- , B.replicate 16 2- , [0xca,0xcc,0x30,0x79,0xe4,0xb7,0x95,0x27,0x63,0xd2,0x55,0xd6,0x34,0x10,0x46,0x14]- )- ]--vectors_aes256_enc =- [ ( replicate 32 0- , B.replicate 16 0- , [0xdc,0x95,0xc0,0x78,0xa2,0x40,0x89,0x89,0xad,0x48,0xa2,0x14,0x92,0x84,0x20,0x87]- )- , ( replicate 32 0- , B.replicate 16 1- , [0x7b,0xc3,0x02,0x6c,0xd7,0x37,0x10,0x3e,0x62,0x90,0x2b,0xcd,0x18,0xfb,0x01,0x63]- )- , ( replicate 32 1- , B.replicate 16 2- , [0x62,0xae,0x12,0xf3,0x24,0xbf,0xea,0x08,0xd5,0xf6,0x75,0xb5,0x13,0x02,0x6b,0xbf]- )- , ( replicate 32 2- , B.replicate 16 1- , [0x00,0xf9,0xc7,0x44,0x4b,0xb0,0xcc,0x80,0x6c,0x7c,0x39,0xee,0x22,0x11,0xf1,0x46]- )- , ( replicate 32 3- , B.replicate 16 2- , [0xb4,0x05,0x87,0x3e,0xa0,0x76,0x1b,0x9c,0xa9,0x9f,0x70,0xb0,0x16,0x16,0xce,0xb1]- )- ]--vectors_aes128_dec =- [ ( replicate 16 0- , B.replicate 16 0- , [0x14,0x0f,0x0f,0x10,0x11,0xb5,0x22,0x3d,0x79,0x58,0x77,0x17,0xff,0xd9,0xec,0x3a]- )- , ( replicate 16 0- , B.replicate 16 1- , [0x15,0x6d,0x0f,0x85,0x75,0xd5,0x33,0x07,0x52,0xf8,0x4a,0xf2,0x72,0xff,0x30,0x50]- )- , ( replicate 16 1- , B.replicate 16 2- , [0x34,0x37,0xd6,0xe2,0x31,0xd7,0x02,0x41,0x9b,0x51,0xb4,0x94,0x72,0x71,0xb6,0x11]- )- , ( replicate 16 2- , B.replicate 16 1- , [0xe3,0xcd,0xe2,0x37,0xc8,0xf2,0xd9,0x7b,0x8d,0x79,0xf9,0x17,0x1d,0x4b,0xda,0xc1]- )- , ( replicate 16 3- , B.replicate 16 2- , [0x5b,0x94,0xaa,0xed,0xd7,0x83,0x99,0x8c,0xd5,0x15,0x35,0x35,0x18,0xcc,0x45,0xe2]- )- ]--vectors_aes192_dec =- [- ( replicate 24 0- , B.replicate 16 0- , [0x13,0x46,0x0e,0x87,0xa8,0xfc,0x02,0x3e,0xf2,0x50,0x1a,0xfe,0x7f,0xf5,0x1c,0x51]- )- , ( replicate 24 0- , B.replicate 16 1- , [0x92,0x17,0x07,0xc3,0x3d,0x1c,0xc5,0x96,0x7d,0xa5,0x1d,0xbb,0xb0,0x66,0xb2,0x6c]- )- , ( replicate 24 1- , B.replicate 16 2- , [0xee,0x92,0x97,0xc6,0xba,0xe8,0x26,0x4d,0xff,0x08,0x0e,0xbb,0x1e,0x74,0x11,0xc1]- )- , ( replicate 24 2- , B.replicate 16 1- , [0x49,0x67,0xdf,0x70,0xd2,0x9e,0x9a,0x7f,0x5d,0x7c,0xb9,0xc1,0x20,0xc3,0x8a,0x71]- )- , ( replicate 24 3- , B.replicate 16 2- , [0x74,0x38,0x62,0x42,0x6b,0x56,0x7f,0xd5,0xf0,0x1d,0x1b,0x59,0x56,0x01,0x26,0x29]- )- ]--vectors_aes256_dec =- [ ( replicate 32 0- , B.replicate 16 0- , [0x67,0x67,0x1c,0xe1,0xfa,0x91,0xdd,0xeb,0x0f,0x8f,0xbb,0xb3,0x66,0xb5,0x31,0xb4]- )- , ( replicate 32 0- , B.replicate 16 1- , [0xcc,0x09,0x21,0xa3,0xc5,0xca,0x17,0xf7,0x48,0xb7,0xc2,0x7b,0x73,0xba,0x87,0xa2]- )- , ( replicate 32 1- , B.replicate 16 2- , [0xc0,0x4b,0x27,0x90,0x1a,0x50,0xcf,0xfa,0xf1,0xbb,0x88,0x9f,0xc0,0x92,0x5e,0x14]- )- , ( replicate 32 2- , B.replicate 16 1- , [0x24,0x61,0x53,0x5d,0x16,0x1c,0x15,0x39,0x88,0x32,0x77,0x29,0xc5,0x8c,0xc0,0x3a]- )- , ( replicate 32 3- , B.replicate 16 2- , [0x30,0xc9,0x1c,0xce,0xfe,0x89,0x30,0xcf,0xff,0x31,0xdb,0xcc,0xfc,0x11,0xc5,0x23]- )- ]--aes128InitKey = AES.initKey128-aes192InitKey = AES.initKey192-aes256InitKey = AES.initKey256--vectors_rc4 =- [ (wordify "Key", "Plaintext", [ 0xBB,0xF3,0x16,0xE8,0xD9,0x40,0xAF,0x0A,0xD3 ])- , (wordify "Wiki", "pedia", [ 0x10,0x21,0xBF,0x04,0x20 ])- , (wordify "Secret", "Attack at dawn", [ 0x45,0xA0,0x1F,0x64,0x5F,0xC3,0x5B,0x38,0x35,0x52,0x54,0x4B,0x9B,0xF5 ])- ]--vectors_camellia128 =- [ - ( replicate 16 0- , B.replicate 16 0- , [0x3d,0x02,0x80,0x25,0xb1,0x56,0x32,0x7c,0x17,0xf7,0x62,0xc1,0xf2,0xcb,0xca,0x71]- )- , ( [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]- , B.pack [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]- , [0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73,0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43]- )- ]--vectors_camellia192 =- [- ( [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77]- , B.pack [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]- ,[0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8,0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9]- )- ]--vectors_camellia256 =- [- ( [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10- ,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff]- , B.pack [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]- , [0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c,0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09]- )- ]--vectors =- [ ("RC4", vectors_rc4, encryptStream RC4.initCtx RC4.encrypt)- , ("AES128 Enc", vectors_aes128_enc, encryptBlock aes128InitKey AES.encrypt)- , ("AES192 Enc", vectors_aes192_enc, encryptBlock aes192InitKey AES.encrypt)- , ("AES256 Enc", vectors_aes256_enc, encryptBlock aes256InitKey AES.encrypt)- , ("AES128 Dec", vectors_aes128_dec, encryptBlock aes128InitKey AES.decrypt)- , ("AES192 Dec", vectors_aes192_dec, encryptBlock aes192InitKey AES.decrypt)- , ("AES256 Dec", vectors_aes256_dec, encryptBlock aes256InitKey AES.decrypt)- , ("Camellia", vectors_camellia128, encryptBlock Camellia.initKey Camellia.encrypt)- ]--utests :: [Unit.Test]-utests = concatMap (\(name, v, f) -> map (\(k,p,e) -> name ~: name ~: e ~=? f k p) v) vectors--{- end of units tests -}-{- start of QuickCheck verification -}--prop_gcde_binary_valid (Positive a, Positive b) =- let (x,y,v) = gcde_binary a b in- let (x',y',v') = gcde a b in- and [v==v', a*x' + b*y' == v', a*x + b*y == v, gcd a b == v]--prop_modexp_rtl_valid (NonNegative a, NonNegative b, Positive m) =- exponantiation_rtl_binary a b m == ((a ^ b) `mod` m)--prop_modinv_valid (Positive a, Positive m)- | m > 1 =- case inverse a m of- Just ainv -> (ainv * a) `mod` m == 1- Nothing -> True- | otherwise = True--prop_sqrti_valid (Positive i) = l*l <= i && i <= u*u where (l, u) = sqrti i--prop_generate_prime_valid i =- -- becuase of the next naive test, we can't generate easily number above 32 bits- -- otherwise it slows down the tests to uselessness. when AKS or ECPP is implemented- -- we can revisit the number here- let p = withAleasInteger rng i (\g -> generatePrime g 32) in- -- FIXME test if p is around 32 bits- primalityTestNaive p--prop_miller_rabin_valid i- | i <= 3 = True- | otherwise =- -- miller rabin only returns with certitude that the integer is composite.- let b = withAleasInteger rng i (\g -> isProbablyPrime g i) in- (b == False && primalityTestNaive i == False) || b == True--withAleasInteger rng i f = case reseed (i2osp (if i < 0 then -i else i)) rng of- Left _ -> error "impossible"- Right rng' -> case f rng' of- Left _ -> error "impossible"- Right v -> fst v--newtype RSAMessage = RSAMessage B.ByteString deriving (Show, Eq)--instance Arbitrary RSAMessage where- arbitrary = do- sz <- choose (0, 128 - 11)- ws <- replicateM sz (choose (0,255) :: Gen Int)- return $ RSAMessage $ B.pack $ map fromIntegral ws--{- this is a just test rng. this is absolutely not a serious RNG. DO NOT use elsewhere -}-data Rng = Rng (Int, Int)--getByte :: Rng -> (Word8, Rng)-getByte (Rng (mz, mw)) =- let mz2 = 36969 * (mz `mod` 65536) in- let mw2 = 18070 * (mw `mod` 65536) in- (fromIntegral (mz2 + mw2), Rng (mz2, mw2))--getBytes 0 rng = ([], rng)-getBytes n rng =- let (b, rng') = getByte rng in- let (l, rng'') = getBytes (n-1) rng' in- (b:l, rng'')--instance CryptoRandomGen Rng where- newGen _ = Right (Rng (2,3))- genSeedLength = 0- genBytes len g = Right $ first B.pack $ getBytes len g- reseed bs (Rng (a,b)) = Right $ Rng (fromIntegral a', b) where- a' = ((fromIntegral a) + i * 36969) `mod` 65536- i = os2ip bs--rng = Rng (1,2) --{-----------------------------------------------------------------------------------------------}-{- testing RSA -}-{-----------------------------------------------------------------------------------------------}--prop_rsa_generate_valid (Positive i, RSAMessage msgz) =- let keysz = 64 in- let (pub,priv) = withAleasInteger rng i (\g -> RSA.generate g keysz 65537) in- let msg = B.take (keysz - 11) msgz in- (RSA.private_p priv * RSA.private_q priv == RSA.private_n priv) &&- ((RSA.private_d priv * RSA.public_e pub) `mod` ((RSA.private_p priv - 1) * (RSA.private_q priv - 1)) == 1) &&- (either Left (RSA.decrypt priv . fst) $ RSA.encrypt rng pub msg) == Right msg--prop_rsa_valid fast (RSAMessage msg) =- (either Left (RSA.decrypt pk . fst) $ RSA.encrypt rng rsaPublickey msg) == Right msg- where pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 }--prop_rsa_fast_valid = prop_rsa_valid True-prop_rsa_slow_valid = prop_rsa_valid False--prop_rsa_sign_valid fast (RSAMessage msg) = (either Left (\smsg -> verify msg smsg) $ sign msg) == Right True- where- verify = RSA.verify (SHA1.hash) sha1desc rsaPublickey- sign = RSA.sign (SHA1.hash) sha1desc pk- sha1desc = B.pack [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03, 0x02,0x1a,0x05,0x00,0x04,0x14]- pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 }--prop_rsa_sign_fast_valid = prop_rsa_sign_valid True-prop_rsa_sign_slow_valid = prop_rsa_sign_valid False--rsaPrivatekey = RSA.PrivateKey- { RSA.private_size = 128- , RSA.private_n = 140203425894164333410594309212077886844966070748523642084363106504571537866632850620326769291612455847330220940078873180639537021888802572151020701352955762744921926221566899281852945861389488419179600933178716009889963150132778947506523961974222282461654256451508762805133855866018054403911588630700228345151- , RSA.private_d = 133764127300370985476360382258931504810339098611363623122953018301285450176037234703101635770582297431466449863745848961134143024057267778947569638425565153896020107107895924597628599677345887446144410702679470631826418774397895304952287674790343620803686034122942606764275835668353720152078674967983573326257- , RSA.private_p = 12909745499610419492560645699977670082358944785082915010582495768046269235061708286800087976003942261296869875915181420265794156699308840835123749375331319- , RSA.private_q = 10860278066550210927914375228722265675263011756304443428318337179619069537063135098400347475029673115805419186390580990519363257108008103841271008948795129- , RSA.private_dP = 5014229697614831746694710412330921341325464081424013940131184365711243776469716106024020620858146547161326009604054855316321928968077674343623831428796843- , RSA.private_dQ = 3095337504083058271243917403868092841421453478127022884745383831699720766632624326762288333095492075165622853999872779070009098364595318242383709601515849- , RSA.private_qinv = 11136639099661288633118187183300604127717437440459572124866697429021958115062007251843236337586667012492941414990095176435990146486852255802952814505784196- }--rsaPublickey = RSA.PublicKey- { RSA.public_size = 128- , RSA.public_n = 140203425894164333410594309212077886844966070748523642084363106504571537866632850620326769291612455847330220940078873180639537021888802572151020701352955762744921926221566899281852945861389488419179600933178716009889963150132778947506523961974222282461654256451508762805133855866018054403911588630700228345151- , RSA.public_e = 65537- }--{-----------------------------------------------------------------------------------------------}-{- testing DSA -}-{-----------------------------------------------------------------------------------------------}---dsaParams = (p,g,q)- where- p = 0x00a8c44d7d0bbce69a39008948604b9c7b11951993a5a1a1fa995968da8bb27ad9101c5184bcde7c14fb79f7562a45791c3d80396cefb328e3e291932a17e22edd- g = 0x0bf9fe6c75d2367b88912b2252d20fdcad06b3f3a234b92863a1e30a96a123afd8e8a4b1dd953e6f5583ef8e48fc7f47a6a1c8f24184c76dba577f0fec2fcd1c- q = 0x0096674b70ef58beaaab6743d6af16bb862d18d119--dsaPrivatekey = DSA.PrivateKey- { DSA.private_params = dsaParams- , DSA.private_x = 0x229bac7aa1c7db8121bfc050a3426eceae23fae8- }--dsaPublickey = DSA.PublicKey- { DSA.public_params = dsaParams- , DSA.public_y = 0x4fa505e86e32922f1fa1702a120abdba088bb4be801d4c44f7fc6b9094d85cd52c429cbc2b39514e30909b31e2e2e0752b0fc05c1a7d9c05c3e52e49e6edef4c- }--prop_dsa_valid (RSAMessage msg) =- case DSA.verify signature (SHA1.hash) dsaPublickey msg of- Left err -> False- Right b -> b- where- Right (signature, rng') = DSA.sign rng (SHA1.hash) dsaPrivatekey msg--{-----------------------------------------------------------------------------------------------}-{- testing DH -}-{-----------------------------------------------------------------------------------------------}-instance Arbitrary DH.PrivateNumber where- arbitrary = fromIntegral <$> (suchThat (arbitrary :: Gen Integer) (\x -> x >= 1))--prop_dh_valid (xa, xb) = sa == sb- where- sa = DH.getShared dhparams xa yb- sb = DH.getShared dhparams xb ya- yb = DH.generatePublic dhparams xb- ya = DH.generatePublic dhparams xa- dhparams = (11, 7)--{-----------------------------------------------------------------------------------------------}-{- testing AES -}-{-----------------------------------------------------------------------------------------------}-data AES128Message = AES128Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)-data AES192Message = AES192Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)-data AES256Message = AES256Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)--arbitraryAES keysize = do- sz <- choose (1, 12)- ws <- replicateM (sz*16) (choose (0,255) :: Gen Int)- key <- replicateM keysize (choose (0,255) :: Gen Int)- iv <- replicateM 16 (choose (0,255) :: Gen Int)- return (ws, key, iv)--instance Arbitrary AES128Message where- arbitrary = do- (ws, key, iv) <- arbitraryAES 16- return $ AES128Message (B.pack $ map fromIntegral key)- (B.pack $ map fromIntegral iv)- (B.pack $ map fromIntegral ws)--instance Arbitrary AES192Message where- arbitrary = do- (ws, key, iv) <- arbitraryAES 24- return $ AES192Message (B.pack $ map fromIntegral key)- (B.pack $ map fromIntegral iv)- (B.pack $ map fromIntegral ws)--instance Arbitrary AES256Message where- arbitrary = do- (ws, key, iv) <- arbitraryAES 32- return $ AES256Message (B.pack $ map fromIntegral key)- (B.pack $ map fromIntegral iv)- (B.pack $ map fromIntegral ws)---prop_ecb_valid k msg = AES.decrypt k (AES.encrypt k msg) == msg-prop_cbc_valid k iv msg = AES.decryptCBC k iv (AES.encryptCBC k iv msg) == msg--prop_aes128_ecb_valid (AES128Message key _ msg) =- let (Right k) = AES.initKey128 key in- prop_ecb_valid k msg--prop_aes192_ecb_valid (AES192Message key _ msg) =- let (Right k) = AES.initKey192 key in- prop_ecb_valid k msg--prop_aes256_ecb_valid (AES256Message key _ msg) =- let (Right k) = AES.initKey256 key in- prop_ecb_valid k msg--prop_aes128_cbc_valid (AES128Message key iv msg) =- let (Right k) = AES.initKey128 key in- prop_cbc_valid k iv msg--prop_aes192_cbc_valid (AES192Message key iv msg) =- let (Right k) = AES.initKey192 key in- prop_cbc_valid k iv msg--prop_aes256_cbc_valid (AES256Message key iv msg) =- let (Right k) = AES.initKey256 key in- prop_cbc_valid k iv msg--{-----------------------------------------------------------------------------------------------}-{- main -}-{-----------------------------------------------------------------------------------------------}--args = stdArgs- { replay = Nothing- , maxSuccess = 200- , maxDiscard = 1000- , maxSize = 200- }--run_test n t = putStr (" " ++ n ++ " ... ") >> hFlush stdout >> quickCheckWith args t--main = do- Unit.runTestTT (Unit.TestList utests)-- -- Number Tests- run_test "gcde binary valid" prop_gcde_binary_valid- run_test "exponantiation RTL valid" prop_modexp_rtl_valid- run_test "inverse valid" prop_modinv_valid- run_test "sqrt integer valid" prop_sqrti_valid- run_test "primality test Miller Rabin" prop_miller_rabin_valid- run_test "Generate prime" prop_generate_prime_valid-- -- AES Tests- run_test "AES128 (ECB) decrypt.encrypt = id" prop_aes128_ecb_valid- run_test "AES128 (CBC) decrypt.encrypt = id" prop_aes128_cbc_valid-- run_test "AES192 (ECB) decrypt.encrypt = id" prop_aes192_ecb_valid- run_test "AES192 (CBC) decrypt.encrypt = id" prop_aes192_cbc_valid-- run_test "AES256 (ECB) decrypt.encrypt = id" prop_aes256_ecb_valid- run_test "AES256 (CBC) decrypt.encrypt = id" prop_aes256_cbc_valid-- -- DH Tests- run_test "DH test" prop_dh_valid-- -- RSA Tests- run_test "RSA generate" prop_rsa_generate_valid- run_test "RSA verify . sign(slow) = true" prop_rsa_sign_slow_valid- run_test "RSA verify . sign(fast) = true" prop_rsa_sign_fast_valid-- run_test "RSA decrypt(slow).encrypt = id" prop_rsa_slow_valid- run_test "RSA decrypt(fast).encrypt = id" prop_rsa_fast_valid-- -- DSA Tests- run_test "DSA verify . sign = true" prop_dsa_valid
+ Tests/AES.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE CPP #-}+module AES (aesTests) where++-- unfortunately due to a bug in some version of cabal+-- there's no way to have a condition cpp-options in the cabal file+-- for test suite. to run test with AESni, uncomment the following+-- #define HAVE_AESNI++import qualified Crypto.Cipher.AES.Haskell as AESHs+#ifdef HAVE_AESNI+import qualified Crypto.Cipher.AES.X86NI as AESNI+#endif++import Crypto.Classes+import qualified Crypto.Modes as CAPI++import Data.Word+import Data.List+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import Control.Monad+import Control.Applicative+import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.QuickCheck++newtype IV = IV ByteString+ deriving (Show,Eq)+newtype Key128 = Key128 ByteString+ deriving (Show,Eq)+newtype Message = Message ByteString+ deriving (Show,Eq)++arbitraryBS sz = B.pack <$> replicateM sz (choose (0,255) :: Gen Word8)++instance Arbitrary IV where+ arbitrary = IV <$> arbitraryBS 16++instance Arbitrary Key128 where+ arbitrary = Key128 <$> arbitraryBS 16++instance Arbitrary Message where+ arbitrary = choose (1,102) >>= \sz -> Message <$> arbitraryBS (16*sz)++ebcTests l (Key128 k, Message m) = (== 1) $ length $ nub $ map (\f -> f k m) l+cbcTests l (IV iv, Key128 k, Message m) = (== 1) $ length $ nub $ map (\f -> f k iv m) l++unright (Right r) = r+unright (Left e) = error e++aesTests =+ [ testProperty "ECB Encryption Equivalent" $ ebcTests+ [ (\k m -> AESHs.encrypt (unright $ AESHs.initKey128 k) m)+#ifdef HAVE_AESNI+ , (\k m -> AESNI.encrypt (AESNI.initKey128 k) m)+#endif+ ]+ , testProperty "CBC Encryption Equivalent" $ cbcTests+ [ (\k iv m -> AESHs.encryptCBC (unright $ AESHs.initKey128 k) iv m)+#ifdef HAVE_AESNI+ , (\k iv m -> AESNI.encryptCBC (AESNI.initKey128 k) iv m)+#endif+ ]+ , testProperty "ECB Decryption Equivalent" $ ebcTests+ [ (\k m -> AESHs.decrypt (unright $ AESHs.initKey128 k) m)+#ifdef HAVE_AESNI+ , (\k m -> AESNI.decrypt (AESNI.initKey128 k) m)+#endif+ ]+ , testProperty "CBC Decryption Equivalent" $ cbcTests+ [ (\k iv m -> AESHs.decryptCBC (unright $ AESHs.initKey128 k) iv m)+#ifdef HAVE_AESNI+ , (\k iv m -> AESNI.decryptCBC (AESNI.initKey128 k) iv m)+#endif+ ]+ ]
+ Tests/KAT.hs view
@@ -0,0 +1,241 @@+{-# LANGUAGE OverloadedStrings, CPP #-}+module KAT (katTests) where++-- unfortunately due to a bug in some version of cabal+-- there's no way to have a condition cpp-options in the cabal file+-- for test suite. to run test with AESni, uncomment the following+-- #define HAVE_AESNI++import Test.Framework.Providers.QuickCheck2 (testProperty)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC++import Data.Word++import qualified Crypto.Cipher.AES.Haskell as AES+#ifdef HAVE_AESNI+import qualified Crypto.Cipher.AES.X86NI as AESNI+#endif+import qualified Crypto.Cipher.Camellia as Camellia+import qualified Crypto.Cipher.RC4 as RC4++encryptStream fi fc key plaintext = B.unpack $ snd $ fc (fi key) plaintext++encryptBlock fi fc key plaintext =+ let e = fi (B.pack key) in+ case e of+ Right k -> B.unpack $ fc k plaintext+ Left e -> error e++wordify :: [Char] -> [Word8]+wordify = map (toEnum . fromEnum)++vectors_aes128_enc =+ [+ ( [0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3,0x74,0xcf,0x86,0x7c,0xfb,0x47,0x38,0x59]+ , B.replicate 16 0+ , [0x6d,0x25,0x1e,0x69,0x44,0xb0,0x51,0xe0,0x4e,0xaa,0x6f,0xb4,0xdb,0xf7,0x84,0x65]+ )+ , ( replicate 16 0+ , B.replicate 16 0+ , [0x66,0xe9,0x4b,0xd4,0xef,0x8a,0x2c,0x3b,0x88,0x4c,0xfa,0x59,0xca,0x34,0x2b,0x2e]+ )+ , ( replicate 16 0+ , B.replicate 16 1+ , [0xe1,0x4d,0x5d,0x0e,0xe2,0x77,0x15,0xdf,0x08,0xb4,0x15,0x2b,0xa2,0x3d,0xa8,0xe0]+ )+ , ( replicate 16 1+ , B.replicate 16 2+ , [0x17,0xd6,0x14,0xf3,0x79,0xa9,0x35,0x90,0x77,0xe9,0x55,0x77,0xfd,0x31,0xc2,0x0a]+ )+ , ( replicate 16 2+ , B.replicate 16 1+ , [0x8f,0x42,0xc2,0x4b,0xee,0x6e,0x63,0x47,0x2b,0x16,0x5a,0xa9,0x41,0x31,0x2f,0x7c]+ )+ , ( replicate 16 3+ , B.replicate 16 2+ , [0x90,0x98,0x85,0xe4,0x77,0xbc,0x20,0xf5,0x8a,0x66,0x97,0x1d,0xa0,0xbc,0x75,0xe3]+ )+ ]++vectors_aes192_enc =+ [+ ( replicate 24 0+ , B.replicate 16 0+ , [0xaa,0xe0,0x69,0x92,0xac,0xbf,0x52,0xa3,0xe8,0xf4,0xa9,0x6e,0xc9,0x30,0x0b,0xd7]+ )+ , ( replicate 24 0+ , B.replicate 16 1+ , [0xcf,0x1e,0xce,0x3c,0x44,0xb0,0x78,0xfb,0x27,0xcb,0x0a,0x3e,0x07,0x1b,0x08,0x20]+ )+ , ( replicate 24 1+ , B.replicate 16 2+ , [0xeb,0x8c,0x17,0x30,0x90,0xc7,0x5b,0x77,0xd6,0x72,0xb4,0x57,0xa7,0x78,0xd9,0xd0]+ )+ , ( replicate 24 2+ , B.replicate 16 1+ , [0xf2,0xf0,0xae,0xd8,0xcd,0xc9,0x21,0xca,0x4b,0x55,0x84,0x5d,0xa4,0x15,0x21,0xc2]+ )+ , ( replicate 24 3+ , B.replicate 16 2+ , [0xca,0xcc,0x30,0x79,0xe4,0xb7,0x95,0x27,0x63,0xd2,0x55,0xd6,0x34,0x10,0x46,0x14]+ )+ ]++vectors_aes256_enc =+ [ ( replicate 32 0+ , B.replicate 16 0+ , [0xdc,0x95,0xc0,0x78,0xa2,0x40,0x89,0x89,0xad,0x48,0xa2,0x14,0x92,0x84,0x20,0x87]+ )+ , ( replicate 32 0+ , B.replicate 16 1+ , [0x7b,0xc3,0x02,0x6c,0xd7,0x37,0x10,0x3e,0x62,0x90,0x2b,0xcd,0x18,0xfb,0x01,0x63]+ )+ , ( replicate 32 1+ , B.replicate 16 2+ , [0x62,0xae,0x12,0xf3,0x24,0xbf,0xea,0x08,0xd5,0xf6,0x75,0xb5,0x13,0x02,0x6b,0xbf]+ )+ , ( replicate 32 2+ , B.replicate 16 1+ , [0x00,0xf9,0xc7,0x44,0x4b,0xb0,0xcc,0x80,0x6c,0x7c,0x39,0xee,0x22,0x11,0xf1,0x46]+ )+ , ( replicate 32 3+ , B.replicate 16 2+ , [0xb4,0x05,0x87,0x3e,0xa0,0x76,0x1b,0x9c,0xa9,0x9f,0x70,0xb0,0x16,0x16,0xce,0xb1]+ )+ ]++vectors_aes128_dec =+ [ ( replicate 16 0+ , B.replicate 16 0+ , [0x14,0x0f,0x0f,0x10,0x11,0xb5,0x22,0x3d,0x79,0x58,0x77,0x17,0xff,0xd9,0xec,0x3a]+ )+ , ( replicate 16 0+ , B.replicate 16 1+ , [0x15,0x6d,0x0f,0x85,0x75,0xd5,0x33,0x07,0x52,0xf8,0x4a,0xf2,0x72,0xff,0x30,0x50]+ )+ , ( replicate 16 1+ , B.replicate 16 2+ , [0x34,0x37,0xd6,0xe2,0x31,0xd7,0x02,0x41,0x9b,0x51,0xb4,0x94,0x72,0x71,0xb6,0x11]+ )+ , ( replicate 16 2+ , B.replicate 16 1+ , [0xe3,0xcd,0xe2,0x37,0xc8,0xf2,0xd9,0x7b,0x8d,0x79,0xf9,0x17,0x1d,0x4b,0xda,0xc1]+ )+ , ( replicate 16 3+ , B.replicate 16 2+ , [0x5b,0x94,0xaa,0xed,0xd7,0x83,0x99,0x8c,0xd5,0x15,0x35,0x35,0x18,0xcc,0x45,0xe2]+ )+ ]++vectors_aes192_dec =+ [+ ( replicate 24 0+ , B.replicate 16 0+ , [0x13,0x46,0x0e,0x87,0xa8,0xfc,0x02,0x3e,0xf2,0x50,0x1a,0xfe,0x7f,0xf5,0x1c,0x51]+ )+ , ( replicate 24 0+ , B.replicate 16 1+ , [0x92,0x17,0x07,0xc3,0x3d,0x1c,0xc5,0x96,0x7d,0xa5,0x1d,0xbb,0xb0,0x66,0xb2,0x6c]+ )+ , ( replicate 24 1+ , B.replicate 16 2+ , [0xee,0x92,0x97,0xc6,0xba,0xe8,0x26,0x4d,0xff,0x08,0x0e,0xbb,0x1e,0x74,0x11,0xc1]+ )+ , ( replicate 24 2+ , B.replicate 16 1+ , [0x49,0x67,0xdf,0x70,0xd2,0x9e,0x9a,0x7f,0x5d,0x7c,0xb9,0xc1,0x20,0xc3,0x8a,0x71]+ )+ , ( replicate 24 3+ , B.replicate 16 2+ , [0x74,0x38,0x62,0x42,0x6b,0x56,0x7f,0xd5,0xf0,0x1d,0x1b,0x59,0x56,0x01,0x26,0x29]+ )+ ]++vectors_aes256_dec =+ [ ( replicate 32 0+ , B.replicate 16 0+ , [0x67,0x67,0x1c,0xe1,0xfa,0x91,0xdd,0xeb,0x0f,0x8f,0xbb,0xb3,0x66,0xb5,0x31,0xb4]+ )+ , ( replicate 32 0+ , B.replicate 16 1+ , [0xcc,0x09,0x21,0xa3,0xc5,0xca,0x17,0xf7,0x48,0xb7,0xc2,0x7b,0x73,0xba,0x87,0xa2]+ )+ , ( replicate 32 1+ , B.replicate 16 2+ , [0xc0,0x4b,0x27,0x90,0x1a,0x50,0xcf,0xfa,0xf1,0xbb,0x88,0x9f,0xc0,0x92,0x5e,0x14]+ )+ , ( replicate 32 2+ , B.replicate 16 1+ , [0x24,0x61,0x53,0x5d,0x16,0x1c,0x15,0x39,0x88,0x32,0x77,0x29,0xc5,0x8c,0xc0,0x3a]+ )+ , ( replicate 32 3+ , B.replicate 16 2+ , [0x30,0xc9,0x1c,0xce,0xfe,0x89,0x30,0xcf,0xff,0x31,0xdb,0xcc,0xfc,0x11,0xc5,0x23]+ )+ ]++aes128InitKey = AES.initKey128+aes192InitKey = AES.initKey192+aes256InitKey = AES.initKey256++vectors_rc4 =+ [ (wordify "Key", "Plaintext", [ 0xBB,0xF3,0x16,0xE8,0xD9,0x40,0xAF,0x0A,0xD3 ])+ , (wordify "Wiki", "pedia", [ 0x10,0x21,0xBF,0x04,0x20 ])+ , (wordify "Secret", "Attack at dawn", [ 0x45,0xA0,0x1F,0x64,0x5F,0xC3,0x5B,0x38,0x35,0x52,0x54,0x4B,0x9B,0xF5 ])+ ]++vectors_camellia128 =+ [ + ( replicate 16 0+ , B.replicate 16 0+ , [0x3d,0x02,0x80,0x25,0xb1,0x56,0x32,0x7c,0x17,0xf7,0x62,0xc1,0xf2,0xcb,0xca,0x71]+ )+ , ( [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]+ , B.pack [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]+ , [0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73,0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43]+ )+ ]++vectors_camellia192 =+ [+ ( [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77]+ , B.pack [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]+ ,[0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8,0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9]+ )+ ]++vectors_camellia256 =+ [+ ( [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10+ ,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff]+ , B.pack [0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10]+ , [0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c,0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09]+ )+ ]++vectors =+ [ ("RC4", vectors_rc4, encryptStream RC4.initCtx RC4.encrypt)+ -- AES haskell implementation+ , ("AES 128 Enc", vectors_aes128_enc, encryptBlock aes128InitKey AES.encrypt)+ , ("AES 192 Enc", vectors_aes192_enc, encryptBlock aes192InitKey AES.encrypt)+ , ("AES 256 Enc", vectors_aes256_enc, encryptBlock aes256InitKey AES.encrypt)+ , ("AES 128 Dec", vectors_aes128_dec, encryptBlock aes128InitKey AES.decrypt)+ , ("AES 192 Dec", vectors_aes192_dec, encryptBlock aes192InitKey AES.decrypt)+ , ("AES 256 Dec", vectors_aes256_dec, encryptBlock aes256InitKey AES.decrypt)+#ifdef HAVE_AESNI+ -- AES ni implementation+ , ("AESNI 128 Enc", vectors_aes128_enc, encryptBlock (Right . AESNI.initKey128) AESNI.encrypt)+ , ("AESNI 128 Dec", vectors_aes128_dec, encryptBlock (Right . AESNI.initKey128) AESNI.decrypt)+#endif+ -- Camellia implementation+ , ("Camellia", vectors_camellia128, encryptBlock Camellia.initKey128 Camellia.encrypt)+ ]++katTests = map makeTests vectors+ where makeTests (name, v, f) = testProperty name (and $ map makeTest v)+ where makeTest (key,plaintext,expected) = assertEq expected $ f key plaintext++assertEq expected got+ | expected == got = True+ | otherwise = error ("expected: " ++ show expected ++ " got: " ++ show got)
+ Tests/tests.hs view
@@ -0,0 +1,321 @@+{-# LANGUAGE OverloadedStrings #-}++import Test.Framework (Test, defaultMain, testGroup)+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Test.QuickCheck+import Test.QuickCheck.Test+import System.IO (hFlush, stdout)++import Control.Monad+import Control.Arrow (first)+import Control.Applicative ((<$>))++import Data.List (intercalate)+import Data.Char+import Data.Bits+import Data.Word+import qualified Data.Vector.Unboxed as V+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+-- for DSA+import qualified Crypto.Hash.SHA1 as SHA1++-- numbers+{-+import Number.ModArithmetic+import Number.Basic+import Number.Prime+import Number.Serialize+-}+-- ciphers/Kexch+import AES (aesTests)+import qualified Crypto.Cipher.AES.Haskell as AES+import qualified Crypto.Cipher.RSA as RSA+import qualified Crypto.Cipher.DSA as DSA+import qualified Crypto.Cipher.DH as DH+import Crypto.Random+import KAT++{-+prop_gcde_binary_valid (Positive a, Positive b) =+ let (x,y,v) = gcde_binary a b in+ let (x',y',v') = gcde a b in+ and [v==v', a*x' + b*y' == v', a*x + b*y == v, gcd a b == v]++prop_modexp_rtl_valid (NonNegative a, NonNegative b, Positive m) =+ exponantiation_rtl_binary a b m == ((a ^ b) `mod` m)++prop_modinv_valid (Positive a, Positive m)+ | m > 1 =+ case inverse a m of+ Just ainv -> (ainv * a) `mod` m == 1+ Nothing -> True+ | otherwise = True++prop_sqrti_valid (Positive i) = l*l <= i && i <= u*u where (l, u) = sqrti i++prop_generate_prime_valid i =+ -- becuase of the next naive test, we can't generate easily number above 32 bits+ -- otherwise it slows down the tests to uselessness. when AKS or ECPP is implemented+ -- we can revisit the number here+ let p = withAleasInteger rng i (\g -> generatePrime g 32) in+ -- FIXME test if p is around 32 bits+ primalityTestNaive p++prop_miller_rabin_valid i+ | i <= 3 = True+ | otherwise =+ -- miller rabin only returns with certitude that the integer is composite.+ let b = withAleasInteger rng i (\g -> isProbablyPrime g i) in+ (b == False && primalityTestNaive i == False) || b == True++withAleasInteger rng i f = case reseed (i2osp (if i < 0 then -i else i)) rng of+ Left _ -> error "impossible"+ Right rng' -> case f rng' of+ Left _ -> error "impossible"+ Right v -> fst v+-}++newtype RSAMessage = RSAMessage B.ByteString deriving (Show, Eq)++instance Arbitrary RSAMessage where+ arbitrary = do+ sz <- choose (0, 128 - 11)+ ws <- replicateM sz (choose (0,255) :: Gen Int)+ return $ RSAMessage $ B.pack $ map fromIntegral ws++{- this is a just test rng. this is absolutely not a serious RNG. DO NOT use elsewhere -}+data Rng = Rng (Int, Int)++getByte :: Rng -> (Word8, Rng)+getByte (Rng (mz, mw)) =+ let mz2 = 36969 * (mz `mod` 65536) in+ let mw2 = 18070 * (mw `mod` 65536) in+ (fromIntegral (mz2 + mw2), Rng (mz2, mw2))++getBytes 0 rng = ([], rng)+getBytes n rng =+ let (b, rng') = getByte rng in+ let (l, rng'') = getBytes (n-1) rng' in+ (b:l, rng'')++instance CryptoRandomGen Rng where+ newGen _ = Right (Rng (2,3))+ genSeedLength = 0+ genBytes len g = Right $ first B.pack $ getBytes len g+ reseed bs (Rng (a,b)) = Right $ Rng (fromIntegral a', b) where+ a' = ((fromIntegral a) + i * 36969) `mod` 65536+ i = B.head bs++rng = Rng (1,2) ++{-----------------------------------------------------------------------------------------------}+{- testing RSA -}+{-----------------------------------------------------------------------------------------------}++{-+prop_rsa_generate_valid (Positive i, RSAMessage msgz) =+ let keysz = 64 in+ let (pub,priv) = withAleasInteger rng i (\g -> RSA.generate g keysz 65537) in+ let msg = B.take (keysz - 11) msgz in+ (RSA.private_p priv * RSA.private_q priv == RSA.private_n priv) &&+ ((RSA.private_d priv * RSA.public_e pub) `mod` ((RSA.private_p priv - 1) * (RSA.private_q priv - 1)) == 1) &&+ (either Left (RSA.decrypt priv . fst) $ RSA.encrypt rng pub msg) == Right msg+-}++prop_rsa_valid fast (RSAMessage msg) =+ (either Left (RSA.decrypt pk . fst) $ RSA.encrypt rng rsaPublickey msg) == Right msg+ where pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 }++prop_rsa_fast_valid = prop_rsa_valid True+prop_rsa_slow_valid = prop_rsa_valid False++prop_rsa_sign_valid fast (RSAMessage msg) = (either Left (\smsg -> verify msg smsg) $ sign msg) == Right True+ where+ verify = RSA.verify (SHA1.hash) sha1desc rsaPublickey+ sign = RSA.sign (SHA1.hash) sha1desc pk+ sha1desc = B.pack [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03, 0x02,0x1a,0x05,0x00,0x04,0x14]+ pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 }++prop_rsa_sign_fast_valid = prop_rsa_sign_valid True+prop_rsa_sign_slow_valid = prop_rsa_sign_valid False++rsaPrivatekey = RSA.PrivateKey+ { RSA.private_size = 128+ , RSA.private_n = 140203425894164333410594309212077886844966070748523642084363106504571537866632850620326769291612455847330220940078873180639537021888802572151020701352955762744921926221566899281852945861389488419179600933178716009889963150132778947506523961974222282461654256451508762805133855866018054403911588630700228345151+ , RSA.private_d = 133764127300370985476360382258931504810339098611363623122953018301285450176037234703101635770582297431466449863745848961134143024057267778947569638425565153896020107107895924597628599677345887446144410702679470631826418774397895304952287674790343620803686034122942606764275835668353720152078674967983573326257+ , RSA.private_p = 12909745499610419492560645699977670082358944785082915010582495768046269235061708286800087976003942261296869875915181420265794156699308840835123749375331319+ , RSA.private_q = 10860278066550210927914375228722265675263011756304443428318337179619069537063135098400347475029673115805419186390580990519363257108008103841271008948795129+ , RSA.private_dP = 5014229697614831746694710412330921341325464081424013940131184365711243776469716106024020620858146547161326009604054855316321928968077674343623831428796843+ , RSA.private_dQ = 3095337504083058271243917403868092841421453478127022884745383831699720766632624326762288333095492075165622853999872779070009098364595318242383709601515849+ , RSA.private_qinv = 11136639099661288633118187183300604127717437440459572124866697429021958115062007251843236337586667012492941414990095176435990146486852255802952814505784196+ }++rsaPublickey = RSA.PublicKey+ { RSA.public_size = 128+ , RSA.public_n = 140203425894164333410594309212077886844966070748523642084363106504571537866632850620326769291612455847330220940078873180639537021888802572151020701352955762744921926221566899281852945861389488419179600933178716009889963150132778947506523961974222282461654256451508762805133855866018054403911588630700228345151+ , RSA.public_e = 65537+ }++{-----------------------------------------------------------------------------------------------}+{- testing DSA -}+{-----------------------------------------------------------------------------------------------}+++dsaParams = (p,g,q)+ where+ p = 0x00a8c44d7d0bbce69a39008948604b9c7b11951993a5a1a1fa995968da8bb27ad9101c5184bcde7c14fb79f7562a45791c3d80396cefb328e3e291932a17e22edd+ g = 0x0bf9fe6c75d2367b88912b2252d20fdcad06b3f3a234b92863a1e30a96a123afd8e8a4b1dd953e6f5583ef8e48fc7f47a6a1c8f24184c76dba577f0fec2fcd1c+ q = 0x0096674b70ef58beaaab6743d6af16bb862d18d119++dsaPrivatekey = DSA.PrivateKey+ { DSA.private_params = dsaParams+ , DSA.private_x = 0x229bac7aa1c7db8121bfc050a3426eceae23fae8+ }++dsaPublickey = DSA.PublicKey+ { DSA.public_params = dsaParams+ , DSA.public_y = 0x4fa505e86e32922f1fa1702a120abdba088bb4be801d4c44f7fc6b9094d85cd52c429cbc2b39514e30909b31e2e2e0752b0fc05c1a7d9c05c3e52e49e6edef4c+ }++prop_dsa_valid (RSAMessage msg) =+ case DSA.verify signature (SHA1.hash) dsaPublickey msg of+ Left err -> False+ Right b -> b+ where+ Right (signature, rng') = DSA.sign rng (SHA1.hash) dsaPrivatekey msg++{-----------------------------------------------------------------------------------------------}+{- testing DH -}+{-----------------------------------------------------------------------------------------------}+instance Arbitrary DH.PrivateNumber where+ arbitrary = fromIntegral <$> (suchThat (arbitrary :: Gen Integer) (\x -> x >= 1))++prop_dh_valid (xa, xb) = sa == sb+ where+ sa = DH.getShared dhparams xa yb+ sb = DH.getShared dhparams xb ya+ yb = DH.generatePublic dhparams xb+ ya = DH.generatePublic dhparams xa+ dhparams = (11, 7)++{-----------------------------------------------------------------------------------------------}+{- testing AES -}+{-----------------------------------------------------------------------------------------------}+data AES128Message = AES128Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)+data AES192Message = AES192Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)+data AES256Message = AES256Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)++arbitraryAES keysize = do+ sz <- choose (1, 12)+ ws <- replicateM (sz*16) (choose (0,255) :: Gen Int)+ key <- replicateM keysize (choose (0,255) :: Gen Int)+ iv <- replicateM 16 (choose (0,255) :: Gen Int)+ return (ws, key, iv)++instance Arbitrary AES128Message where+ arbitrary = do+ (ws, key, iv) <- arbitraryAES 16+ return $ AES128Message (B.pack $ map fromIntegral key)+ (B.pack $ map fromIntegral iv)+ (B.pack $ map fromIntegral ws)++instance Arbitrary AES192Message where+ arbitrary = do+ (ws, key, iv) <- arbitraryAES 24+ return $ AES192Message (B.pack $ map fromIntegral key)+ (B.pack $ map fromIntegral iv)+ (B.pack $ map fromIntegral ws)++instance Arbitrary AES256Message where+ arbitrary = do+ (ws, key, iv) <- arbitraryAES 32+ return $ AES256Message (B.pack $ map fromIntegral key)+ (B.pack $ map fromIntegral iv)+ (B.pack $ map fromIntegral ws)+++prop_ecb_valid k msg = AES.decrypt k (AES.encrypt k msg) == msg+prop_cbc_valid k iv msg = AES.decryptCBC k iv (AES.encryptCBC k iv msg) == msg++prop_aes128_ecb_valid (AES128Message key _ msg) =+ let (Right k) = AES.initKey128 key in+ prop_ecb_valid k msg++prop_aes192_ecb_valid (AES192Message key _ msg) =+ let (Right k) = AES.initKey192 key in+ prop_ecb_valid k msg++prop_aes256_ecb_valid (AES256Message key _ msg) =+ let (Right k) = AES.initKey256 key in+ prop_ecb_valid k msg++prop_aes128_cbc_valid (AES128Message key iv msg) =+ let (Right k) = AES.initKey128 key in+ prop_cbc_valid k iv msg++prop_aes192_cbc_valid (AES192Message key iv msg) =+ let (Right k) = AES.initKey192 key in+ prop_cbc_valid k iv msg++prop_aes256_cbc_valid (AES256Message key iv msg) =+ let (Right k) = AES.initKey256 key in+ prop_cbc_valid k iv msg++{-----------------------------------------------------------------------------------------------}+{- main -}+{-----------------------------------------------------------------------------------------------}++symCipherExpectedTests = testGroup "symmetric cipher KAT" katTests++symCipherMarshallTests = testGroup "symmetric cipher marshall"+ [ testProperty "AES128 (ECB)" prop_aes128_ecb_valid+ , testProperty "AES128 (CBC)" prop_aes128_cbc_valid+ , testProperty "AES192 (ECB)" prop_aes192_ecb_valid+ , testProperty "AES192 (CBC)" prop_aes192_cbc_valid+ , testProperty "AES256 (ECB)" prop_aes256_ecb_valid+ , testProperty "AES256 (CBC)" prop_aes256_cbc_valid+ ]++asymEncryptionTests = testGroup "assymmetric cipher encryption"+ [ testProperty "RSA (slow)" prop_rsa_slow_valid+ , testProperty "RSA (fast)" prop_rsa_fast_valid+ ]++asymSignatureTests = testGroup "assymmetric cipher signature"+ [ testProperty "RSA (slow)" prop_rsa_sign_slow_valid+ , testProperty "RSA (fast)" prop_rsa_sign_fast_valid+ , testProperty "DSA" prop_dsa_valid+ ]++asymOtherTests = testGroup "assymetric other tests"+ [ testProperty "DH valid" prop_dh_valid+ ]++arithmeticTests = testGroup "arithmetic"+ []++{- run_test "RSA generate" prop_rsa_generate_valid -}++tests :: [Test]+tests =+ [ symCipherExpectedTests+ , symCipherMarshallTests+ , testGroup "AES" aesTests+ , arithmeticTests+ , asymEncryptionTests+ , asymSignatureTests+ , asymOtherTests+ ]++main = defaultMain tests+{-+ -- Number Tests+ run_test "gcde binary valid" prop_gcde_binary_valid+ run_test "exponantiation RTL valid" prop_modexp_rtl_valid+ run_test "inverse valid" prop_modinv_valid+ run_test "sqrt integer valid" prop_sqrti_valid+ run_test "primality test Miller Rabin" prop_miller_rabin_valid+ run_test "Generate prime" prop_generate_prime_valid+ -}
+ cbits/aes/x86ni.c view
@@ -0,0 +1,191 @@+/*+ * Copyright (c) 2012 Vincent Hanquez <vincent@snarc.org>+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ * notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ * notice, this list of conditions and the following disclaimer in the+ * documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ * may be used to endorse or promote products derived from this software+ * without specific prior written permission.+ * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */+#include <wmmintrin.h>+#include <tmmintrin.h>+#include "aes.h"++static __m128i aes_128_key_expansion(__m128i key, __m128i keygened)+{+ keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3,3,3,3));+ key = _mm_xor_si128(key, _mm_slli_si128(key, 4));+ key = _mm_xor_si128(key, _mm_slli_si128(key, 4));+ key = _mm_xor_si128(key, _mm_slli_si128(key, 4));+ return _mm_xor_si128(key, keygened);+}++void aes_generate_key128(aes_key128 *key, uint8_t *ikey)+{+ __m128i *k = (__m128i *) key->_data;+ k[0] = _mm_loadu_si128((const __m128i*) ikey);++#define AES_128_key_exp(K, RCON) aes_128_key_expansion(K, _mm_aeskeygenassist_si128(K, RCON))+ k[1] = AES_128_key_exp(k[0], 0x01);+ k[2] = AES_128_key_exp(k[1], 0x02);+ k[3] = AES_128_key_exp(k[2], 0x04);+ k[4] = AES_128_key_exp(k[3], 0x08);+ k[5] = AES_128_key_exp(k[4], 0x10);+ k[6] = AES_128_key_exp(k[5], 0x20);+ k[7] = AES_128_key_exp(k[6], 0x40);+ k[8] = AES_128_key_exp(k[7], 0x80);+ k[9] = AES_128_key_exp(k[8], 0x1B);+ k[10] = AES_128_key_exp(k[9], 0x36);++ /* generate decryption keys in reverse order.+ * k[10] is shared by last encryption and first decryption rounds+ * k[20] is shared by first encryption round (and is the original user key) */+ k[11] = _mm_aesimc_si128(k[9]);+ k[12] = _mm_aesimc_si128(k[8]);+ k[13] = _mm_aesimc_si128(k[7]);+ k[14] = _mm_aesimc_si128(k[6]);+ k[15] = _mm_aesimc_si128(k[5]);+ k[16] = _mm_aesimc_si128(k[4]);+ k[17] = _mm_aesimc_si128(k[3]);+ k[18] = _mm_aesimc_si128(k[2]);+ k[19] = _mm_aesimc_si128(k[1]);+}++#define PRELOAD_ENC_KEYS(k) \+ __m128i K0 = k[0]; __m128i K1 = k[1]; __m128i K2 = k[2]; __m128i K3 = k[3]; \+ __m128i K4 = k[4]; __m128i K5 = k[5]; __m128i K6 = k[6]; __m128i K7 = k[7]; \+ __m128i K8 = k[8]; __m128i K9 = k[9]; __m128i K10 = k[10];++#define DO_ENC_BLOCK(m) \+ m = _mm_xor_si128(m, K0); \+ m = _mm_aesenc_si128(m, K1); \+ m = _mm_aesenc_si128(m, K2); \+ m = _mm_aesenc_si128(m, K3); \+ m = _mm_aesenc_si128(m, K4); \+ m = _mm_aesenc_si128(m, K5); \+ m = _mm_aesenc_si128(m, K6); \+ m = _mm_aesenc_si128(m, K7); \+ m = _mm_aesenc_si128(m, K8); \+ m = _mm_aesenc_si128(m, K9); \+ m = _mm_aesenclast_si128(m, K10);++#define PRELOAD_DEC_KEYS(k) \+ __m128i K0 = k[10+0]; __m128i K1 = k[10+1]; __m128i K2 = k[10+2]; __m128i K3 = k[10+3]; \+ __m128i K4 = k[10+4]; __m128i K5 = k[10+5]; __m128i K6 = k[10+6]; __m128i K7 = k[10+7]; \+ __m128i K8 = k[10+8]; __m128i K9 = k[10+9]; __m128i K10 = k[0];++#define DO_DEC_BLOCK(m) \+ m = _mm_xor_si128(m, K0); \+ m = _mm_aesdec_si128(m, K1); \+ m = _mm_aesdec_si128(m, K2); \+ m = _mm_aesdec_si128(m, K3); \+ m = _mm_aesdec_si128(m, K4); \+ m = _mm_aesdec_si128(m, K5); \+ m = _mm_aesdec_si128(m, K6); \+ m = _mm_aesdec_si128(m, K7); \+ m = _mm_aesdec_si128(m, K8); \+ m = _mm_aesdec_si128(m, K9); \+ m = _mm_aesdeclast_si128(m, K10);++void aes_encrypt(uint8_t *out, aes_key128 *key, uint8_t *in, uint32_t blocks)+{+ uint32_t i;+ uint64_t _out[2] __attribute__((aligned(16)));+ __m128i *k = (__m128i *) key->_data;++ PRELOAD_ENC_KEYS(k);++ for (i = 0; i < blocks; i++, in += 16, out += 16) {+ __m128i m = _mm_loadu_si128((__m128i *) in);++ DO_ENC_BLOCK(m);++ _mm_store_si128((__m128i *) _out, m);+ ((uint64_t *) out)[0] = (_out[0]);+ ((uint64_t *) out)[1] = (_out[1]);+ }+}++void aes_decrypt(uint8_t *out, aes_key128 *key, uint8_t *in, uint32_t blocks)+{+ uint32_t i;+ uint64_t _out[2] __attribute__((aligned(16)));+ __m128i *k = (__m128i *) key->_data;++ PRELOAD_DEC_KEYS(k);++ for (i = 0; i < blocks; i++, in += 16, out += 16) {+ __m128i m = _mm_loadu_si128((__m128i *) in);++ DO_DEC_BLOCK(m);++ _mm_store_si128((__m128i *) _out, m);+ ((uint64_t *) out)[0] = (_out[0]);+ ((uint64_t *) out)[1] = (_out[1]);+ }+}++void aes_encrypt_cbc(uint8_t *out, aes_key128 *key, uint8_t *_iv, uint8_t *in, uint32_t blocks)+{+ uint32_t i;+ uint64_t _out[2] __attribute__((aligned(16)));+ __m128i *k = (__m128i *) key->_data;+ __m128i iv = _mm_loadu_si128((__m128i *) _iv);++ PRELOAD_ENC_KEYS(k);++ for (i = 0; i < blocks; i++, in += 16, out += 16) {+ __m128i m = _mm_loadu_si128((__m128i *) in);+ m = _mm_xor_si128(m, iv);++ DO_ENC_BLOCK(m);++ _mm_store_si128((__m128i *) _out, m);+ iv = m;+ ((uint64_t *) out)[0] = (_out[0]);+ ((uint64_t *) out)[1] = (_out[1]);+ }+}++void aes_decrypt_cbc(uint8_t *out, aes_key128 *key, uint8_t *_iv, uint8_t *in, uint32_t blocks)+{+ uint32_t i;+ uint64_t _out[2] __attribute__((aligned(16)));+ __m128i *k = (__m128i *) key->_data;+ __m128i iv = _mm_loadu_si128((__m128i *) _iv);++ PRELOAD_DEC_KEYS(k);++ for (i = 0; i < blocks; i++, in += 16, out += 16) {+ __m128i m = _mm_loadu_si128((__m128i *) in);+ __m128i ivnext = m;++ DO_DEC_BLOCK(m);+ m = _mm_xor_si128(m, iv);++ _mm_store_si128((__m128i *) _out, m);+ iv = ivnext;+ ((uint64_t *) out)[0] = (_out[0]);+ ((uint64_t *) out)[1] = (_out[1]);+ }+}
cryptocipher.cabal view
@@ -1,5 +1,5 @@ Name: cryptocipher-Version: 0.3.0+Version: 0.3.1 Description: Symmetrical Block, Stream and PubKey Ciphers License: BSD3 License-file: LICENSE@@ -10,20 +10,22 @@ Category: Cryptography Build-Type: Simple Homepage: http://github.com/vincenthz/hs-cryptocipher-Cabal-Version: >=1.6--Flag test- Description: Build unit test- Default: False+Cabal-Version: >=1.8+Extra-Source-Files: Tests/*.hs Flag benchmark Description: Build benchmarks Default: False +Flag aesni+ Description: Use fast aesni operations that are cpu dependant+ Default: False+ Library Build-Depends: base >= 4 && < 5 , bytestring , vector >= 0.7+ , cpu >= 0.1 && < 0.2 , ghc-prim , primitive , crypto-api >= 0.5@@ -32,6 +34,7 @@ , cereal Exposed-modules: Crypto.Cipher.RC4 Crypto.Cipher.AES+ Crypto.Cipher.AES.Haskell Crypto.Cipher.Camellia Crypto.Cipher.RSA Crypto.Cipher.DSA@@ -42,42 +45,45 @@ Number.Basic Number.Polynomial Number.Prime- System.Endian ghc-options: -Wall- if arch(ppc) || arch(sparc)- cpp-options: -DBIG_ENDIAN- else- cpp-options: -DLITTLE_ENDIAN+ if flag(aesni)+ cpp-options: -DHAVE_AESNI+ Exposed-modules: Crypto.Cipher.AES.X86NI+ C-sources: cbits/aes/x86ni.c+ CC-options: -mssse3 -maes -Executable Tests- Main-Is: Tests.hs- if flag(test)- Buildable: True- Build-depends: base >= 4 && < 5- , HUnit+Test-Suite test-cryptocipher+ type: exitcode-stdio-1.0+ hs-source-dirs: Tests+ Main-Is: tests.hs+ Build-depends: base >= 4 && < 5+ , crypto-api >= 0.5+ , cryptocipher , bytestring , cryptohash+ , vector+ , entropy , QuickCheck >= 2- else- Buildable: False- if arch(ppc) || arch(sparc)- cpp-options: -DBIG_ENDIAN- else- cpp-options: -DLITTLE_ENDIAN+ , test-framework >= 0.3.3 && < 0.7+ , test-framework-quickcheck2 >= 0.2.9 && < 0.3 Executable Benchmarks+ hs-source-dirs: Benchmarks Main-Is: Benchmarks.hs if flag(benchmark) Buildable: True Build-depends: base >= 4 && < 5+ , bytestring+ , crypto-api+ , cryptocipher , criterion , mtl else Buildable: False- if arch(ppc) || arch(sparc)- cpp-options: -DBIG_ENDIAN- else- cpp-options: -DLITTLE_ENDIAN+ if flag(aesni)+ cpp-options: -DHAVE_AESNI+ C-sources: cbits/aes/x86ni.c+ CC-options: -mssse3 -maes source-repository head type: git