1-- | 2-- Module : Crypto.Cipher.TripleDES 3-- License : BSD-style 4-- Stability : experimental 5-- Portability : ??? 6 7module Crypto.Cipher.TripleDES 8 ( DES_EEE3 9 , DES_EDE3 10 , DES_EEE2 11 , DES_EDE2 12 ) where 13 14import Data.Word 15import Crypto.Error 16import Crypto.Cipher.Types 17import Crypto.Cipher.DES.Primitive 18import Crypto.Internal.ByteArray (ByteArrayAccess) 19import qualified Crypto.Internal.ByteArray as B 20import Data.Memory.Endian 21 22-- | 3DES with 3 different keys used all in the same direction 23data DES_EEE3 = DES_EEE3 Word64 Word64 Word64 24 deriving (Eq) 25 26-- | 3DES with 3 different keys used in alternative direction 27data DES_EDE3 = DES_EDE3 Word64 Word64 Word64 28 deriving (Eq) 29 30-- | 3DES where the first and third keys are equal, used in the same direction 31data DES_EEE2 = DES_EEE2 Word64 Word64 -- key1 and key3 are equal 32 deriving (Eq) 33 34-- | 3DES where the first and third keys are equal, used in alternative direction 35data DES_EDE2 = DES_EDE2 Word64 Word64 -- key1 and key3 are equal 36 deriving (Eq) 37 38instance Cipher DES_EEE3 where 39 cipherName _ = "3DES_EEE" 40 cipherKeySize _ = KeySizeFixed 24 41 cipherInit k = init3DES DES_EEE3 k 42 43instance Cipher DES_EDE3 where 44 cipherName _ = "3DES_EDE" 45 cipherKeySize _ = KeySizeFixed 24 46 cipherInit k = init3DES DES_EDE3 k 47 48instance Cipher DES_EDE2 where 49 cipherName _ = "2DES_EDE" 50 cipherKeySize _ = KeySizeFixed 16 51 cipherInit k = init2DES DES_EDE2 k 52 53instance Cipher DES_EEE2 where 54 cipherName _ = "2DES_EEE" 55 cipherKeySize _ = KeySizeFixed 16 56 cipherInit k = init2DES DES_EEE2 k 57 58instance BlockCipher DES_EEE3 where 59 blockSize _ = 8 60 ecbEncrypt (DES_EEE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (encrypt k3 . encrypt k2 . encrypt k1) . Block) 61 ecbDecrypt (DES_EEE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (decrypt k1 . decrypt k2 . decrypt k3) . Block) 62 63instance BlockCipher DES_EDE3 where 64 blockSize _ = 8 65 ecbEncrypt (DES_EDE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (encrypt k3 . decrypt k2 . encrypt k1) . Block) 66 ecbDecrypt (DES_EDE3 k1 k2 k3) = B.mapAsWord64 (unBlock . (decrypt k1 . encrypt k2 . decrypt k3) . Block) 67 68instance BlockCipher DES_EEE2 where 69 blockSize _ = 8 70 ecbEncrypt (DES_EEE2 k1 k2) = B.mapAsWord64 (unBlock . (encrypt k1 . encrypt k2 . encrypt k1) . Block) 71 ecbDecrypt (DES_EEE2 k1 k2) = B.mapAsWord64 (unBlock . (decrypt k1 . decrypt k2 . decrypt k1) . Block) 72 73instance BlockCipher DES_EDE2 where 74 blockSize _ = 8 75 ecbEncrypt (DES_EDE2 k1 k2) = B.mapAsWord64 (unBlock . (encrypt k1 . decrypt k2 . encrypt k1) . Block) 76 ecbDecrypt (DES_EDE2 k1 k2) = B.mapAsWord64 (unBlock . (decrypt k1 . encrypt k2 . decrypt k1) . Block) 77 78init3DES :: ByteArrayAccess key => (Word64 -> Word64 -> Word64 -> a) -> key -> CryptoFailable a 79init3DES constr k 80 | len == 24 = CryptoPassed $ constr k1 k2 k3 81 | otherwise = CryptoFailed CryptoError_KeySizeInvalid 82 where len = B.length k 83 (k1, k2, k3) = (fromBE $ B.toW64BE k 0, fromBE $ B.toW64BE k 8, fromBE $ B.toW64BE k 16) 84 85init2DES :: ByteArrayAccess key => (Word64 -> Word64 -> a) -> key -> CryptoFailable a 86init2DES constr k 87 | len == 16 = CryptoPassed $ constr k1 k2 88 | otherwise = CryptoFailed CryptoError_KeySizeInvalid 89 where len = B.length k 90 (k1, k2) = (fromBE $ B.toW64BE k 0, fromBE $ B.toW64BE k 8) 91