-- Module : Main -- Copyright : (c) Ron Leisti 2010-2012 -- License : BSD3 -- Maintainer : ron.leisti@gmail.com -- -- |Various tests for the Twofish cipher, taken from the -- Twofish paper. -- -- module Main(main) where import Data.Array.Unboxed import Data.Bits import Data.LargeWord import Codec.Encryption.Twofish import System.Exit (exitSuccess, exitFailure) import Test.HUnit import Text.Printf -- |A test, including intermediate steps, of 192-bit encryption. test192_single_encrypt = let key = fromIntegral 0x77665544332211001032547698BADCFEEFCDAB8967452301 :: Word192 s = mkS key h = mkfH key k = mkK key 16 h g = mkG h s p0 = 0 `xor` k 0 p1 = 0 `xor` k 1 p2 = 0 `xor` k 2 p3 = 0 `xor` k 3 testRound :: (Integral a) => Int -> a -> a -> Assertion testRound n block0 block1 = let (r0, r1, r2, r3) = encryptRounds g k n (p0, p1, p2, p3) in do assertEqualHex (printf "Round %d word 0" n :: String) block0 r0 assertEqualHex (printf "Round %d word 1" n :: String) block1 r1 in TestCase $ do assertEqualHex "s 0 must match" 0x45661061 (s ! 0) assertEqualHex "s 1 must match" 0xb255bc4b (s ! 1) assertEqualHex "s 2 must match" 0xb89ff6f2 (s ! 2) assertEqualHex "k 0 must match" 0x38394A24 (k 0) assertEqualHex "k 1 must match" 0xc36d1175 (k 1) assertEqualHex "k 2 must match" 0xe802528f (k 2) assertEqualHex "k 3 must match" 0x219bfeb4 (k 3) assertEqualHex "k 4 must match" 0xb9141ab4 (k 4) assertEqualHex "k 5 must match" 0xbd3e70cd (k 5) assertEqualHex "k 6 must match" 0xaf609383 (k 6) assertEqualHex "k 7 must match" 0xfd36908a (k 7) testRound 1 0x9c263d67 0x5e68be8f testRound 2 0xc8f5099f 0x0c4b8f53 testRound 3 0x69948f5e 0xe67c030f testRound 16 0x17738cd3 0xb5142d18 let (f0, f1, f2, f3) = encryptRounds g k 16 (p0, p1, p2, p3) let c0 = f2 `xor` k 4 c1 = f3 `xor` k 5 c2 = f0 `xor` k 6 c3 = f1 `xor` k 7 assertEqualHex "c0 must match" 0xe5d2d1cf c0 assertEqualHex "c1 must match" 0xdf9cbea9 c1 assertEqualHex "c2 must match" 0xb8131f50 c2 assertEqualHex "c3 must match" 0x4822bd92 c3 assertEqualHex "final result must match" 0x4822bd92b8131f50df9cbea9e5d2d1cf $ encrypt (mkStdCipher key) (fromIntegral 0) -- | Encryption test with multiple iterations using a 128 bit key. test128_iterative_encrypt :: Test test128_iterative_encrypt = let key = fromIntegral 0 :: Word128 block = fromIntegral 0 :: Word128 run key block n | n > 0 = let c = encrypt (mkStdCipher key) block in run block c (n - 1) | otherwise = block testIteration :: Int -> Word128 -> Assertion testIteration iteration expected = assertEqualHex msg expected (run key block iteration) where msg = printf "128 bit encryption iteration %d" iteration :: String in TestCase $ do testIteration 47 0x21f9527982aa147e98c63345a524a7bc -- | Encryption test with multiple iterations using a 192 bit key. test192_iterative_encrypt :: Test test192_iterative_encrypt = let key = fromIntegral 0 :: Word192 block = fromIntegral 0 :: Word128 run key block n | n > 0 = let c = encrypt (mkStdCipher key) block block' = fromIntegral block :: Integer key' = fromIntegral key :: Integer key'' = (key' `shiftL` 128) .|. block' key''' = fromIntegral key'' in run key''' c (n - 1) | otherwise = block testIteration :: Int -> Word128 -> Assertion testIteration iteration expected = assertEqualHex msg expected (run key block iteration) where msg = printf "192 bit encryption iteration %d" iteration :: String in TestCase $ do testIteration 1 0x0191c18f1760f85344bd6589781fa7ef testIteration 2 0x881e1a736dbb46b4365e106b70b2b288 testIteration 3 0xb241a33c07dcb685d59749bad669da39 testIteration 4 0x653a1929dcacdaf945ea9714d8022b18 testIteration 9 0x78fc631263bd71350750c5987bd63f89 testIteration 10 0x678f8e57b50087d5631a84c8c94f4316 testIteration 48 0xb676fb8553be70ef21fa25113073abf0 testIteration 49 0x4109640a86bd90a3f4f9ee2b214954e7 -- | Encryption test with multiple iterations using a 256 bit key. test256_iterative_encrypt :: Test test256_iterative_encrypt = let key = fromIntegral 0 :: Word256 block = fromIntegral 0 :: Word128 run key block n | n > 0 = let c = encrypt (mkStdCipher key) block block' = fromIntegral block :: Integer key' = fromIntegral key :: Integer key'' = (key' `shiftL` 128) .|. block' key''' = fromIntegral key'' in run key''' c (n - 1) | otherwise = block testIteration :: Int -> Word128 -> Assertion testIteration iteration expected = assertEqualHex msg expected (run key block iteration) where msg = printf "256 bit encryption iteration %d" iteration :: String in TestCase $ do testIteration 49 0x05a2973bc3f4ddf57561f61cff26fe37 -- | Asserts that two numeric values are equal, and if they are not, -- reports the numbers using their hexidecimal representations. assertEqualHex :: (Integral a, Integral b) => String -> a -> b -> Assertion assertEqualHex message x y = let x' = printf "%x" (fromIntegral x :: Integer) :: String y' = printf "%x" (fromIntegral y :: Integer) :: String in assertEqual message x' y' main = do result <- runTestTT $ TestList [test128_iterative_encrypt ,test192_single_encrypt ,test192_iterative_encrypt ,test256_iterative_encrypt] if (failures result > 0) then exitFailure else exitSuccess