Twofish 0.1 → 0.2
raw patch · 4 files changed
+46/−46 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- Codec/Encryption/Twofish.hs +31/−31
- Data/Cipher.hs +2/−4
- Test.hs +4/−4
- Twofish.cabal +9/−7
Codec/Encryption/Twofish.hs view
@@ -48,7 +48,7 @@ -- This particular implementation works around a bug in the -- Data.LargeWord module involving right shifts. keyByte :: a -> Int -> Word8- keyByte w n = let w' = (fromIntegral w) :: Integer+ keyByte w n = let w' = fromIntegral w :: Integer in fromIntegral $ (w' `shiftR` (8 * n)) .&. 0xff -- Standard key sizes@@ -78,7 +78,7 @@ -- in the Data.LargeWord module involving right shifts. mkBlock :: Word128 -> Block mkBlock b = - let b' = (fromIntegral b) :: Integer+ let b' = fromIntegral b :: Integer w0 = b' .&. 0xffffffff w1 = (b' `shiftR` 32) .&. 0xffffffff w2 = (b' `shiftR` 64) .&. 0xffffffff@@ -134,8 +134,8 @@ roundT (r0, r1, r2, r3) r = let t0 = g r0 t1 = g (r1 `rotateL` 8)- f0 = t0 + t1 + (k (2 * r + 8))- f1 = t0 + 2 * t1 + (k (2 * r + 9))+ f0 = t0 + t1 + k (2 * r + 8)+ f1 = t0 + 2 * t1 + k (2 * r + 9) r0' = (r2 `xor` f0) `rotateR` 1 r1' = (r3 `rotateL` 1) `xor` f1 r2' = r0@@ -149,8 +149,8 @@ roundT r (r0, r1, r2, r3) = let t0 = g r0 t1 = g (r1 `rotateL` 8)- f0 = t0 + t1 + (k (2 * r + 8))- f1 = t0 + 2 * t1 + (k (2 * r + 9))+ f0 = t0 + t1 + k (2 * r + 8)+ f1 = t0 + 2 * t1 + k (2 * r + 9) r0' = (r2 `rotateL` 1) `xor` f0 r1' = (r3 `xor` f1) `rotateR` 1 r2' = r0@@ -169,7 +169,7 @@ -- Calculates the k value of a key (a function of the key length) fK :: (Key a) => a -> Int-fK key = (bitSize key) `div` 64+fK key = bitSize key `div` 64 -- Generates a G function from an H function and an S vector -- The G function forms the 'heart' of Twofish@@ -190,29 +190,29 @@ reverse = mkVector . P.reverse . elems mkVector :: [Word32] -> WordVector-mkVector w = listArray (0, (P.length w) - 1) w+mkVector w = listArray (0, P.length w - 1) w -- Generates the expanded key indexor from a key, the number -- of rounds, and an H function. -- The number of rounds determines the length of the expanded key mkK :: (Key a) => a -> Int -> HFunc -> KIndexor mkK key n fH =- let me = mkVector $ [m i | i <- [0..(2 * k - 2)], even i]- mo = mkVector $ [m i | i <- [1..(2 * k - 1)], odd i]- ks = mkVector $ [getK me mo i | i <- [0..(8 + (n * 2) - 1)]]+ let me = mkVector [m i | i <- [0..(2 * k - 2)], even i]+ mo = mkVector [m i | i <- [1..(2 * k - 1)], odd i]+ ks = mkVector [getK me mo i | i <- [0..(8 + (n * 2) - 1)]] in (ks !) where getK :: WordVector -> WordVector -> Int -> Word32 getK me mo i- | even i = (ai me $ ie i) + (bi mo $ ie i)- | otherwise = ((ai me $ io i) + 2 * (bi mo $ io i)) `rotateL` 9+ | even i = ai me (ie i) + bi mo (ie i)+ | otherwise = (ai me (io i) + 2 * bi mo (io i)) `rotateL` 9 ie i = i `div` 2 io i = (i - 1) `div` 2 ai :: WordVector -> Int -> Word32- ai me i = fH (2 * (fromIntegral i) * rho) me+ ai me i = fH (2 * fromIntegral i * rho) me bi :: WordVector -> Int -> Word32- bi mo i = (fH ((2 * (fromIntegral i) + 1) * rho) mo) `rotateL` 8+ bi mo i = fH ((2 * fromIntegral i + 1) * rho) mo `rotateL` 8 m i = selectWord (\j -> 4 * i + j) key k = fK key@@ -229,27 +229,27 @@ -- Most of the work in the Twofish cipher happens here. fHGenerator :: (Word8 -> Word8) -> (Word8 -> Word8) -> ByteVector -> ByteVector -> Int -> Word32 -> WordVector -> Word32 fHGenerator q0 q1 mxX mxY k x l = mds mxX mxY (y0, y1, y2, y3)- where y0 = q1 $ q0 (q0 (yij 2 0) `xor` (lij 1 0)) `xor` (lij 0 0)- y1 = q0 $ q0 (q1 (yij 2 1) `xor` (lij 1 1)) `xor` (lij 0 1)- y2 = q1 $ q1 (q0 (yij 2 2) `xor` (lij 1 2)) `xor` (lij 0 2)- y3 = q0 $ q1 (q1 (yij 2 3) `xor` (lij 1 3)) `xor` (lij 0 3)+ where y0 = q1 $ q0 (q0 (yij 2 0) `xor` lij 1 0) `xor` lij 0 0+ y1 = q0 $ q0 (q1 (yij 2 1) `xor` lij 1 1) `xor` lij 0 1+ y2 = q1 $ q1 (q0 (yij 2 2) `xor` lij 1 2) `xor` lij 0 2+ y3 = q0 $ q1 (q1 (yij 2 3) `xor` lij 1 3) `xor` lij 0 3 yij :: Int -> Int -> Word8 yij 3 j- | k == 4 = let qx = if (j == 0 || j == 3) then q1 else q0- in qx (yij 4 j) `xor` (lij 3 j)+ | k == 4 = let qx = if j `elem` [0, 3] then q1 else q0+ in qx (yij 4 j) `xor` lij 3 j | otherwise = xj j yij 2 j - | k >= 3 = let qx = if (j == 0 || j == 1) then q1 else q0- in qx (yij 3 j) `xor` (lij 2 j)+ | k >= 3 = let qx = if j `elem` [0, 1] then q1 else q0+ in qx (yij 3 j) `xor` lij 2 j | otherwise = xj j yij _ j = xj j xj :: Int -> Word8- xj j = byteN x j+ xj = byteN x lij :: Int -> Int -> Word8- lij i j = byteN (l ! i) j+ lij i = byteN (l ! i) -- Multiply a vector of bytes by the MDS matrix mds :: ByteVector -> ByteVector -> (Word8, Word8, Word8, Word8) -> Word32@@ -258,8 +258,8 @@ r1 = (mxX ! x0) `xor` (mxY ! x1) `xor` (mxY ! x2) `xor` x3 r2 = (mxY ! x0) `xor` (mxX ! x1) `xor` x2 `xor` (mxY ! x3) r3 = (mxY ! x0) `xor` x1 `xor` (mxY ! x2) `xor` (mxX ! x3)- in (fromIntegral r0) .|. ((fromIntegral r1) `shiftL` 8) .|.- ((fromIntegral r2) `shiftL` 16) .|. ((fromIntegral r3) `shiftL` 24)+ in fromIntegral r0 .|. (fromIntegral r1 `shiftL` 8) .|.+ (fromIntegral r2 `shiftL` 16) .|. (fromIntegral r3 `shiftL` 24) -- A byte mapping used as part of the MDS matrix multiply mkMdsX :: ByteVector@@ -282,7 +282,7 @@ -- Multiply a vector of bytes by the RS matrix rs :: Word32 -> Word32 -> Word32 rs k0 k1 =- rsRem4 ((rsRem4 k1) `xor` k0)+ rsRem4 (rsRem4 k1 `xor` k0) where rsRem4 = rsRem . rsRem . rsRem .rsRem rsRem :: Word32 -> Word32@@ -317,7 +317,7 @@ -- Extracts the n'th byte from a word byteN :: (Integral a, Bits a) => a -> Int -> Word8-byteN w n = let s = fromIntegral $ (n `shiftL` 3)+byteN w n = let s = fromIntegral (n `shiftL` 3) in fromIntegral $ (w .&. (0xff `shiftL` s)) `shiftR` s type ByteVector = UArray Word8 Word8@@ -369,11 +369,11 @@ where a0 = x `div` 16 b0 = x `mod` 16 a1 = a0 `xor` b0- b1 = a0 `xor` (ror4 b0 1) `xor` (8 * a0) `mod` 16+ b1 = a0 `xor` ror4 b0 1 `xor` (8 * a0) `mod` 16 a2 = t0 ! a1 b2 = t1 ! b1 a3 = a2 `xor` b2- b3 = a2 `xor` (ror4 b2 1) `xor` (8 * a2) `mod` 16+ b3 = a2 `xor` ror4 b2 1 `xor` (8 * a2) `mod` 16 a4 = t2 ! a3 b4 = t3 ! b3
Data/Cipher.hs view
@@ -5,14 +5,12 @@ module Data.Cipher ( -- * Classes- Cipher+ Cipher(encrypt, decrypt) ,MonadCbc -- * Types ,Cbc ,CbcT -- * Functions- ,encrypt- ,decrypt ,evalCbc ,evalCbcT ,cbcEncrypt@@ -66,7 +64,7 @@ -- |This is the fundamental cipher-block-chaining decryption protocol cbcDecrypt :: (MonadCbc c w s m) => w -> m w cbcDecrypt w = monadCbc $ do (c, iv) <- get- let w' = (decrypt c w) `xor` iv+ let w' = decrypt c w `xor` iv put (c, w) return w'
Test.hs view
@@ -14,15 +14,15 @@ 48 tfTest192 :: Test-tfTest192 = tfTest (\k b -> (fromIntegral b) .|. (k `shiftL` 128))+tfTest192 = tfTest (\k b -> fromIntegral b .|. (k `shiftL` 128)) (0 :: Word192) (0x4109640a86bd90a3f4f9ee2b214954e7 :: Word128) 50 tfTest256 :: Test-tfTest256 = tfTest (\k b -> (fromIntegral b) .|. (k `shiftL` 128))+tfTest256 = tfTest (\k b -> fromIntegral b .|. (k `shiftL` 128)) (0 :: Word256)- (0x05a2973bc3f4ddf57561f61cff26fe37)+ 0x05a2973bc3f4ddf57561f61cff26fe37 50 -- |Test Twofish using the given test vectors in the Twofish@@ -30,7 +30,7 @@ -- initial block consisting of all zeroes, and a known -- final cipher text after 48 rounds tfTest :: (Key a) => (a -> Word128 -> a) -> a -> Word128 -> Int -> Test-tfTest f k o r = TestCase $ assertEqual ("Key Size: " ++ (show (bitSize k)))+tfTest f k o r = TestCase $ assertEqual ("Key Size: " ++ show (bitSize k)) o $ run k 0 1 where run key block n
Twofish.cabal view
@@ -1,26 +1,26 @@ Name: Twofish-Version: 0.1+Version: 0.2 Category: Cryptography, Codec Stability: experimental Synopsis: An implementation of the Twofish Symmetric-key cipher. Description: Implements the Twofish symmetric block cipher, designed by: Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson.-+ . As well, this module includes some generic definitions for- ciphers and cipher-block-chaining mode, in the Data.Cipher+ ciphers and cipher-block-chaining mode in the Data.Cipher module. In the future, these should probably either be moved to their own package, or all of this should be merged into the Crypto package.-+ . Acknowledgments:-+ . Dominic Steinitz and Creighton Hogg for their work on the Crypto package, upon which this package depends (particularily for the Data.LargeWord module).-+ . Stephen Tetley for his advice and code examples provided on- the Haskell-Beginners mailing list, in response to a question+ the Haskell-Beginners mailing list in response to a question I had, which helped me to create a transformer version of the Cbc monad. Author: Ron Leisti@@ -32,6 +32,8 @@ License-File: LICENSE Cabal-Version: >= 1.2 Build-Type: Simple++Tested-With: GHC == 6.12.1 Library Build-Depends: array >= 0.3