packages feed

Z-Botan-0.4.0.0: test/Z/Crypto/CipherSpec.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}

module Z.Crypto.CipherSpec where
import           Control.Monad
import           Test.Hspec
import           Test.HUnit
import           Z.IO
import qualified Z.IO.FileSystem as FS
import           Z.Data.ASCII
import           Z.Data.Vector.Hex
import qualified Z.Data.Parser      as P
import qualified Z.Data.Vector      as V
import qualified Z.Data.Text        as T
import           Z.Crypto.Cipher
import           Z.Crypto.Hash
import           Z.Crypto.SafeMem
import           Utils

spec :: Spec
spec = do
    describe "Crypto.Cipher.BlockCipher" $ do
        forM_
            [ ("aes.vec", "AES-128", AES128)
            , ("aes.vec", "AES-192", AES192)
            , ("aes.vec", "AES-256", AES256)
            , ("aria.vec", "ARIA-128", ARIA128)
            , ("aria.vec", "ARIA-192", ARIA192)
            , ("aria.vec", "ARIA-256", ARIA256)
            , ("blowfish.vec", "Blowfish", Blowfish)
            , ("camellia.vec", "Camellia-128", Camellia128)
            , ("camellia.vec", "Camellia-192", Camellia192)
            , ("camellia.vec", "Camellia-256", Camellia256)
            , ("cascade.vec", "Cascade(Serpent,Twofish)", Cascade Serpent Twofish)
            , ("cascade.vec", "Cascade(Serpent,AES-256)", Cascade Serpent AES256)
            , ("cascade.vec", "Cascade(Serpent,CAST-128)", Cascade Serpent CAST128)
            , ("cast128.vec", "CAST-128", CAST128)
            , ("cast256.vec", "CAST-256", CAST256)
            , ("des.vec", "DES", DES)
            , ("idea.vec", "IDEA", IDEA)
            , ("kasumi.vec", "KASUMI", KASUMI)
            , ("lion.vec", "Lion(SHA-160,RC4,64)", Lion SHA160 RC4 64)
            , ("misty.vec", "MISTY1", MISTY1)
            , ("noekeon.vec", "Noekeon", Noekeon)
            , ("seed.vec", "SEED", SEED)
            , ("serpent.vec", "Serpent", Serpent)
            , ("shacal2.vec", "SHACAL2", SHACAL2)
            -- dont support iterations
            -- , ("sm4.vec", "SM4", SM4)
            -- dont support tweak
            -- , ("threefish.vec", "Threefish-512", Threefish512)
            , ("twofish.vec", "Twofish", Twofish)
            , ("xtea.vec", "XTEA", XTEA)
            ] $ \ (file, algoName, cipherType) ->
                it (T.unpack $ T.validate algoName) $ do
                    tvMap <- parseBlockCipherTestVector =<< "./third_party/botan/src/tests/data/block/" `FS.join` file
                    tvs <- unwrap' "ENOTFOUND" "no algo founded" $ lookup algoName tvMap
                    forM_ tvs $ \ (key0, i, o) -> do

                        key <- unsafeSecretFromBytes key0

                        c <- newBlockCipher cipherType
                        setBlockCipherKey c key
                        o' <- encryptBlocks c i (V.length i `quot` blockCipherSize c)
                        o' @=? o
                        i' <- decryptBlocks c o (V.length o `quot` blockCipherSize c)
                        i' @=? i

    describe "Crypto.Cipher.CipherMode" $ do
        forM_
            [ ("cbc.vec", "DES/CBC/NoPadding", CBC_NoPadding DES)
            , ("cbc.vec", "CAST-128/CBC/PKCS7", CBC_PKCS7 CAST128)
            , ("cbc.vec", "DES/CBC/PKCS7", CBC_PKCS7 DES)
            , ("cbc.vec", "TripleDES/CBC/NoPadding", CBC_NoPadding TripleDES)
            , ("cbc.vec", "TripleDES/CBC/PKCS7", CBC_PKCS7 TripleDES)
            , ("cbc.vec", "Blowfish/CBC/NoPadding", CBC_NoPadding Blowfish)
            , ("cbc.vec", "Noekeon/CBC/PKCS7", CBC_PKCS7 Noekeon)
            , ("cbc.vec", "DES/CBC/OneAndZeros", CBC_OneAndZeros DES)
            , ("cbc.vec", "DES/CBC/CTS", CBC_CTS DES)
            , ("cbc.vec", "AES-128/CBC/PKCS7", CBC_PKCS7 AES128)
            , ("cbc.vec", "AES-128/CBC/NoPadding", CBC_NoPadding AES128)
            , ("cbc.vec", "AES-192/CBC/NoPadding", CBC_NoPadding AES192)
            , ("cbc.vec", "AES-256/CBC/NoPadding", CBC_NoPadding AES256)
            , ("cbc.vec", "AES-128/CBC/CTS", CBC_CTS AES128)
            , ("cbc.vec", "ARIA-256/CBC/NoPadding", CBC_NoPadding ARIA256)
            , ("cfb.vec", "DES/CFB", CFB DES)
            , ("cfb.vec", "DES/CFB(32)", CFB' DES 32)
            , ("cfb.vec", "DES/CFB(16)", CFB' DES 16)
            , ("cfb.vec", "DES/CFB(8)", CFB' DES 8)
            , ("cfb.vec", "TripleDES/CFB", CFB TripleDES)
            , ("cfb.vec", "TripleDES/CFB(8)", CFB' TripleDES 8)
            , ("cfb.vec", "AES-128/CFB(8)", CFB' AES128 8)
            , ("cfb.vec", "AES-192/CFB(8)", CFB' AES192 8)
            , ("cfb.vec", "AES-256/CFB(8)", CFB' AES256 8)
            , ("cfb.vec", "AES-128/CFB", CFB AES128)
            , ("cfb.vec", "AES-192/CFB", CFB AES192)
            , ("cfb.vec", "AES-256/CFB", CFB AES256)
            , ("xts.vec", "AES-128/XTS", XTS AES128)
            , ("xts.vec", "AES-256/XTS", XTS AES256)
            , ("xts.vec", "Twofish/XTS", XTS Twofish)
            , ("xts.vec", "Serpent/XTS", XTS Serpent)
            , ("xts.vec", "TripleDES/XTS", XTS TripleDES)
            , ("xts.vec", "SHACAL2/XTS", XTS SHACAL2)
            , ("xts.vec", "Threefish-512/XTS", XTS Threefish512)
            ] $ \ (file, algoName, cipherType) ->
                it (T.unpack $ T.validate algoName) $ do
                    tvMap <- parseCipherModeTestVector =<< "./third_party/botan/src/tests/data/modes/" `FS.join` file
                    tvs <- unwrap' "ENOTFOUND" "no algo founded" $ lookup algoName tvMap
                    forM_ tvs $ \ (key0, nonce, i, o) -> do

                        key <- unsafeSecretFromBytes key0

                        c <- newCipher cipherType CipherEncrypt
                        setCipherKey c key

                        d <- newCipher cipherType CipherDecrypt
                        setCipherKey d key

                        o' <- runCipher c nonce i ""
                        o' @=? o

                        i' <- runCipher d nonce o ""
                        i' @=? i

    describe "Crypto.Cipher.AEAD" $ do
        forM_
            [ ("ccm.vec", "AES-128/CCM(8,2)", CCM' AES128 8 2)
            , ("chacha20poly1305.vec", "ChaCha20Poly1305", ChaCha20Poly1305)
            ] $ \ (file, algoName, cipherType) ->
                it (T.unpack $ T.validate algoName) $ do
                    tvMap <- parseCipherAEADTestVector =<< "./third_party/botan/src/tests/data/aead/" `FS.join` file
                    tvs <- unwrap' "ENOTFOUND" "no algo founded" $ lookup algoName tvMap
                    forM_ tvs $ \ (key0, nonce, i, ad, o) -> do

                        key <- unsafeSecretFromBytes key0

                        c <- newCipher cipherType CipherEncrypt
                        setCipherKey c key

                        d <- newCipher cipherType CipherDecrypt
                        setCipherKey d key

                        o' <- runCipher c nonce i ad
                        o' @=? o

                        i' <- runCipher d nonce o ad
                        i' @=? i


    describe "Crypto.Cipher.StreamCipher(I)" $ do
        forM_
            [ ("ctr.vec", "CTR-BE(DES)", CTR_BE DES)
            , ("ctr.vec", "CTR-BE(AES-128)", CTR_BE AES128)
            ] $ \ (file, algoName, cipherType) ->
                it (T.unpack $ T.validate algoName) $ do
                    tvMap <- parseCipherModeTestVector =<< "./third_party/botan/src/tests/data/modes/" `FS.join` file
                    tvs <- unwrap' "ENOTFOUND" "no algo founded" $ lookup algoName tvMap
                    forM_ tvs $ \ (key0, nonce, i, o) -> do

                        key <- unsafeSecretFromBytes key0

                        c <- newStreamCipher cipherType
                        setStreamCipherKey c key
                        setStreamCipherIV c nonce

                        d <- newStreamCipher cipherType
                        setStreamCipherKey d key
                        setStreamCipherIV d nonce

                        o' <- runStreamCipher c i
                        o' @?= o
                        i' <- runStreamCipher d o
                        i' @?= i