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

import Data.Byteable
import Data.Word
import Crypto.Cipher.Types
import Crypto.Cipher.DES.Primitive
import Crypto.Cipher.DES.Serialization

-- | 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
/= :: DES -> DES -> Bool
$c/= :: DES -> DES -> Bool
== :: DES -> DES -> Bool
$c== :: 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 :: Key DES -> DES
cipherInit Key DES
k    = Key DES -> DES
forall b. Byteable b => b -> DES
initDES Key DES
k

instance BlockCipher DES where
    blockSize :: DES -> Int
blockSize DES
_ = Int
8
    ecbEncrypt :: DES -> ByteString -> ByteString
ecbEncrypt (DES Word64
key) = [Block] -> ByteString
unblockify ([Block] -> ByteString)
-> (ByteString -> [Block]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Block -> Block) -> [Block] -> [Block]
forall a b. (a -> b) -> [a] -> [b]
map (Word64 -> Block -> Block
encrypt Word64
key) ([Block] -> [Block])
-> (ByteString -> [Block]) -> ByteString -> [Block]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Block]
blockify
    ecbDecrypt :: DES -> ByteString -> ByteString
ecbDecrypt (DES Word64
key) = [Block] -> ByteString
unblockify ([Block] -> ByteString)
-> (ByteString -> [Block]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Block -> Block) -> [Block] -> [Block]
forall a b. (a -> b) -> [a] -> [b]
map (Word64 -> Block -> Block
decrypt Word64
key) ([Block] -> [Block])
-> (ByteString -> [Block]) -> ByteString -> [Block]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Block]
blockify

initDES :: Byteable b => b -> DES
initDES :: forall b. Byteable b => b -> DES
initDES b
k
    | Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
8  = Word64 -> DES
DES Word64
key
    | Bool
otherwise = String -> DES
forall a. HasCallStack => String -> a
error String
"DES: not a valid key length (valid=8)"
  where len :: Int
len  = b -> Int
forall a. Byteable a => a -> Int
byteableLength b
k
        (Block Word64
key) = ByteString -> Block
toW64 (ByteString -> Block) -> ByteString -> Block
forall a b. (a -> b) -> a -> b
$ b -> ByteString
forall a. Byteable a => a -> ByteString
toBytes b
k