    -- |
    -- Module      : Crypto.Cipher.DES
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : stable
    -- Portability : good
    module Crypto.Cipher.DES (
        DES,
    ) where

    import Crypto.Cipher.DES.Primitive
    import Crypto.Cipher.Types
    import Crypto.Error
    import Crypto.Internal.ByteArray (ByteArrayAccess)
    import qualified Crypto.Internal.ByteArray as B
    import Data.Memory.Endian
    import Data.Word

    -- | DES Context
    data DES = DES Word64
        deriving (DES -> DES -> Bool
    (DES -> DES -> Bool) -> (DES -> DES -> Bool) -> Eq DES
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: DES -> DES -> Bool
    == :: DES -> DES -> Bool
    $c/= :: DES -> DES -> Bool
    /= :: DES -> DES -> Bool
    Eq)

    instance Cipher DES where
        cipherName :: DES -> String
    cipherName DES
    _ = String
    "DES"
        cipherKeySize :: DES -> KeySizeSpecifier
    cipherKeySize DES
    _ = Int -> KeySizeSpecifier
    KeySizeFixed Int
    8
        cipherInit :: forall key. ByteArray key => key -> CryptoFailable DES
    cipherInit key
    k = key -> CryptoFailable DES
    forall key. ByteArrayAccess key => key -> CryptoFailable DES
    initDES key
    k

    instance BlockCipher DES where
        blockSize :: DES -> Int
    blockSize DES
    _ = Int
    8
        ecbEncrypt :: forall ba. ByteArray ba => DES -> ba -> ba
    ecbEncrypt (DES Word64
    key) = (Word64 -> Word64) -> ba -> ba
    forall bs. ByteArray bs => (Word64 -> Word64) -> bs -> bs
    B.mapAsWord64 (Block -> Word64
    unBlock (Block -> Word64) -> (Word64 -> Block) -> Word64 -> Word64
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> Block -> Block
    encrypt Word64
    key (Block -> Block) -> (Word64 -> Block) -> Word64 -> Block
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> Block
    Block)
        ecbDecrypt :: forall ba. ByteArray ba => DES -> ba -> ba
    ecbDecrypt (DES Word64
    key) = (Word64 -> Word64) -> ba -> ba
    forall bs. ByteArray bs => (Word64 -> Word64) -> bs -> bs
    B.mapAsWord64 (Block -> Word64
    unBlock (Block -> Word64) -> (Word64 -> Block) -> Word64 -> Word64
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> Block -> Block
    decrypt Word64
    key (Block -> Block) -> (Word64 -> Block) -> Word64 -> Block
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> Block
    Block)

    initDES :: ByteArrayAccess key => key -> CryptoFailable DES
    initDES :: forall key. ByteArrayAccess key => key -> CryptoFailable DES
    initDES key
    k
        | Int
    len Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    8 = DES -> CryptoFailable DES
    forall a. a -> CryptoFailable a
    CryptoPassed (DES -> CryptoFailable DES) -> DES -> CryptoFailable DES
    forall a b. (a -> b) -> a -> b
    $ Word64 -> DES
    DES Word64
    key
        | Bool
    otherwise = CryptoError -> CryptoFailable DES
    forall a. CryptoError -> CryptoFailable a
    CryptoFailed (CryptoError -> CryptoFailable DES)
    -> CryptoError -> CryptoFailable DES
    forall a b. (a -> b) -> a -> b
    $ CryptoError
    CryptoError_KeySizeInvalid
      where
        len :: Int
    len = key -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    B.length key
    k
        key :: Word64
    key = BE Word64 -> Word64
    forall a. ByteSwap a => BE a -> a
    fromBE (BE Word64 -> Word64) -> BE Word64 -> Word64
    forall a b. (a -> b) -> a -> b
    $ key -> Int -> BE Word64
    forall bs. ByteArrayAccess bs => bs -> Int -> BE Word64
    B.toW64BE key
    k Int
    0