module Crypto.Store.KeyWrap.TripleDES
( wrap
, unwrap
) where
import Data.ByteArray (ByteArray)
import qualified Data.ByteArray as B
import Crypto.Cipher.Types
import Crypto.Hash
import Crypto.Store.Error
import Crypto.Store.Util
checksum :: ByteArray ba => ba -> ba
checksum :: forall ba. ByteArray ba => ba -> ba
checksum ba
bs = View (Digest SHA1) -> ba
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
B.convert (View (Digest SHA1) -> ba) -> View (Digest SHA1) -> ba
forall a b. (a -> b) -> a -> b
$ Digest SHA1 -> Int -> View (Digest SHA1)
forall bytes. ByteArrayAccess bytes => bytes -> Int -> View bytes
B.takeView (SHA1 -> ba -> Digest SHA1
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA1
SHA1 ba
bs) Int
8
iv4adda22c79e82105 :: B.Bytes
iv4adda22c79e82105 :: Bytes
iv4adda22c79e82105 = [Word8] -> Bytes
forall a. ByteArray a => [Word8] -> a
B.pack [Word8
0x4a, Word8
0xdd, Word8
0xa2, Word8
0x2c, Word8
0x79, Word8
0xe8, Word8
0x21, Word8
0x05]
wrap :: (BlockCipher cipher, ByteArray ba)
=> cipher -> IV cipher -> ba -> Either StoreError ba
wrap :: forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> IV cipher -> ba -> Either StoreError ba
wrap cipher
cipher IV cipher
iv ba
cek
| Int
inLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
24 = ba -> Either StoreError ba
forall a b. b -> Either a b
Right ba
wrapped
| Bool
otherwise = StoreError -> Either StoreError ba
forall a b. a -> Either a b
Left
(String -> StoreError
InvalidInput String
"KeyWrap.TripleDES: invalid length for content encryption key")
where
inLen :: Int
inLen = ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
cek
Just IV cipher
iv' = Bytes -> Maybe (IV cipher)
forall b c. (ByteArrayAccess b, BlockCipher c) => b -> Maybe (IV c)
makeIV Bytes
iv4adda22c79e82105
cekicv :: ba
cekicv = ba -> ba -> ba
forall bs. ByteArray bs => bs -> bs -> bs
B.append ba
cek (ba -> ba
forall ba. ByteArray ba => ba -> ba
checksum ba
cek)
temp1 :: ba
temp1 = cipher -> IV cipher -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> IV cipher -> ba -> ba
forall ba. ByteArray ba => cipher -> IV cipher -> ba -> ba
cbcEncrypt cipher
cipher IV cipher
iv ba
cekicv
temp2 :: ba
temp2 = ba -> ba -> ba
forall bs. ByteArray bs => bs -> bs -> bs
B.append (IV cipher -> ba
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
B.convert IV cipher
iv) ba
temp1
temp3 :: ba
temp3 = ba -> ba
forall ba. ByteArray ba => ba -> ba
reverseBytes ba
temp2
wrapped :: ba
wrapped = cipher -> IV cipher -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> IV cipher -> ba -> ba
forall ba. ByteArray ba => cipher -> IV cipher -> ba -> ba
cbcEncrypt cipher
cipher IV cipher
iv' ba
temp3
unwrap :: (BlockCipher cipher, ByteArray ba)
=> cipher -> ba -> Either StoreError ba
unwrap :: forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> Either StoreError ba
unwrap cipher
cipher ba
wrapped
| Int
inLen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
40 = Either StoreError ba
forall {b}. Either StoreError b
invalid
| ba -> ba -> Bool
forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
B.constEq ba
icv (ba -> ba
forall ba. ByteArray ba => ba -> ba
checksum ba
cek) = ba -> Either StoreError ba
forall a b. b -> Either a b
Right ba
cek
| Bool
otherwise = Either StoreError ba
forall {b}. Either StoreError b
invalid
where
inLen :: Int
inLen = ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
wrapped
Just IV cipher
iv' = Bytes -> Maybe (IV cipher)
forall b c. (ByteArrayAccess b, BlockCipher c) => b -> Maybe (IV c)
makeIV Bytes
iv4adda22c79e82105
temp3 :: ba
temp3 = cipher -> IV cipher -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> IV cipher -> ba -> ba
forall ba. ByteArray ba => cipher -> IV cipher -> ba -> ba
cbcDecrypt cipher
cipher IV cipher
iv' ba
wrapped
temp2 :: ba
temp2 = ba -> ba
forall ba. ByteArray ba => ba -> ba
reverseBytes ba
temp3
(ba
ivBs, ba
temp1) = Int -> ba -> (ba, ba)
forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
8 ba
temp2
Just IV cipher
iv = ba -> Maybe (IV cipher)
forall b c. (ByteArrayAccess b, BlockCipher c) => b -> Maybe (IV c)
makeIV ba
ivBs
cekicv :: ba
cekicv = cipher -> IV cipher -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> IV cipher -> ba -> ba
forall ba. ByteArray ba => cipher -> IV cipher -> ba -> ba
cbcDecrypt cipher
cipher IV cipher
iv ba
temp1
(ba
cek, ba
icv) = Int -> ba -> (ba, ba)
forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
24 ba
cekicv
invalid :: Either StoreError b
invalid = StoreError -> Either StoreError b
forall a b. a -> Either a b
Left StoreError
BadChecksum