-- |
-- Module      : Data.Store.PKCS5
-- License     : BSD-style
-- Maintainer  : Olivier Chéron <olivier.cheron@gmail.com>
-- Stability   : experimental
-- Portability : unknown
--
-- Password-Based Cryptography, aka PKCS #5.
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Crypto.Store.PKCS5
    ( Password
    , EncryptedContent
    -- * High-level API
    , PKCS5(..)
    , encrypt
    , decrypt
    -- * Encryption schemes
    , EncryptionScheme(..)
    , PBEParameter(..)
    , PBES2Parameter(..)
    -- * Key derivation
    , KeyDerivationFunc(..)
    , PBKDF2_PRF(..)
    , Salt
    , generateSalt
    -- * Content encryption
    , ContentEncryptionParams
    , ContentEncryptionAlg(..)
    , ContentEncryptionCipher(..)
    , generateEncryptionParams
    , getContentEncryptionAlg
    -- * Low-level API
    , pbEncrypt
    , pbDecrypt
    ) where

import           Data.ASN1.Types
import           Data.ByteArray (ByteArrayAccess)
import           Data.ByteString (ByteString)
import           Data.Maybe (fromMaybe)

import Crypto.Store.ASN1.Parse
import Crypto.Store.ASN1.Generate
import Crypto.Store.CMS.Algorithms
import Crypto.Store.CMS.Encrypted
import Crypto.Store.CMS.Enveloped
import Crypto.Store.CMS.Util
import Crypto.Store.Error
import Crypto.Store.PKCS5.PBES1

data EncryptionSchemeType = Type_PBES2
                          | Type_PBE_MD5_DES_CBC
                          | Type_PBE_SHA1_DES_CBC
                          | Type_PBE_SHA1_RC4_128
                          | Type_PBE_SHA1_RC4_40
                          | Type_PBE_SHA1_DES_EDE3_CBC
                          | Type_PBE_SHA1_DES_EDE2_CBC
                          | Type_PBE_SHA1_RC2_128
                          | Type_PBE_SHA1_RC2_40

instance Enumerable EncryptionSchemeType where
    values :: [EncryptionSchemeType]
values = [ EncryptionSchemeType
Type_PBES2
             , EncryptionSchemeType
Type_PBE_MD5_DES_CBC
             , EncryptionSchemeType
Type_PBE_SHA1_DES_CBC
             , EncryptionSchemeType
Type_PBE_SHA1_RC4_128
             , EncryptionSchemeType
Type_PBE_SHA1_RC4_40
             , EncryptionSchemeType
Type_PBE_SHA1_DES_EDE3_CBC
             , EncryptionSchemeType
Type_PBE_SHA1_DES_EDE2_CBC
             , EncryptionSchemeType
Type_PBE_SHA1_RC2_128
             , EncryptionSchemeType
Type_PBE_SHA1_RC2_40
             ]

instance OIDable EncryptionSchemeType where
    getObjectID :: EncryptionSchemeType -> OID
getObjectID EncryptionSchemeType
Type_PBES2                 = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
5,Integer
13]
    getObjectID EncryptionSchemeType
Type_PBE_MD5_DES_CBC       = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
5,Integer
3]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_DES_CBC      = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
5,Integer
10]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_RC4_128      = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
12,Integer
1,Integer
1]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_RC4_40       = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
12,Integer
1,Integer
2]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_DES_EDE3_CBC = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
12,Integer
1,Integer
3]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_DES_EDE2_CBC = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
12,Integer
1,Integer
4]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_RC2_128      = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
12,Integer
1,Integer
5]
    getObjectID EncryptionSchemeType
Type_PBE_SHA1_RC2_40       = [Integer
1,Integer
2,Integer
840,Integer
113549,Integer
1,Integer
12,Integer
1,Integer
6]

instance OIDNameable EncryptionSchemeType where
    fromObjectID :: OID -> Maybe EncryptionSchemeType
fromObjectID OID
oid = forall a. OIDNameableWrapper a -> a
unOIDNW forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. OIDNameable a => OID -> Maybe a
fromObjectID OID
oid

-- | Password-Based Encryption Scheme (PBES).
data EncryptionScheme = PBES2 PBES2Parameter               -- ^ PBES2
                      | PBE_MD5_DES_CBC PBEParameter       -- ^ pbeWithMD5AndDES-CBC
                      | PBE_SHA1_DES_CBC PBEParameter      -- ^ pbeWithSHA1AndDES-CBC
                      | PBE_SHA1_RC4_128 PBEParameter      -- ^ pbeWithSHAAnd128BitRC4
                      | PBE_SHA1_RC4_40 PBEParameter       -- ^ pbeWithSHAAnd40BitRC4
                      | PBE_SHA1_DES_EDE3_CBC PBEParameter -- ^ pbeWithSHAAnd3-KeyTripleDES-CBC
                      | PBE_SHA1_DES_EDE2_CBC PBEParameter -- ^ pbeWithSHAAnd2-KeyTripleDES-CBC
                      | PBE_SHA1_RC2_128 PBEParameter      -- ^ pbeWithSHAAnd128BitRC2-CBC
                      | PBE_SHA1_RC2_40 PBEParameter       -- ^ pbewithSHAAnd40BitRC2-CBC
                      deriving (Int -> EncryptionScheme -> ShowS
[EncryptionScheme] -> ShowS
EncryptionScheme -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EncryptionScheme] -> ShowS
$cshowList :: [EncryptionScheme] -> ShowS
show :: EncryptionScheme -> String
$cshow :: EncryptionScheme -> String
showsPrec :: Int -> EncryptionScheme -> ShowS
$cshowsPrec :: Int -> EncryptionScheme -> ShowS
Show,EncryptionScheme -> EncryptionScheme -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EncryptionScheme -> EncryptionScheme -> Bool
$c/= :: EncryptionScheme -> EncryptionScheme -> Bool
== :: EncryptionScheme -> EncryptionScheme -> Bool
$c== :: EncryptionScheme -> EncryptionScheme -> Bool
Eq)

-- | PBES2 parameters.
data PBES2Parameter = PBES2Parameter
    { PBES2Parameter -> KeyDerivationFunc
pbes2KDF     :: KeyDerivationFunc       -- ^ Key derivation function
    , PBES2Parameter -> ContentEncryptionParams
pbes2EScheme :: ContentEncryptionParams -- ^ Underlying encryption scheme
    }
    deriving (Int -> PBES2Parameter -> ShowS
[PBES2Parameter] -> ShowS
PBES2Parameter -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PBES2Parameter] -> ShowS
$cshowList :: [PBES2Parameter] -> ShowS
show :: PBES2Parameter -> String
$cshow :: PBES2Parameter -> String
showsPrec :: Int -> PBES2Parameter -> ShowS
$cshowsPrec :: Int -> PBES2Parameter -> ShowS
Show,PBES2Parameter -> PBES2Parameter -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PBES2Parameter -> PBES2Parameter -> Bool
$c/= :: PBES2Parameter -> PBES2Parameter -> Bool
== :: PBES2Parameter -> PBES2Parameter -> Bool
$c== :: PBES2Parameter -> PBES2Parameter -> Bool
Eq)

instance ASN1Elem e => ProduceASN1Object e PBES2Parameter where
    asn1s :: PBES2Parameter -> ASN1Stream e
asn1s PBES2Parameter{KeyDerivationFunc
ContentEncryptionParams
pbes2EScheme :: ContentEncryptionParams
pbes2KDF :: KeyDerivationFunc
pbes2EScheme :: PBES2Parameter -> ContentEncryptionParams
pbes2KDF :: PBES2Parameter -> KeyDerivationFunc
..} =
        let kdFunc :: ASN1Stream e
kdFunc  = forall e param.
(ASN1Elem e, AlgorithmId param, OIDable (AlgorithmType param)) =>
ASN1ConstructionType -> param -> ASN1Stream e
algorithmASN1S ASN1ConstructionType
Sequence KeyDerivationFunc
pbes2KDF
            eScheme :: ASN1Stream e
eScheme = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s ContentEncryptionParams
pbes2EScheme
         in forall e.
ASN1Elem e =>
ASN1ConstructionType -> ASN1Stream e -> ASN1Stream e
asn1Container ASN1ConstructionType
Sequence (ASN1Stream e
kdFunc forall b c a. (b -> c) -> (a -> b) -> a -> c
. ASN1Stream e
eScheme)

instance Monoid e => ParseASN1Object e PBES2Parameter where
    parse :: ParseASN1 e PBES2Parameter
parse = forall e a.
Monoid e =>
ASN1ConstructionType -> ParseASN1 e a -> ParseASN1 e a
onNextContainer ASN1ConstructionType
Sequence forall a b. (a -> b) -> a -> b
$ do
        KeyDerivationFunc
kdFunc  <- forall e param.
(Monoid e, AlgorithmId param, OIDNameable (AlgorithmType param)) =>
ASN1ConstructionType -> ParseASN1 e param
parseAlgorithm ASN1ConstructionType
Sequence
        ContentEncryptionParams
eScheme <- forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
        case KeyDerivationFunc -> Maybe Int
kdfKeyLength KeyDerivationFunc
kdFunc of
            Maybe Int
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
            Just Int
sz
                | forall params. HasKeySize params => params -> Int -> Bool
validateKeySize ContentEncryptionParams
eScheme Int
sz -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
                | Bool
otherwise -> forall e a. String -> ParseASN1 e a
throwParseError String
"PBES2Parameter: parsed key length incompatible with encryption scheme"
        forall (m :: * -> *) a. Monad m => a -> m a
return PBES2Parameter { pbes2KDF :: KeyDerivationFunc
pbes2KDF = KeyDerivationFunc
kdFunc, pbes2EScheme :: ContentEncryptionParams
pbes2EScheme = ContentEncryptionParams
eScheme }

instance AlgorithmId EncryptionScheme where
    type AlgorithmType EncryptionScheme = EncryptionSchemeType
    algorithmName :: EncryptionScheme -> String
algorithmName EncryptionScheme
_  = String
"encryption scheme"

    algorithmType :: EncryptionScheme -> AlgorithmType EncryptionScheme
algorithmType (PBES2 PBES2Parameter
_)                 = EncryptionSchemeType
Type_PBES2
    algorithmType (PBE_MD5_DES_CBC PBEParameter
_)       = EncryptionSchemeType
Type_PBE_MD5_DES_CBC
    algorithmType (PBE_SHA1_DES_CBC PBEParameter
_)      = EncryptionSchemeType
Type_PBE_SHA1_DES_CBC
    algorithmType (PBE_SHA1_RC4_128 PBEParameter
_)      = EncryptionSchemeType
Type_PBE_SHA1_RC4_128
    algorithmType (PBE_SHA1_RC4_40 PBEParameter
_)       = EncryptionSchemeType
Type_PBE_SHA1_RC4_40
    algorithmType (PBE_SHA1_DES_EDE3_CBC PBEParameter
_) = EncryptionSchemeType
Type_PBE_SHA1_DES_EDE3_CBC
    algorithmType (PBE_SHA1_DES_EDE2_CBC PBEParameter
_) = EncryptionSchemeType
Type_PBE_SHA1_DES_EDE2_CBC
    algorithmType (PBE_SHA1_RC2_128 PBEParameter
_)      = EncryptionSchemeType
Type_PBE_SHA1_RC2_128
    algorithmType (PBE_SHA1_RC2_40 PBEParameter
_)       = EncryptionSchemeType
Type_PBE_SHA1_RC2_40

    parameterASN1S :: forall e. ASN1Elem e => EncryptionScheme -> ASN1Stream e
parameterASN1S (PBES2 PBES2Parameter
p)                 = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBES2Parameter
p
    parameterASN1S (PBE_MD5_DES_CBC PBEParameter
p)       = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_DES_CBC PBEParameter
p)      = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_RC4_128 PBEParameter
p)      = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_RC4_40 PBEParameter
p)       = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_DES_EDE3_CBC PBEParameter
p) = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_DES_EDE2_CBC PBEParameter
p) = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_RC2_128 PBEParameter
p)      = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p
    parameterASN1S (PBE_SHA1_RC2_40 PBEParameter
p)       = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s PBEParameter
p

    parseParameter :: forall e.
Monoid e =>
AlgorithmType EncryptionScheme -> ParseASN1 e EncryptionScheme
parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBES2                 = PBES2Parameter -> EncryptionScheme
PBES2 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_MD5_DES_CBC       = PBEParameter -> EncryptionScheme
PBE_MD5_DES_CBC forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_DES_CBC      = PBEParameter -> EncryptionScheme
PBE_SHA1_DES_CBC forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_RC4_128      = PBEParameter -> EncryptionScheme
PBE_SHA1_RC4_128 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_RC4_40       = PBEParameter -> EncryptionScheme
PBE_SHA1_RC4_40 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_DES_EDE3_CBC = PBEParameter -> EncryptionScheme
PBE_SHA1_DES_EDE3_CBC forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_DES_EDE2_CBC = PBEParameter -> EncryptionScheme
PBE_SHA1_DES_EDE2_CBC forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_RC2_128      = PBEParameter -> EncryptionScheme
PBE_SHA1_RC2_128 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
    parseParameter AlgorithmType EncryptionScheme
EncryptionSchemeType
Type_PBE_SHA1_RC2_40       = PBEParameter -> EncryptionScheme
PBE_SHA1_RC2_40 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse

instance ASN1Elem e => ProduceASN1Object e EncryptionScheme where
    asn1s :: EncryptionScheme -> ASN1Stream e
asn1s = forall e param.
(ASN1Elem e, AlgorithmId param, OIDable (AlgorithmType param)) =>
ASN1ConstructionType -> param -> ASN1Stream e
algorithmASN1S ASN1ConstructionType
Sequence

instance Monoid e => ParseASN1Object e EncryptionScheme where
    parse :: ParseASN1 e EncryptionScheme
parse = forall e param.
(Monoid e, AlgorithmId param, OIDNameable (AlgorithmType param)) =>
ASN1ConstructionType -> ParseASN1 e param
parseAlgorithm ASN1ConstructionType
Sequence


-- High-level API

-- | Content encrypted with a Password-Based Encryption Scheme (PBES).
--
-- The content will usually be the binary representation of an ASN.1 object,
-- however the transformation may be applied to any bytestring.
data PKCS5 = PKCS5
    { PKCS5 -> EncryptionScheme
encryptionAlgorithm :: EncryptionScheme -- ^ Scheme used to encrypt content
    , PKCS5 -> Password
encryptedData       :: EncryptedContent -- ^ Encrypted content
    }
    deriving (Int -> PKCS5 -> ShowS
[PKCS5] -> ShowS
PKCS5 -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PKCS5] -> ShowS
$cshowList :: [PKCS5] -> ShowS
show :: PKCS5 -> String
$cshow :: PKCS5 -> String
showsPrec :: Int -> PKCS5 -> ShowS
$cshowsPrec :: Int -> PKCS5 -> ShowS
Show,PKCS5 -> PKCS5 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PKCS5 -> PKCS5 -> Bool
$c/= :: PKCS5 -> PKCS5 -> Bool
== :: PKCS5 -> PKCS5 -> Bool
$c== :: PKCS5 -> PKCS5 -> Bool
Eq)

instance ASN1Elem e => ProduceASN1Object e PKCS5 where
    asn1s :: PKCS5 -> ASN1Stream e
asn1s PKCS5{Password
EncryptionScheme
encryptedData :: Password
encryptionAlgorithm :: EncryptionScheme
encryptedData :: PKCS5 -> Password
encryptionAlgorithm :: PKCS5 -> EncryptionScheme
..} = forall e.
ASN1Elem e =>
ASN1ConstructionType -> ASN1Stream e -> ASN1Stream e
asn1Container ASN1ConstructionType
Sequence (ASN1Stream e
alg forall b c a. (b -> c) -> (a -> b) -> a -> c
. ASN1Stream e
bs)
      where alg :: ASN1Stream e
alg = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s EncryptionScheme
encryptionAlgorithm
            bs :: ASN1Stream e
bs  = forall e. ASN1Elem e => Password -> ASN1Stream e
gOctetString Password
encryptedData

instance Monoid e => ParseASN1Object e PKCS5 where
    parse :: ParseASN1 e PKCS5
parse = forall e a.
Monoid e =>
ASN1ConstructionType -> ParseASN1 e a -> ParseASN1 e a
onNextContainer ASN1ConstructionType
Sequence forall a b. (a -> b) -> a -> b
$ do
        EncryptionScheme
alg <- forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse
        OctetString Password
bs <- forall e. Monoid e => ParseASN1 e ASN1
getNext
        forall (m :: * -> *) a. Monad m => a -> m a
return PKCS5 { encryptionAlgorithm :: EncryptionScheme
encryptionAlgorithm = EncryptionScheme
alg, encryptedData :: Password
encryptedData = Password
bs }

instance ASN1Object PKCS5 where
    toASN1 :: PKCS5 -> ASN1S
toASN1   = forall e obj. ProduceASN1Object e obj => obj -> ASN1Stream e
asn1s
    fromASN1 :: [ASN1] -> Either String (PKCS5, [ASN1])
fromASN1 = forall a. ParseASN1 () a -> [ASN1] -> Either String (a, [ASN1])
runParseASN1State forall e obj. ParseASN1Object e obj => ParseASN1 e obj
parse

-- | Encrypt a bytestring with the specified encryption scheme and password.
encrypt :: EncryptionScheme -> Password -> ByteString -> Either StoreError PKCS5
encrypt :: EncryptionScheme -> Password -> Password -> Either StoreError PKCS5
encrypt EncryptionScheme
alg Password
pwd Password
bs = Password -> PKCS5
build forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> EncryptionScheme
-> Password -> Password -> Either StoreError Password
pbEncrypt EncryptionScheme
alg Password
bs Password
pwd
  where
    build :: Password -> PKCS5
build Password
ed = Password
ed seq :: forall a b. a -> b -> b
`seq` PKCS5 { encryptionAlgorithm :: EncryptionScheme
encryptionAlgorithm = EncryptionScheme
alg, encryptedData :: Password
encryptedData = Password
ed }

-- | Decrypt the PKCS #5 content with the specified password.
decrypt :: PKCS5 -> Password -> Either StoreError ByteString
decrypt :: PKCS5 -> Password -> Either StoreError Password
decrypt PKCS5
obj = EncryptionScheme
-> Password -> Password -> Either StoreError Password
pbDecrypt (PKCS5 -> EncryptionScheme
encryptionAlgorithm PKCS5
obj) (PKCS5 -> Password
encryptedData PKCS5
obj)


-- Encryption Schemes

-- | Encrypt a bytestring with the specified encryption scheme and password.
pbEncrypt :: EncryptionScheme -> ByteString -> Password
          -> Either StoreError EncryptedContent
pbEncrypt :: EncryptionScheme
-> Password -> Password -> Either StoreError Password
pbEncrypt (PBES2 PBES2Parameter
p)                 = forall password result.
ByteArrayAccess password =>
(Key -> ContentEncryptionParams -> Password -> result)
-> PBES2Parameter -> Password -> password -> result
pbes2  forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt PBES2Parameter
p
pbEncrypt (PBE_MD5_DES_CBC PBEParameter
p)       = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs5  forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt DigestProxy MD5
MD5  ContentEncryptionCipher DES
DES PBEParameter
p
pbEncrypt (PBE_SHA1_DES_CBC PBEParameter
p)      = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs5  forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt DigestProxy SHA1
SHA1 ContentEncryptionCipher DES
DES PBEParameter
p
pbEncrypt (PBE_SHA1_RC4_128 PBEParameter
p)      = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12stream forall a b. a -> Either a b
Left forall key ba.
(ByteArrayAccess key, ByteArray ba) =>
key -> ba -> Either StoreError ba
rc4Combine DigestProxy SHA1
SHA1 Int
16 PBEParameter
p
pbEncrypt (PBE_SHA1_RC4_40 PBEParameter
p)       = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12stream forall a b. a -> Either a b
Left forall key ba.
(ByteArrayAccess key, ByteArray ba) =>
key -> ba -> Either StoreError ba
rc4Combine DigestProxy SHA1
SHA1 Int
5 PBEParameter
p
pbEncrypt (PBE_SHA1_DES_EDE3_CBC PBEParameter
p) = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs12 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt DigestProxy SHA1
SHA1 ContentEncryptionCipher DES_EDE3
DES_EDE3 PBEParameter
p
pbEncrypt (PBE_SHA1_DES_EDE2_CBC PBEParameter
p) = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs12 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt DigestProxy SHA1
SHA1 ContentEncryptionCipher DES_EDE2
DES_EDE2 PBEParameter
p
pbEncrypt (PBE_SHA1_RC2_128 PBEParameter
p)      = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12rc2 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt DigestProxy SHA1
SHA1 Int
128 PBEParameter
p
pbEncrypt (PBE_SHA1_RC2_40 PBEParameter
p)       = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12rc2 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentEncrypt DigestProxy SHA1
SHA1 Int
40 PBEParameter
p

-- | Decrypt an encrypted bytestring with the specified encryption scheme and
-- password.
pbDecrypt :: EncryptionScheme -> EncryptedContent -> Password -> Either StoreError ByteString
pbDecrypt :: EncryptionScheme
-> Password -> Password -> Either StoreError Password
pbDecrypt (PBES2 PBES2Parameter
p)                 = forall password result.
ByteArrayAccess password =>
(Key -> ContentEncryptionParams -> Password -> result)
-> PBES2Parameter -> Password -> password -> result
pbes2  forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt PBES2Parameter
p
pbDecrypt (PBE_MD5_DES_CBC PBEParameter
p)       = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs5  forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt DigestProxy MD5
MD5  ContentEncryptionCipher DES
DES PBEParameter
p
pbDecrypt (PBE_SHA1_DES_CBC PBEParameter
p)      = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs5  forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt DigestProxy SHA1
SHA1 ContentEncryptionCipher DES
DES PBEParameter
p
pbDecrypt (PBE_SHA1_RC4_128 PBEParameter
p)      = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12stream forall a b. a -> Either a b
Left forall key ba.
(ByteArrayAccess key, ByteArray ba) =>
key -> ba -> Either StoreError ba
rc4Combine DigestProxy SHA1
SHA1 Int
16 PBEParameter
p
pbDecrypt (PBE_SHA1_RC4_40 PBEParameter
p)       = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12stream forall a b. a -> Either a b
Left forall key ba.
(ByteArrayAccess key, ByteArray ba) =>
key -> ba -> Either StoreError ba
rc4Combine DigestProxy SHA1
SHA1 Int
5 PBEParameter
p
pbDecrypt (PBE_SHA1_DES_EDE3_CBC PBEParameter
p) = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs12 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt DigestProxy SHA1
SHA1 ContentEncryptionCipher DES_EDE3
DES_EDE3 PBEParameter
p
pbDecrypt (PBE_SHA1_DES_EDE2_CBC PBEParameter
p) = forall hash cipher password result.
(HashAlgorithm hash, BlockCipher cipher,
 ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> ContentEncryptionCipher cipher
-> PBEParameter
-> Password
-> password
-> result
pkcs12 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt DigestProxy SHA1
SHA1 ContentEncryptionCipher DES_EDE2
DES_EDE2 PBEParameter
p
pbDecrypt (PBE_SHA1_RC2_128 PBEParameter
p)      = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12rc2 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt DigestProxy SHA1
SHA1 Int
128 PBEParameter
p
pbDecrypt (PBE_SHA1_RC2_40 PBEParameter
p)       = forall hash password result.
(HashAlgorithm hash, ByteArrayAccess password) =>
(StoreError -> result)
-> (Key -> ContentEncryptionParams -> Password -> result)
-> DigestProxy hash
-> Int
-> PBEParameter
-> Password
-> password
-> result
pkcs12rc2 forall a b. a -> Either a b
Left forall cek ba.
(ByteArray cek, ByteArray ba) =>
cek -> ContentEncryptionParams -> ba -> Either StoreError ba
contentDecrypt DigestProxy SHA1
SHA1 Int
40 PBEParameter
p

pbes2 :: ByteArrayAccess password
      => (Key -> ContentEncryptionParams -> ByteString -> result)
      -> PBES2Parameter -> ByteString -> password -> result
pbes2 :: forall password result.
ByteArrayAccess password =>
(Key -> ContentEncryptionParams -> Password -> result)
-> PBES2Parameter -> Password -> password -> result
pbes2 Key -> ContentEncryptionParams -> Password -> result
encdec PBES2Parameter{KeyDerivationFunc
ContentEncryptionParams
pbes2EScheme :: ContentEncryptionParams
pbes2KDF :: KeyDerivationFunc
pbes2EScheme :: PBES2Parameter -> ContentEncryptionParams
pbes2KDF :: PBES2Parameter -> KeyDerivationFunc
..} Password
bs password
pwd = Key -> ContentEncryptionParams -> Password -> result
encdec Key
key ContentEncryptionParams
pbes2EScheme Password
bs
  where key :: Key
key = forall password out.
(ByteArrayAccess password, ByteArray out) =>
KeyDerivationFunc -> Int -> password -> out
kdfDerive KeyDerivationFunc
pbes2KDF Int
len password
pwd :: Key
        len :: Int
len = forall a. a -> Maybe a -> a
fromMaybe (forall params. HasKeySize params => params -> Int
getMaximumKeySize ContentEncryptionParams
pbes2EScheme) (KeyDerivationFunc -> Maybe Int
kdfKeyLength KeyDerivationFunc
pbes2KDF)