packages feed

cryptocipher 0.2.12 → 0.2.13

raw patch · 9 files changed

+1218/−1046 lines, 9 filesdep +ghc-primdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: ghc-prim

Dependency ranges changed: base

API changes (from Hackage documentation)

Files

Crypto/Cipher/AES.hs view
@@ -1,1006 +1,1014 @@--- |--- 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 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--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` mRcon 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 gm2 #-}-		gm2 a = V.unsafeIndex gmtab2 $ fromIntegral a-		{-# INLINE gm3 #-}-		gm3 a = V.unsafeIndex gmtab3 $ fromIntegral 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 gm14 #-}-		{-# INLINE gm13 #-}-		{-# INLINE gm11 #-}-		{-# INLINE gm9 #-}-		gm14 a = V.unsafeIndex gmtab14 $ fromIntegral a-		gm13 a = V.unsafeIndex gmtab13 $ fromIntegral a-		gm11 a = V.unsafeIndex gmtab11 $ fromIntegral a-		gm9 a  = V.unsafeIndex gmtab9 $ fromIntegral a--{-# 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 mRcon #-}-mRcon :: Int -> Word8-mRcon i = V.unsafeIndex rcon (i `mod` len)-	where len = V.length rcon--{-# INLINE sbox #-}-sbox :: Word8 -> Word8-sbox = V.unsafeIndex tab . fromIntegral-	where tab = V.fromList-		[ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5-		, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76-		, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0-		, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0-		, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc-		, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15-		, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a-		, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75-		, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0-		, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84-		, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b-		, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf-		, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85-		, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8-		, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5-		, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2-		, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17-		, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73-		, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88-		, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb-		, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c-		, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79-		, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9-		, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08-		, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6-		, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a-		, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e-		, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e-		, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94-		, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf-		, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68-		, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16-		]--sbox1, sbox2, sbox3, sbox4 :: Word8 -> Word32--sbox1 = V.unsafeIndex tab . fromIntegral-	where tab = V.fromList-		[ 0x00000063, 0x0000007c, 0x00000077, 0x0000007b-		, 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5-		, 0x00000030, 0x00000001, 0x00000067, 0x0000002b-		, 0x000000fe, 0x000000d7, 0x000000ab, 0x00000076-		, 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d-		, 0x000000fa, 0x00000059, 0x00000047, 0x000000f0-		, 0x000000ad, 0x000000d4, 0x000000a2, 0x000000af-		, 0x0000009c, 0x000000a4, 0x00000072, 0x000000c0-		, 0x000000b7, 0x000000fd, 0x00000093, 0x00000026-		, 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc-		, 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1-		, 0x00000071, 0x000000d8, 0x00000031, 0x00000015-		, 0x00000004, 0x000000c7, 0x00000023, 0x000000c3-		, 0x00000018, 0x00000096, 0x00000005, 0x0000009a-		, 0x00000007, 0x00000012, 0x00000080, 0x000000e2-		, 0x000000eb, 0x00000027, 0x000000b2, 0x00000075-		, 0x00000009, 0x00000083, 0x0000002c, 0x0000001a-		, 0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0-		, 0x00000052, 0x0000003b, 0x000000d6, 0x000000b3-		, 0x00000029, 0x000000e3, 0x0000002f, 0x00000084-		, 0x00000053, 0x000000d1, 0x00000000, 0x000000ed-		, 0x00000020, 0x000000fc, 0x000000b1, 0x0000005b-		, 0x0000006a, 0x000000cb, 0x000000be, 0x00000039-		, 0x0000004a, 0x0000004c, 0x00000058, 0x000000cf-		, 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb-		, 0x00000043, 0x0000004d, 0x00000033, 0x00000085-		, 0x00000045, 0x000000f9, 0x00000002, 0x0000007f-		, 0x00000050, 0x0000003c, 0x0000009f, 0x000000a8-		, 0x00000051, 0x000000a3, 0x00000040, 0x0000008f-		, 0x00000092, 0x0000009d, 0x00000038, 0x000000f5-		, 0x000000bc, 0x000000b6, 0x000000da, 0x00000021-		, 0x00000010, 0x000000ff, 0x000000f3, 0x000000d2-		, 0x000000cd, 0x0000000c, 0x00000013, 0x000000ec-		, 0x0000005f, 0x00000097, 0x00000044, 0x00000017-		, 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d-		, 0x00000064, 0x0000005d, 0x00000019, 0x00000073-		, 0x00000060, 0x00000081, 0x0000004f, 0x000000dc-		, 0x00000022, 0x0000002a, 0x00000090, 0x00000088-		, 0x00000046, 0x000000ee, 0x000000b8, 0x00000014-		, 0x000000de, 0x0000005e, 0x0000000b, 0x000000db-		, 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a-		, 0x00000049, 0x00000006, 0x00000024, 0x0000005c-		, 0x000000c2, 0x000000d3, 0x000000ac, 0x00000062-		, 0x00000091, 0x00000095, 0x000000e4, 0x00000079-		, 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d-		, 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9-		, 0x0000006c, 0x00000056, 0x000000f4, 0x000000ea-		, 0x00000065, 0x0000007a, 0x000000ae, 0x00000008-		, 0x000000ba, 0x00000078, 0x00000025, 0x0000002e-		, 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6-		, 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f-		, 0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a-		, 0x00000070, 0x0000003e, 0x000000b5, 0x00000066-		, 0x00000048, 0x00000003, 0x000000f6, 0x0000000e-		, 0x00000061, 0x00000035, 0x00000057, 0x000000b9-		, 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e-		, 0x000000e1, 0x000000f8, 0x00000098, 0x00000011-		, 0x00000069, 0x000000d9, 0x0000008e, 0x00000094-		, 0x0000009b, 0x0000001e, 0x00000087, 0x000000e9-		, 0x000000ce, 0x00000055, 0x00000028, 0x000000df-		, 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d-		, 0x000000bf, 0x000000e6, 0x00000042, 0x00000068-		, 0x00000041, 0x00000099, 0x0000002d, 0x0000000f-		, 0x000000b0, 0x00000054, 0x000000bb, 0x00000016-		]--sbox2 = V.unsafeIndex tab . fromIntegral-	where tab = V.fromList-		[ 0x00006300, 0x00007c00, 0x00007700, 0x00007b00-		, 0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500-		, 0x00003000, 0x00000100, 0x00006700, 0x00002b00-		, 0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600-		, 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00-		, 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000-		, 0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00-		, 0x00009c00, 0x0000a400, 0x00007200, 0x0000c000-		, 0x0000b700, 0x0000fd00, 0x00009300, 0x00002600-		, 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00-		, 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100-		, 0x00007100, 0x0000d800, 0x00003100, 0x00001500-		, 0x00000400, 0x0000c700, 0x00002300, 0x0000c300-		, 0x00001800, 0x00009600, 0x00000500, 0x00009a00-		, 0x00000700, 0x00001200, 0x00008000, 0x0000e200-		, 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500-		, 0x00000900, 0x00008300, 0x00002c00, 0x00001a00-		, 0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000-		, 0x00005200, 0x00003b00, 0x0000d600, 0x0000b300-		, 0x00002900, 0x0000e300, 0x00002f00, 0x00008400-		, 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00-		, 0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00-		, 0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900-		, 0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00-		, 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00-		, 0x00004300, 0x00004d00, 0x00003300, 0x00008500-		, 0x00004500, 0x0000f900, 0x00000200, 0x00007f00-		, 0x00005000, 0x00003c00, 0x00009f00, 0x0000a800-		, 0x00005100, 0x0000a300, 0x00004000, 0x00008f00-		, 0x00009200, 0x00009d00, 0x00003800, 0x0000f500-		, 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100-		, 0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200-		, 0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00-		, 0x00005f00, 0x00009700, 0x00004400, 0x00001700-		, 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00-		, 0x00006400, 0x00005d00, 0x00001900, 0x00007300-		, 0x00006000, 0x00008100, 0x00004f00, 0x0000dc00-		, 0x00002200, 0x00002a00, 0x00009000, 0x00008800-		, 0x00004600, 0x0000ee00, 0x0000b800, 0x00001400-		, 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00-		, 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00-		, 0x00004900, 0x00000600, 0x00002400, 0x00005c00-		, 0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200-		, 0x00009100, 0x00009500, 0x0000e400, 0x00007900-		, 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00-		, 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900-		, 0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00-		, 0x00006500, 0x00007a00, 0x0000ae00, 0x00000800-		, 0x0000ba00, 0x00007800, 0x00002500, 0x00002e00-		, 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600-		, 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00-		, 0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00-		, 0x00007000, 0x00003e00, 0x0000b500, 0x00006600-		, 0x00004800, 0x00000300, 0x0000f600, 0x00000e00-		, 0x00006100, 0x00003500, 0x00005700, 0x0000b900-		, 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00-		, 0x0000e100, 0x0000f800, 0x00009800, 0x00001100-		, 0x00006900, 0x0000d900, 0x00008e00, 0x00009400-		, 0x00009b00, 0x00001e00, 0x00008700, 0x0000e900-		, 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00-		, 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00-		, 0x0000bf00, 0x0000e600, 0x00004200, 0x00006800-		, 0x00004100, 0x00009900, 0x00002d00, 0x00000f00-		, 0x0000b000, 0x00005400, 0x0000bb00, 0x00001600-		]--sbox3 = V.unsafeIndex tab . fromIntegral-	where tab = V.fromList-		[ 0x00630000, 0x007c0000, 0x00770000, 0x007b0000-		, 0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000-		, 0x00300000, 0x00010000, 0x00670000, 0x002b0000-		, 0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000-		, 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000-		, 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000-		, 0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000-		, 0x009c0000, 0x00a40000, 0x00720000, 0x00c00000-		, 0x00b70000, 0x00fd0000, 0x00930000, 0x00260000-		, 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000-		, 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000-		, 0x00710000, 0x00d80000, 0x00310000, 0x00150000-		, 0x00040000, 0x00c70000, 0x00230000, 0x00c30000-		, 0x00180000, 0x00960000, 0x00050000, 0x009a0000-		, 0x00070000, 0x00120000, 0x00800000, 0x00e20000-		, 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000-		, 0x00090000, 0x00830000, 0x002c0000, 0x001a0000-		, 0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000-		, 0x00520000, 0x003b0000, 0x00d60000, 0x00b30000-		, 0x00290000, 0x00e30000, 0x002f0000, 0x00840000-		, 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000-		, 0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000-		, 0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000-		, 0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000-		, 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000-		, 0x00430000, 0x004d0000, 0x00330000, 0x00850000-		, 0x00450000, 0x00f90000, 0x00020000, 0x007f0000-		, 0x00500000, 0x003c0000, 0x009f0000, 0x00a80000-		, 0x00510000, 0x00a30000, 0x00400000, 0x008f0000-		, 0x00920000, 0x009d0000, 0x00380000, 0x00f50000-		, 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000-		, 0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000-		, 0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000-		, 0x005f0000, 0x00970000, 0x00440000, 0x00170000-		, 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000-		, 0x00640000, 0x005d0000, 0x00190000, 0x00730000-		, 0x00600000, 0x00810000, 0x004f0000, 0x00dc0000-		, 0x00220000, 0x002a0000, 0x00900000, 0x00880000-		, 0x00460000, 0x00ee0000, 0x00b80000, 0x00140000-		, 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000-		, 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000-		, 0x00490000, 0x00060000, 0x00240000, 0x005c0000-		, 0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000-		, 0x00910000, 0x00950000, 0x00e40000, 0x00790000-		, 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000-		, 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000-		, 0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000-		, 0x00650000, 0x007a0000, 0x00ae0000, 0x00080000-		, 0x00ba0000, 0x00780000, 0x00250000, 0x002e0000-		, 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000-		, 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000-		, 0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000-		, 0x00700000, 0x003e0000, 0x00b50000, 0x00660000-		, 0x00480000, 0x00030000, 0x00f60000, 0x000e0000-		, 0x00610000, 0x00350000, 0x00570000, 0x00b90000-		, 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000-		, 0x00e10000, 0x00f80000, 0x00980000, 0x00110000-		, 0x00690000, 0x00d90000, 0x008e0000, 0x00940000-		, 0x009b0000, 0x001e0000, 0x00870000, 0x00e90000-		, 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000-		, 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000-		, 0x00bf0000, 0x00e60000, 0x00420000, 0x00680000-		, 0x00410000, 0x00990000, 0x002d0000, 0x000f0000-		, 0x00b00000, 0x00540000, 0x00bb0000, 0x00160000-		]--sbox4 = V.unsafeIndex tab . fromIntegral-	where tab = V.fromList-		[ 0x63000000, 0x7c000000, 0x77000000, 0x7b000000-		, 0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000-		, 0x30000000, 0x01000000, 0x67000000, 0x2b000000-		, 0xfe000000, 0xd7000000, 0xab000000, 0x76000000-		, 0xca000000, 0x82000000, 0xc9000000, 0x7d000000-		, 0xfa000000, 0x59000000, 0x47000000, 0xf0000000-		, 0xad000000, 0xd4000000, 0xa2000000, 0xaf000000-		, 0x9c000000, 0xa4000000, 0x72000000, 0xc0000000-		, 0xb7000000, 0xfd000000, 0x93000000, 0x26000000-		, 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000-		, 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000-		, 0x71000000, 0xd8000000, 0x31000000, 0x15000000-		, 0x04000000, 0xc7000000, 0x23000000, 0xc3000000-		, 0x18000000, 0x96000000, 0x05000000, 0x9a000000-		, 0x07000000, 0x12000000, 0x80000000, 0xe2000000-		, 0xeb000000, 0x27000000, 0xb2000000, 0x75000000-		, 0x09000000, 0x83000000, 0x2c000000, 0x1a000000-		, 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000-		, 0x52000000, 0x3b000000, 0xd6000000, 0xb3000000-		, 0x29000000, 0xe3000000, 0x2f000000, 0x84000000-		, 0x53000000, 0xd1000000, 0x00000000, 0xed000000-		, 0x20000000, 0xfc000000, 0xb1000000, 0x5b000000-		, 0x6a000000, 0xcb000000, 0xbe000000, 0x39000000-		, 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000-		, 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000-		, 0x43000000, 0x4d000000, 0x33000000, 0x85000000-		, 0x45000000, 0xf9000000, 0x02000000, 0x7f000000-		, 0x50000000, 0x3c000000, 0x9f000000, 0xa8000000-		, 0x51000000, 0xa3000000, 0x40000000, 0x8f000000-		, 0x92000000, 0x9d000000, 0x38000000, 0xf5000000-		, 0xbc000000, 0xb6000000, 0xda000000, 0x21000000-		, 0x10000000, 0xff000000, 0xf3000000, 0xd2000000-		, 0xcd000000, 0x0c000000, 0x13000000, 0xec000000-		, 0x5f000000, 0x97000000, 0x44000000, 0x17000000-		, 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000-		, 0x64000000, 0x5d000000, 0x19000000, 0x73000000-		, 0x60000000, 0x81000000, 0x4f000000, 0xdc000000-		, 0x22000000, 0x2a000000, 0x90000000, 0x88000000-		, 0x46000000, 0xee000000, 0xb8000000, 0x14000000-		, 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000-		, 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000-		, 0x49000000, 0x06000000, 0x24000000, 0x5c000000-		, 0xc2000000, 0xd3000000, 0xac000000, 0x62000000-		, 0x91000000, 0x95000000, 0xe4000000, 0x79000000-		, 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000-		, 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000-		, 0x6c000000, 0x56000000, 0xf4000000, 0xea000000-		, 0x65000000, 0x7a000000, 0xae000000, 0x08000000-		, 0xba000000, 0x78000000, 0x25000000, 0x2e000000-		, 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000-		, 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000-		, 0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000-		, 0x70000000, 0x3e000000, 0xb5000000, 0x66000000-		, 0x48000000, 0x03000000, 0xf6000000, 0x0e000000-		, 0x61000000, 0x35000000, 0x57000000, 0xb9000000-		, 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000-		, 0xe1000000, 0xf8000000, 0x98000000, 0x11000000-		, 0x69000000, 0xd9000000, 0x8e000000, 0x94000000-		, 0x9b000000, 0x1e000000, 0x87000000, 0xe9000000-		, 0xce000000, 0x55000000, 0x28000000, 0xdf000000-		, 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000-		, 0xbf000000, 0xe6000000, 0x42000000, 0x68000000-		, 0x41000000, 0x99000000, 0x2d000000, 0x0f000000-		, 0xb0000000, 0x54000000, 0xbb000000, 0x16000000-		]--{-# INLINE rsbox #-}-rsbox :: Word8 -> Word8-rsbox = V.unsafeIndex tab . fromIntegral-	where tab = V.fromList-		[ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38-		, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb-		, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87-		, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb-		, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d-		, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e-		, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2-		, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25-		, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16-		, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92-		, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda-		, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84-		, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a-		, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06-		, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02-		, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b-		, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea-		, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73-		, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85-		, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e-		, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89-		, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b-		, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20-		, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4-		, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31-		, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f-		, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d-		, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef-		, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0-		, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61-		, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26-		, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d-		]--rcon :: Vector Word8-rcon = V.fromList-	[ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40-	, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a-	, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a-	, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39-	, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25-	, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a-	, 0x74, 0xe8, 0xcb-	]--gmtab2, gmtab3, gmtab9, gmtab11, gmtab13, gmtab14 :: Vector Word8-gmtab2 = V.fromList-	[ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e-	, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e-	, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e-	, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e-	, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e-	, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e-	, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e-	, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e-	, 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e-	, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e-	, 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae-	, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe-	, 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce-	, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde-	, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee-	, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe-	, 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15-	, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05-	, 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35-	, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25-	, 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55-	, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45-	, 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75-	, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65-	, 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95-	, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85-	, 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5-	, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5-	, 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5-	, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5-	, 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5-	, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5-	]--gmtab3 = V.fromList-	[ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09-	, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11-	, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39-	, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21-	, 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69-	, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71-	, 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59-	, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41-	, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9-	, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1-	, 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9-	, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1-	, 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9-	, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1-	, 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99-	, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81-	, 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92-	, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a-	, 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2-	, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba-	, 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2-	, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea-	, 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2-	, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda-	, 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52-	, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a-	, 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62-	, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a-	, 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32-	, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a-	, 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02-	, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a-	]--gmtab9 = V.fromList-	[ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f-	, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77-	, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf-	, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7-	, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04-	, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c-	, 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94-	, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc-	, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49-	, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01-	, 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9-	, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91-	, 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72-	, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a-	, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2-	, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa-	, 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3-	, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b-	, 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43-	, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b-	, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8-	, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0-	, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78-	, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30-	, 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5-	, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed-	, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35-	, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d-	, 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e-	, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6-	, 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e-	, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46-	]--gmtab11 = V.fromList-	[ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31-	, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69-	, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81-	, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9-	, 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a-	, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12-	, 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa-	, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2-	, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7-	, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f-	, 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77-	, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f-	, 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc-	, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4-	, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c-	, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54-	, 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6-	, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e-	, 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76-	, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e-	, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd-	, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5-	, 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d-	, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55-	, 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30-	, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68-	, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80-	, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8-	, 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b-	, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13-	, 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb-	, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3-	]--gmtab13 = V.fromList-	[ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23-	, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b-	, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3-	, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b-	, 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98-	, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0-	, 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48-	, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20-	, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e-	, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26-	, 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e-	, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6-	, 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5-	, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d-	, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25-	, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d-	, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9-	, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91-	, 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29-	, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41-	, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42-	, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a-	, 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92-	, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa-	, 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94-	, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc-	, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44-	, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c-	, 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f-	, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47-	, 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff-	, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97-	]--gmtab14 = V.fromList-	[ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a-	, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a-	, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca-	, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba-	, 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1-	, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81-	, 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11-	, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61-	, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87-	, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7-	, 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67-	, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17-	, 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c-	, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c-	, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc-	, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc-	, 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b-	, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b-	, 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b-	, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb-	, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0-	, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0-	, 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50-	, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20-	, 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6-	, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6-	, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26-	, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56-	, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d-	, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d-	, 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd-	, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d-	]+{-# LANGUAGE 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"#
Number/Basic.hs view
@@ -1,4 +1,11 @@ {-# LANGUAGE BangPatterns #-}+-- |+-- Module      : Number.Basic+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good+ module Number.Basic 	( sqrti 	, gcde
Number/Generate.hs view
@@ -1,3 +1,10 @@+-- |+-- Module      : Number.Generate+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good+ module Number.Generate 	( generateMax 	, generateBetween@@ -12,7 +19,7 @@ -- | generate a positive integer between 0 and m. -- using as many bytes as necessary to the same size as m, that are converted to integer. generateMax :: CryptoRandomGen g => g -> Integer -> Either GenError (Integer, g)-generateMax rng m = case genBytes (logiBytes m) rng of+generateMax rng m = case genBytes (lengthBytes m) rng of 	Left err         -> Left err 	Right (bs, rng') -> Right (os2ip bs `mod` m, rng') @@ -29,8 +36,3 @@ generateOfSize rng bits = case genBytes (bits `div` 8) rng of 	Left err         -> Left err 	Right (bs, rng') -> Right (os2ip $ snd $ B.mapAccumL (\acc w -> (0, w .|. acc)) 0xc0 bs, rng')--logiBytes :: Integer -> Int-logiBytes n-	| n < 256   = 1-	| otherwise = 1 + logiBytes (n `div` 256)
Number/ModArithmetic.hs view
@@ -1,4 +1,11 @@ {-# LANGUAGE BangPatterns #-}+-- |+-- Module      : Number.ModArithmetic+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good+ module Number.ModArithmetic 	( exponantiation_rtl_binary 	, inverse
+ Number/Polynomial.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE BangPatterns #-}+-- |+-- Module      : Number.Polynomial+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good++module Number.Polynomial+	( Monomial(..)+	-- * polynomial operations+	, Polynomial+	, toList+	, fromList+	, addPoly+	, subPoly+	, mulPoly+	, squarePoly+	, expPoly+	, divPoly+	, negPoly+	) where++import Data.List (intercalate, sort)+import Data.Vector ((!), Vector)+import qualified Data.Vector as V+import Control.Arrow (first)++data Monomial = Monomial {-# UNPACK #-} !Int !Integer+	deriving (Eq)++data Polynomial = Polynomial (Vector Monomial)+	deriving (Eq)++instance Ord Monomial where+	compare (Monomial w1 v1) (Monomial w2 v2) =+		case compare w1 w2 of+			EQ -> compare v1 v2+			r  -> r++instance Show Monomial where+	show (Monomial w v) = show v ++ "x^" ++ show w++instance Show Polynomial where+	show (Polynomial p) = intercalate "+" $ map show $ V.toList p++toList (Polynomial p) = V.toList p++fromList = Polynomial . V.fromList . reverse . sort . filterZero+	where+		filterZero = filter (\(Monomial _ v) -> v /= 0)++getWeight (Polynomial p) n = look 0+	where+		plen = V.length p+		look !i+			| i >= plen = Nothing+			| otherwise =+				let (Monomial w v) = p ! i in+				case compare w n of+					LT -> Nothing+					EQ -> Just v+					GT -> look (i+1)+		++mergePoly f (Polynomial p1) (Polynomial p2) = fromList $ loop 0 0+	where+		l1 = V.length p1+		l2 = V.length p2+		loop !i1 !i2+			| i1 == l1 && i2 == l2 = []+			| i1 == l1             = (p2 ! i2) : loop i1 (i2+1)+			| i2 == l2             = (p1 ! i1) : loop (i1+1) i2+			| 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) =+			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 = mergePoly (+)+subPoly = mergePoly (-)++negPoly (Polynomial p) = Polynomial $ V.map negateMonomial p+	where negateMonomial (Monomial w v) = Monomial w (-v)++mulPoly p1@(Polynomial v1) p2@(Polynomial v2) =+	fromList $ filter (\(Monomial _ v) -> v /= 0) $ map (\i -> Monomial i (c i)) $ reverse [0..(m+n)]+	where+		(Monomial m _) = v1 ! 0+		(Monomial n _) = v2 ! 0+		c r = foldl (\acc i -> (b $ r-i) * (a $ i) + acc) 0 [0..r]+			where+				a = maybe 0 id . getWeight p1+				b = maybe 0 id . getWeight p2++squarePoly p = p `mulPoly` p++expPoly p e = loop e+	where+		loop t 0 = t+		loop t n = loop (squarePoly t) (n-1)++divPoly :: Polynomial -> Polynomial -> (Polynomial, Polynomial)+divPoly p1 p2@(Polynomial pp2) = first fromList $ divLoop p1+	where divLoop d1@(Polynomial pp1)+		| V.null pp1 = ([], d1)+		| otherwise  =+			let (Monomial w1 v1) = pp1 ! 0 in+			let (Monomial w2 v2) = pp2 ! 0 in+			let w = w1 - w2 in+			let (v,r) = v1 `divMod` v2 in+			if w >= 0 && r == 0+				then+					let mono = (Monomial w v) in+					let remain = d1 `subPoly` (p2 `mulPoly` (fromList [mono])) in+					let (l, finalRem) = divLoop remain in+					(mono : l, finalRem)+				else+					([], d1)
Number/Prime.hs view
@@ -1,3 +1,11 @@+{-# LANGUAGE BangPatterns #-}+-- |+-- Module      : Number.Prime+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good+ module Number.Prime 	( generatePrime 	, generateSafePrime@@ -5,7 +13,6 @@ 	, findPrimeFrom 	, findPrimeFromWith 	, primalityTestNaive-	-- , primalityTestAKS 	, primalityTestMillerRabin 	, isCoprime 	) where@@ -20,7 +27,7 @@ -- first a list of small primes are implicitely tested for divisibility, -- 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+isProbablyPrime rng !n 	| any (\p -> p `divides` n) (filter (< n) smallPrimes) = Right (False, rng) 	| otherwise                                            = primalityTestMillerRabin rng 30 n @@ -31,7 +38,7 @@ 	Right (sp, rng') -> findPrimeFrom rng' sp  -- | generate a prime number of the form 2p+1 where p is also prime.--- it is also know as a Sophie Germaine prime or safe prime.+-- it is also knowed as a Sophie Germaine prime or safe prime. -- -- The number of safe prime is significantly smaller to the number of prime, -- as such it shouldn't be used if this number is supposed to be kept safe.@@ -44,7 +51,7 @@  -- | find a prime from a starting point where the property hold. findPrimeFromWith :: CryptoRandomGen g => g -> (g -> Integer -> Either GenError (Bool,g)) -> Integer -> Either GenError (Integer, g)-findPrimeFromWith rng prop n+findPrimeFromWith rng prop !n 	| even n        = findPrimeFromWith rng prop (n+1) 	| otherwise     = case isProbablyPrime rng n of 		Left err               -> Left err@@ -62,52 +69,32 @@ -- | Miller Rabin algorithm return if the number is probably prime or composite. -- the tries parameter is the number of recursion, that determines the accuracy of the test. primalityTestMillerRabin :: CryptoRandomGen g => g -> Int -> Integer -> Either GenError (Bool, g)-primalityTestMillerRabin rng tries n+primalityTestMillerRabin rng tries !n 	| n <= 3     = error "Miller-Rabin requires tested value to be > 3" 	| even n     = Right (False, rng) 	| tries <= 0 = error "Miller-Rabin tries need to be > 0" 	| otherwise  = loop rng (factorise 0 (n-1)) tries where 		-- factorise n-1 into the form 2^s*d 		factorise :: Integer -> Integer -> (Integer, Integer)-		factorise s v+		factorise !s !v 			| v `testBit` 0 = (s, v) 			| otherwise     = factorise (s+1) (v `shiftR` 1) 		expmod = exponantiation_rtl_binary 		-- when iteration reach zero, we have a probable prime-		loop g _     0 = Right (True, g)-		loop g (s,d) k = case generateBetween g 2 (n-2) of+		loop g _       0 = Right (True, g)+		loop g t@(_,d) k = case generateBetween g 2 (n-2) of 			Left err      -> Left err 			Right (a, g') -> 				let x = expmod a d n in 				if x == (1 :: Integer) || x == (n-1)-					then loop g' (s,d) (k-1)-					else loop' g' (s,d) (k-1) ((x*x) `mod` n) 1+					then loop g' t (k-1)+					else loop' g' t (k-1) ((x*x) `mod` n) 1 		-- loop from 1 to s-1. if we reach the end then it's composite-		loop' g o@(s,_) km1 x2 r+		loop' g t@(s,_) km1 !x2 !r 			| r == s      = Right (False, g) 			| x2 == 1     = Right (False, g)-			| x2 /= (n-1) = loop' g o km1 ((x2*x2) `mod` n) (r+1)-			| otherwise   = loop g o km1-			--- | AKS primality test return if the number is prime or composite--- it uses the following algorithm:---   Input: integer n > 1.---   If n = ab for integers a > 0 and b > 1, output composite.---   Find the smallest r such that o_r(n) > log2(n).---   If 1 < gcd(a,n) < n for some a ≤ r, output composite.---   If n <= r, output prime.---   For a = 1 to lower-bound(sqrt(phi(n)) * log2(n)) do---     if (X+a)n ≠ Xn+a (mod Xr − 1,n), output composite;---   Output prime.-primalityTestAKS :: Integer -> Bool-primalityTestAKS n = undefined-	where-		-- for p prime, the euler totient (# of coprime to n) is clearly n -1-		totient = n-1-		ubound = (fst $ sqrti totient) * (logi n)-		logi z-			| z == 0    = 0-			| otherwise = 1 + logi (z `shiftR` 1)+			| x2 /= (n-1) = loop' g t km1 ((x2*x2) `mod` n) (r+1)+			| otherwise   = loop g t km1  -- | Test naively is integer is prime. -- while naive, we skip even number and stop iteration at i > sqrt(n)
Number/Serialize.hs view
@@ -1,6 +1,7 @@ module Number.Serialize 	( i2osp 	, os2ip+	, lengthBytes 	) where  import Data.ByteString (ByteString)@@ -17,3 +18,9 @@ 	where 		divMod256 0 = Nothing 		divMod256 n = Just (fromIntegral a,b) where (b,a) = n `divMod` 256++-- | returns the number of bytes to store an integer with i2osp+lengthBytes :: Integer -> Int+lengthBytes n+	| n < 256   = 1+	| otherwise = 1 + lengthBytes (n `div` 256)
+ System/Endian.hs view
@@ -0,0 +1,17 @@+{-# 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
cryptocipher.cabal view
@@ -1,5 +1,5 @@ Name:                cryptocipher-Version:             0.2.12+Version:             0.2.13 Description:         Symmetrical Block, Stream and PubKey Ciphers License:             BSD3 License-file:        LICENSE@@ -24,6 +24,7 @@   Build-Depends:     base >= 4 && < 5                    , bytestring                    , vector >= 0.7+                   , ghc-prim                    , primitive                    , crypto-api >= 0.5                    , tagged@@ -38,8 +39,14 @@                      Number.Serialize                      Number.Generate                      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  Executable           Tests   Main-Is:           Tests.hs@@ -52,6 +59,10 @@                    , QuickCheck >= 2   else     Buildable:       False+  if arch(ppc) || arch(sparc)+    cpp-options: -DBIG_ENDIAN+  else+    cpp-options: -DLITTLE_ENDIAN  Executable           Benchmarks   Main-Is:           Benchmarks.hs@@ -62,6 +73,10 @@                    , mtl   else     Buildable:       False+  if arch(ppc) || arch(sparc)+    cpp-options: -DBIG_ENDIAN+  else+    cpp-options: -DLITTLE_ENDIAN  source-repository head   type:     git