Hi,

After a few weeks of hard work I have managed to add the CTR, CMAC and
SIV modes of operation. The implemententation passes all the KATS I
could find and is made as efficiently as possible without forgetting the
risk of timing attacks over them. The patch is attached here and you can
free it along with your library  with a BSD-3 license as long as you
recognize  the authorship.

Francisco Blas Izquierdo Riera (klondike)

PS: Attached is also a set of commands I used with ghci to check quickly
the implementation and which contain parts of the KATS I used, feel free
to use them.

diff -ur crypto-api-0.5.2/Crypto/Modes.hs crypto-api-0.5.2.new/Crypto/Modes.hs
--- crypto-api-0.5.2/Crypto/Modes.hs    2011-02-16 17:46:11.000000000 +0100
+++ crypto-api-0.5.2.new/Crypto/Modes.hs        2011-04-09 01:44:06.743745436 
+0200
@@ -12,7 +12,7 @@
        (
        -- * Initialization Vector Type (for all ciphers for all modes that use 
IVs)
          IV
-       , getIV, getIVIO
+       , getIV, getIVIO, zeroIV
        -- * Blockcipher modes of operation.  Note name' (with a prime) means 
strict, without a prime means lazy bytestrings.
        , ecb, unEcb
        , cbc, unCbc
@@ -28,7 +28,9 @@
        -- , gmc
        -- , xts
        -- , ccm
-       -- , ctr, unCtr, ctr', unCtr'
+       , cMac', cMac
+       , ctr, unCtr, ctr', unCtr', incIV, dblIV
+       , siv, unSiv, siv', unSiv'
        ) where
 
 import qualified Data.ByteString as B
@@ -36,12 +38,15 @@
 import Data.Serialize
 import qualified Data.Serialize.Put as SP
 import qualified Data.Serialize.Get as SG
-import Data.Bits (xor)
+import Data.Bits 
(xor,shift,(.&.),(.|.),testBit,setBit,clearBit,Bits,complementBit)
 import Data.Tagged
 import Crypto.Classes
 import Crypto.Random
+import Crypto.CPoly
 import System.Crypto.Random (getEntropy)
 import Control.Monad (liftM)
+import Data.Word (Word8)
+import Data.List (genericDrop,genericReplicate,genericLength)
 #if MIN_VERSION_tagged(0,2,0)
 import Data.Proxy
 #endif
@@ -120,10 +125,10 @@
        in (c:cs, ivFinal)
 
 cbcMac' :: BlockCipher k => k -> B.ByteString -> B.ByteString
-cbcMac' k pt = encode $ snd $ cbc' k (IV (B.replicate (blockSize `for` k) 0)) 
pt
+cbcMac' k pt = encode $ snd $ cbc' k zeroIV pt
 
 cbcMac :: BlockCipher k => k -> L.ByteString -> L.ByteString
-cbcMac k pt = L.fromChunks [encode $ snd $ cbc k (IV (B.replicate (blockSize 
`for` k) 0)) pt]
+cbcMac k pt = L.fromChunks [encode $ snd $ cbc k zeroIV pt]
 
 -- |Cipher block chaining decryption for strict bytestrings
 unCbc' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
@@ -261,6 +266,253 @@
            newIV = IV . B.concat . L.toChunks . L.take (fromIntegral ivLen) . 
L.drop mLen . L.fromChunks $ ivStr
        in (zwp' (B.concat ivStr) msg, newIV)
 
+-- |Counter mode for lazy bytestrings
+ctr :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> L.ByteString -> 
(L.ByteString, IV k)
+ctr = unCtr
+
+-- |Counter  mode for lazy bytestrings
+unCtr :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> L.ByteString -> 
(L.ByteString, IV k)
+unCtr f k (IV iv) msg =
+       let ivStr = iterate f $ IV iv
+           ivLen = fromIntegral $ B.length iv
+           newIV = head $ genericDrop ((ivLen - 1 + L.length msg) `div` ivLen) 
ivStr
+       in (zwp (L.fromChunks $ map (encryptBlock k) $ map initializationVector 
ivStr) msg, newIV)
+
+-- |Counter mode for strict bytestrings
+ctr' :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> B.ByteString -> 
(B.ByteString, IV k)
+ctr' = unCtr'
+
+-- |Counter mode for strict bytestrings
+unCtr' :: BlockCipher k => (IV k -> IV k) -> k -> IV k -> B.ByteString -> 
(B.ByteString, IV k)
+unCtr' f k (IV iv) msg =
+       let ivStr = iterate f $ IV iv
+           ivLen = fromIntegral $ B.length iv
+           newIV = head $ genericDrop ((ivLen - 1 + B.length msg) `div` ivLen) 
ivStr
+       in (zwp' (B.concat $ collect (B.length msg) (map (encryptBlock k . 
initializationVector) ivStr)) msg, newIV)
+
+-- |Generate cmac subkeys
+-- |The usage of seq tries to force evaluation of both keys avoiding posible 
timing attacks
+cMacSubk :: BlockCipher k => k -> (IV k, IV k)
+cMacSubk k = (k1, k2) `seq` (k1, k2)
+  where
+       bSize = blockSizeBytes `for` k
+       k1 = dblIV $ IV $ encryptBlock k $ B.replicate bSize 0
+       k2 = dblIV $ k1
+
+-- |Pad the string as required by the cmac algorithm. In theory this should 
work
+-- | at bit level but since the API works at byte level we do the same
+cMacPad :: ([Word8], Bool, Int) -> Maybe (Word8,([Word8], Bool, Int))
+cMacPad (_, _, 0) = Nothing
+cMacPad ([], False, n) = Just (0,([], False, n-1))
+cMacPad ([], True, n) = Just (128,([], False, n-1))
+cMacPad (x:xs, b, n) =  Just (x,(xs, b, n-1))
+
+-- |Obtain the cmac with the specified subkey for lazy bytestrings
+cMacWithSubK :: BlockCipher k => k -> (IV k, IV k) -> L.ByteString -> 
L.ByteString
+cMacWithSubK k (IV k1, IV k2) l = L.fromChunks $ [go (chunkFor k t) $ 
B.replicate bSize1 0]
+  where
+       bSize1 = fromIntegral $ blockSizeBytes `for` k
+       bSize2 = fromIntegral $ blockSizeBytes `for` k
+       (t,e) = L.splitAt (((L.length l-1)`div` bSize2)*bSize2) l
+       pe =  fst $ B.unfoldrN (bSize1) cMacPad (L.unpack e,True,bSize1)
+       fe | bSize2 == L.length e = zwp' k1 pe
+          | otherwise =  zwp' k2 pe
+       go [] c = encryptBlock k (zwp' c fe)
+       go (x:xs) c = go xs $ encryptBlock k $ zwp' c x
+
+-- |Obtain the cmac for lazy bytestrings
+cMac :: BlockCipher k => k -> L.ByteString -> L.ByteString
+cMac k = cMacWithSubK k (cMacSubk k)
+
+-- |Obtain the cmac with the specified subkey for strict bytestrings
+cMacWithSubK' :: BlockCipher k => k -> (IV k, IV k) -> B.ByteString -> 
B.ByteString
+cMacWithSubK' k (IV k1, IV k2) b = go (chunkFor' k t) $ B.replicate bSize1 0
+  where
+       bSize1 = fromIntegral $ blockSizeBytes `for` k
+       bSize2 = fromIntegral $ blockSizeBytes `for` k
+       (t,e) = B.splitAt (((B.length b-1)`div` bSize2)*bSize2) b
+       pe =  fst $ B.unfoldrN (bSize1) cMacPad (B.unpack e,True,bSize1)
+       fe | bSize2 == B.length e = zwp' k1 pe
+          | otherwise =  zwp' k2 pe
+       go [] c = encryptBlock k (zwp' c fe)
+       go (x:xs) c = go xs $ encryptBlock k $ zwp' c x
+
+-- |Obtain the cmac for strict bytestrings
+cMac' :: BlockCipher k => k -> B.ByteString -> B.ByteString
+cMac' k = cMacWithSubK' k (cMacSubk k)
+
+-- |Generate the xor stream for the last step of the CMAC* algorithm
+xorend  :: Int -> (Int,[Word8]) -> Maybe (Word8,(Int,[Word8]))
+xorend bsize (0, []) = Nothing
+xorend bsize (n, x:xs) | n <= bsize = Just (x,((n-1),xs))
+                      | otherwise = Just (0,((n-1),(x:xs)))
+
+-- |Obtain the CMAC* on lazy bytestrings
+cMacStar :: BlockCipher k => k -> [L.ByteString] -> L.ByteString
+cMacStar k l = go (lcmac (L.replicate bSize 0)) l
+  where
+       bSize = fromIntegral $ blockSizeBytes `for` k
+       bSizeb = fromIntegral $ blockSize `for` k
+       lcmac = cMacWithSubK k (cMacSubk k)
+       go s [] = s
+       go s [x] | (L.length x) >= bSize = lcmac $ zwp x $ L.unfoldr (xorend $ 
fromIntegral bSize) (fromIntegral $ L.length x,L.unpack s)
+                | otherwise = lcmac $ zwp (dblL s) (L.unfoldr cMacPad 
(L.unpack x,True,fromIntegral bSize))
+       go s (x:xs) = go (zwp (dblL s) (lcmac x)) xs
+
+-- |Obtain the CMAC* on strict bytestrings
+cMacStar' :: BlockCipher k => k -> [B.ByteString] -> B.ByteString
+cMacStar' k s = go (lcmac (B.replicate bSize 0)) s
+  where
+       bSize = fromIntegral $ blockSizeBytes `for` k
+       bSizeb = fromIntegral $ blockSize `for` k
+       lcmac = cMacWithSubK' k (cMacSubk k)
+       go s [] = s
+       go s [x] | (B.length x) >= bSize = lcmac $ zwp' x $ fst $ B.unfoldrN 
(B.length x) (xorend bSize) (fromIntegral $ B.length x,B.unpack s)
+                | otherwise = lcmac $ zwp' (dblB s) (fst $ B.unfoldrN bSize 
cMacPad (B.unpack x,True,bSize))
+       go s (x:xs) = go (zwp' (dblB s) (lcmac x)) xs
+
+-- |Create the mask for SIV based ciphers
+sivMask :: B.ByteString -> B.ByteString
+sivMask b = snd $ B.mapAccumR (go) 0 b
+  where go :: Int -> Word8 -> (Int,Word8)
+       go 24 w = (32,clearBit w 7)
+       go 56 w = (64,clearBit w 7)
+       go n w = (n+8,w)
+
+-- |SIV (Synthetic IV) mode for lazy bytestrings
+-- |First argument is the optional list of bytestrings to be authenticated
+-- | but not encrypted
+-- |As required by the specification this algorithm may return nothing when
+-- | certain constraints aren't met.
+siv :: BlockCipher k => k -> k -> [L.ByteString] -> L.ByteString -> Maybe 
L.ByteString
+siv k1 k2 xs m | length xs > bSizeb - 1 = Nothing
+              | otherwise = Just $ L.append iv $ fst $ ctr incIV k2 (IV $ 
sivMask $ B.concat $ L.toChunks iv) m
+  where
+       bSize = fromIntegral $ blockSizeBytes `for` k1
+       bSizeb = fromIntegral $ blockSize `for` k1
+       iv = cMacStar k1 $ xs ++ [m]
+
+
+-- |SIV (Synthetic IV) for lazy bytestrings
+-- |First argument is the optional list of bytestrings to be authenticated
+-- | but not encrypted
+-- |As required by the specification this algorithm may return nothing when
+-- | authentication fails
+unSiv :: BlockCipher k => k -> k -> [L.ByteString] -> L.ByteString -> Maybe 
L.ByteString
+unSiv k1 k2 xs c | length xs > bSizeb - 1 = Nothing
+                | L.length c < fromIntegral bSize = Nothing
+                | iv /= (cMacStar k1 $ xs ++ [dm]) = Nothing
+                | otherwise = Just dm
+  where
+       bSize = fromIntegral $ blockSizeBytes `for` k1
+       bSizeb = fromIntegral $ blockSize `for` k1
+       (iv,m) = L.splitAt (fromIntegral bSize) c
+       dm = fst $ unCtr incIV k2 (IV $ sivMask $ B.concat $ L.toChunks iv) m
+
+-- |SIV (Synthetic IV) mode for strict bytestrings
+-- |First argument is the optional list of bytestrings to be authenticated
+-- | but not encrypted
+-- |As required by the specification this algorithm may return nothing when
+-- | certain constraints aren't met.
+siv' :: BlockCipher k => k -> k -> [B.ByteString] -> B.ByteString -> Maybe 
B.ByteString
+siv' k1 k2 xs m | length xs > bSizeb - 1 = Nothing
+               | otherwise = Just $ B.append iv $ fst $ ctr' incIV k2 (IV $ 
sivMask iv) m
+  where
+       bSize = fromIntegral $ blockSizeBytes `for` k1
+       bSizeb = fromIntegral $ blockSize `for` k1
+       iv = cMacStar' k1 $ xs ++ [m]
+
+
+-- |SIV (Synthetic IV) for strict bytestrings
+-- |First argument is the optional list of bytestrings to be authenticated
+-- | but not encrypted
+-- |As required by the specification this algorithm may return nothing when
+-- | authentication fails
+unSiv' :: BlockCipher k => k -> k -> [B.ByteString] -> B.ByteString -> Maybe 
B.ByteString
+unSiv' k1 k2 xs c | length xs > bSizeb - 1 = Nothing
+                 | B.length c < bSize = Nothing
+                 | iv /= (cMacStar' k1 $ xs ++ [dm]) = Nothing
+                 | otherwise = Just dm
+  where
+       bSize = fromIntegral $ blockSizeBytes `for` k1
+       bSizeb = fromIntegral $ blockSize `for` k1
+       (iv,m) = B.splitAt bSize c
+       dm = fst $ unCtr' incIV k2 (IV $ sivMask iv) m
+
+-- |Increase an `IV` by one
+-- |This is way faster than decoding, increasing, encoding 
+incIV :: BlockCipher k => IV k -> IV k
+incIV (IV b) = IV $ snd $ B.mapAccumR (incw) True b
+  where incw :: Bool -> Word8 -> (Bool, Word8)
+       incw True w = (w == maxBound, w + 1)
+       incw False w = (False, w)
+
+-- |Accumulator based double operation
+dblw :: Bool -> (Int,[Int],Bool) -> Word8 -> ((Int,[Int],Bool), Word8)
+dblw hb (i,xs,b) w = dblw' hb
+  where slw True w = (setBit (shift w 1) 0)
+       slw False w = (clearBit (shift w 1) 0)
+       cpolyw i [] w = ((i+8,[]),w)
+       cpolyw i (x:xs) w
+         | x < i +8 = (\(a,b) -> (a,complementBit b (x-i))) $ cpolyw i xs w
+         |otherwise = ((i+8,(x:xs)),w)
+       b' = testBit w 7
+       w' = slw b w
+       ((i',xs'),w'') = cpolyw i xs w'
+       dblw' False = i'`seq`xs'`seq`w''`seq`((i,xs,b'),w')
+       dblw' True  = ((i',xs',b'),w'')
+
+
+-- |Perform doubling as defined by the CMAC and SIV papers
+dblIV :: BlockCipher k => IV k -> IV k
+dblIV (IV b) = IV $ dblB b
+
+-- |Perform doubling as defined by the CMAC and SIV papers
+dblB :: B.ByteString -> B.ByteString
+dblB b | B.null b = b
+       | otherwise = snd $ B.mapAccumR (dblw (testBit (B.head b) 7)) 
(0,cpoly2revlist (B.length b * 8),False) b
+
+-- |Perform doubling as defined by the CMAC and SIV papers
+dblL :: L.ByteString -> L.ByteString
+dblL b | L.null b = b
+       | otherwise = snd $ L.mapAccumR (dblw (testBit (L.head b) 7)) 
(0,cpoly2revlist (L.length b * 8),False) b
+
+-- |Cast a bigEndian ByteString into an Integer
+decodeB :: B.ByteString -> Integer
+decodeB = B.foldl' (\acc w -> (shift acc 8) + toInteger(w)) 0
+
+-- |Cast an Integer into a bigEndian ByteString of size k
+-- |It will drop the MSBs in case the number is bigger than k and add 00s if it
+-- |is smaller
+encodeB :: (Ord a,Num a) => a -> Integer -> B.ByteString
+encodeB k n = B.pack $ if lr > k then takel (lr - k) r else pad (k - lr) r
+  where go 0 xs = xs 
+       go n xs = go (shift n (-8)) (fromInteger (n .&. 255) : xs)
+       pad 0 xs = xs
+       pad n xs = 0 : pad (n-1) xs
+       takel 0 xs = xs
+       takel n (_:xs) = takel (n-1) xs
+       r = go n []
+       lr = genericLength r
+
+-- |Cast a bigEndian ByteString into an Integer
+decodeL :: L.ByteString -> Integer
+decodeL = L.foldl' (\acc w -> (shift acc 8) + toInteger(w)) 0
+
+-- |Cast an Integer into a bigEndian ByteString of size k
+-- |It will drop the MSBs in case the number is bigger than k and add 00s if it
+-- |is smaller
+encodeL :: (Ord a,Num a) => a -> Integer -> L.ByteString
+encodeL k n = L.pack $ if lr > k then takel (lr - k) r else pad (k - lr) r
+  where go 0 xs = xs 
+       go n xs = go (shift n (-8)) (fromInteger (n .&. 255) : xs)
+       pad 0 xs = xs
+       pad n xs = 0 : pad (n-1) xs
+       takel 0 xs = xs
+       takel n (_:xs) = takel (n-1) xs
+       r = go n []
+       lr = genericLength r
+
 unfoldK :: (b -> Maybe (a,b)) -> b -> ([a],b)
 unfoldK f i = 
        case (f i) of
@@ -269,6 +521,13 @@
                        let (as, iF) = unfoldK f i'
                        in (a:as, iF)
 
+
+-- |Obtain an `IV` made only of zeroes
+zeroIV :: (BlockCipher k) => IV k
+zeroIV = iv
+  where bytes = ivBlockSizeBytes iv
+       iv  = IV $ B.replicate  bytes 0
+
 -- |Obtain an `IV` using the provided CryptoRandomGenerator.
 getIV :: (BlockCipher k, CryptoRandomGen g) => g -> Either GenError (IV k, g)
 getIV g =
Sólo en crypto-api-0.5.2.new/Crypto: Poly.hs

import Crypto.Cipher.AES
import Codec.Binary.Base16
import Data.Maybe
import Data.Char

let (k) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"2b7e151628aed2a6abf7158809cf4f3c"
let (iv) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
let (Just ptext) = Codec.Binary.Base16.decode $ map toUpper $ 
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
let (Just ctext) = Codec.Binary.Base16.decode $ map toUpper $ 
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
let lastIV = IV $ B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
$ "f0f1f2f3f4f5f6f7f8f9fafbfcfdff03"
let (Just c) = buildKey k::Maybe AES128
(ctr incIV c (IV iv) $ L.pack  ptext) == (L.pack ctext,lastIV)
(ctr' incIV c (IV iv) $ B.pack  ptext) == (B.pack ctext,lastIV)
let (Just ptext) = Codec.Binary.Base16.decode $ map toUpper $ 
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c37"
let (Just ctext) = Codec.Binary.Base16.decode $ map toUpper $ 
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009c"
(ctr incIV c (IV iv) $ L.pack  ptext) == (L.pack ctext,lastIV)
(ctr' incIV  c (IV iv) $ B.pack  ptext) == (B.pack ctext,lastIV)

let (k1) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"fbeed618357133667c85e08f7236a8de"
let (k2) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"f7ddac306ae266ccf90bc11ee46d513b"

( cMacSubk c) == (IV k1, IV k2)

let (ehash) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $  
"bb1d6929e95937287fa37d129b756746"
let m1 = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"6bc1bee22e409f96e93d7e117393172a"
let m1hash = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"070a16b46b4d4144f79bdd9dd04a287c"
let m2 = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411"
let m2hash = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"dfa66747de9ae63030ca32611497c827"
let m3 = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
let m3hash = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"51f0bebf7e3b9d92fc49741779363cfe"


(cMac' c B.empty) == ehash
(cMac' c m1) == m1hash
(cMac' c m2) == m2hash
(cMac' c m3) == m3hash



let (ka) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0"
let (kb) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
let (Just c1) = buildKey ka::Maybe AES128
let (Just c2) = buildKey kb::Maybe AES128
let ad = map (\x->B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
x) ["101112131415161718191a1b1c1d1e1f2021222324252627"]
let pt = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"112233445566778899aabbccddee"
let res = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"85632d07c6e8f37f950acd320a2ecc9340c02b9690c4dc04daef7f6afe5c"
siv' c1 c2 ad pt == Just res
unSiv' c1 c2 ad (fromJust $ siv' c1 c2 ad pt) == Just pt

let (ka) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"7f7e7d7c7b7a79787776757473727170"
let (kb) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"404142434445464748494a4b4c4d4e4f"
let (Just c1) = buildKey ka::Maybe AES128
let (Just c2) = buildKey kb::Maybe AES128
let ad = map (\x->B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
x) 
["00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa99887766554433221100","102030405060708090a0","09f911029d74e35bd84156c5635688c0"]
let pt = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"7468697320697320736f6d6520706c61696e7465787420746f20656e6372797074207573696e67205349562d414553"
let res = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"7bdb6e3b432667eb06f4d14bff2fbd0fcb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829ea64ad544a272e9c485b62a3fd5c0d"
siv' c1 c2 ad pt == Just res
unSiv' c1 c2 ad (fromJust $ siv' c1 c2 ad pt) == Just pt

let (ka) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0"
let (kb) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
let (Just c1) = buildKey ka::Maybe AES128
let (Just c2) = buildKey kb::Maybe AES128
let ad = map (\x->L.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
x) ["101112131415161718191a1b1c1d1e1f2021222324252627"]
let pt = L.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"112233445566778899aabbccddee"
let res = L.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"85632d07c6e8f37f950acd320a2ecc9340c02b9690c4dc04daef7f6afe5c"
siv c1 c2 ad pt == Just res
unSiv c1 c2 ad (fromJust $ siv c1 c2 ad pt) == Just pt

let (ka) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"7f7e7d7c7b7a79787776757473727170"
let (kb) = B.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper $ 
"404142434445464748494a4b4c4d4e4f"
let (Just c1) = buildKey ka::Maybe AES128
let (Just c2) = buildKey kb::Maybe AES128
let ad = map (\x->L.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
x) 
["00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa99887766554433221100","102030405060708090a0","09f911029d74e35bd84156c5635688c0"]
let pt = L.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"7468697320697320736f6d6520706c61696e7465787420746f20656e6372797074207573696e67205349562d414553"
let res = L.pack $ fromJust $ Codec.Binary.Base16.decode $ map toUpper 
"7bdb6e3b432667eb06f4d14bff2fbd0fcb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829ea64ad544a272e9c485b62a3fd5c0d"
siv c1 c2 ad pt == Just res
unSiv c1 c2 ad (fromJust $ siv c1 c2 ad pt) == Just pt

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to