cryptostore-0.3.1.0: Serialization of cryptographic data types

License | BSD-style
Maintainer | Olivier Chéron <olivier.cheron@gmail.com>
Stability | experimental
Portability | unknown
Safe Haskell | Safe-Inferred
Language | Haskell2010

Crypto.Store.PKCS12

Contents

- PKCS #12 privacy
- PKCS #12 contents and bags
- PKCS #12 attributes
- Credentials
- Password-based protection

Description

Personal Information Exchange Syntax, aka PKCS #12.

Only password integrity mode and password privacy modes are supported.

Synopsis

- type IntegrityParams = (DigestAlgorithm, PBEParameter)
- readP12File :: FilePath -> IO (Either StoreError (OptAuthenticated PKCS12))
- readP12FileFromMemory :: ByteString -> Either StoreError (OptAuthenticated PKCS12)
- writeP12File :: FilePath -> IntegrityParams -> ProtectionPassword -> PKCS12 -> IO (Either StoreError ())
- writeP12FileToMemory :: IntegrityParams -> ProtectionPassword -> PKCS12 -> Either StoreError ByteString
- writeUnprotectedP12File :: FilePath -> PKCS12 -> IO ()
- writeUnprotectedP12FileToMemory :: PKCS12 -> ByteString
- data PKCS12
- unPKCS12 :: PKCS12 -> OptProtected [SafeContents]
- unPKCS12' :: PKCS12 -> [OptProtected SafeContents]
- unencrypted :: SafeContents -> PKCS12
- encrypted :: EncryptionScheme -> ProtectionPassword -> SafeContents -> Either StoreError PKCS12
- newtype SafeContents = SafeContents {
  - unSafeContents :: [SafeBag]
  }
- type SafeBag = Bag SafeInfo
- data Bag info = Bag {
  - bagInfo :: info
  - bagAttributes :: [Attribute]
  }
- data SafeInfo
  - = KeyBag (FormattedKey PrivKey)
  - | PKCS8ShroudedKeyBag PKCS5
  - | CertBag (Bag CertInfo)
  - | CRLBag (Bag CRLInfo)
  - | SecretBag [ASN1]
  - | SafeContentsBag SafeContents
- newtype CertInfo = CertX509 SignedCertificate
- newtype CRLInfo = CRLX509 SignedCRL
- data Attribute = Attribute {
  - attrType :: OID
  - attrValues :: [ASN1]
  }
- getSafeKeys :: SafeContents -> [OptProtected PrivKey]
- getAllSafeKeys :: [SafeContents] -> OptProtected [PrivKey]
- getSafeX509Certs :: SafeContents -> [SignedCertificate]
- getAllSafeX509Certs :: [SafeContents] -> [SignedCertificate]
- getSafeX509CRLs :: SafeContents -> [SignedCRL]
- getAllSafeX509CRLs :: [SafeContents] -> [SignedCRL]
- findAttribute :: OID -> [Attribute] -> Maybe [ASN1]
- setAttribute :: OID -> [ASN1] -> [Attribute] -> [Attribute]
- filterAttributes :: (OID -> Bool) -> [Attribute] -> [Attribute]
- getFriendlyName :: [Attribute] -> Maybe String
- setFriendlyName :: String -> [Attribute] -> [Attribute]
- getLocalKeyId :: [Attribute] -> Maybe ByteString
- setLocalKeyId :: ByteString -> [Attribute] -> [Attribute]
- fromCredential :: Maybe EncryptionScheme -> EncryptionScheme -> ProtectionPassword -> (CertificateChain, PrivKey) -> Either StoreError PKCS12
- fromNamedCredential :: String -> Maybe EncryptionScheme -> EncryptionScheme -> ProtectionPassword -> (CertificateChain, PrivKey) -> Either StoreError PKCS12
- toCredential :: PKCS12 -> OptProtected (Maybe (CertificateChain, PrivKey))
- toNamedCredential :: String -> PKCS12 -> OptProtected (Maybe (CertificateChain, PrivKey))
- type Password = ByteString
- data OptAuthenticated a
  - = Unauthenticated a
  - | Authenticated (Password -> Either StoreError (ProtectionPassword, a))
- recoverAuthenticated :: Password -> OptAuthenticated a -> Either StoreError (ProtectionPassword, a)
- data ProtectionPassword
- emptyNotTerminated :: ProtectionPassword
- fromProtectionPassword :: ProtectionPassword -> ByteString
- toProtectionPassword :: ByteString -> ProtectionPassword
- data OptProtected a
  - = Unprotected a
  - | Protected (ProtectionPassword -> Either StoreError a)
- recover :: ProtectionPassword -> OptProtected a -> Either StoreError a
- recoverA :: Applicative f => f ProtectionPassword -> OptProtected a -> f (Either StoreError a)

# Documentation

type IntegrityParams = (DigestAlgorithm, PBEParameter) Source #

Parameters used for password integrity mode.

readP12File :: FilePath -> IO (Either StoreError (OptAuthenticated PKCS12)) Source #

Read a PKCS #12 file from disk.

readP12FileFromMemory :: ByteString -> Either StoreError (OptAuthenticated PKCS12) Source #

Read a PKCS #12 file from a bytearray in BER format.

writeP12File :: FilePath -> IntegrityParams -> ProtectionPassword -> PKCS12 -> IO (Either StoreError ()) Source #

Write a PKCS #12 file to disk.

writeP12FileToMemory :: IntegrityParams -> ProtectionPassword -> PKCS12 -> Either StoreError ByteString Source #

Write a PKCS #12 file to a bytearray in DER format.

writeUnprotectedP12File :: FilePath -> PKCS12 -> IO () Source #

Write a PKCS #12 file without integrity protection to disk.

writeUnprotectedP12FileToMemory :: PKCS12 -> ByteString Source #

Write a PKCS #12 file without integrity protection to a bytearray in DER format.

# PKCS #12 privacy

data PKCS12 Source #

PKCS #12 privacy wrapper, adding optional encryption to `SafeContents`. ASN.1 equivalent is `AuthenticatedSafe`.

The semigroup interface allows to combine multiple pieces encrypted separately but they should all derive from the same password to be readable by `unPKCS12` and most other software.

#### Instances

Instances details

Semigroup PKCS12 Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (<>) :: PKCS12 -> PKCS12 -> PKCS12 Source # sconcat :: NonEmpty PKCS12 -> PKCS12 Source # stimes :: Integral b => b -> PKCS12 -> PKCS12 Source #
Show PKCS12 Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods showsPrec :: Int -> PKCS12 -> ShowS Source # show :: PKCS12 -> String Source # showList :: [PKCS12] -> ShowS Source #
Eq PKCS12 Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (==) :: PKCS12 -> PKCS12 -> Bool Source # (/=) :: PKCS12 -> PKCS12 -> Bool Source #

unPKCS12 :: PKCS12 -> OptProtected [SafeContents] Source #

Read the contents of a PKCS #12. The same privacy password will be used for all content elements.

This convenience function returns a `Protected` value as soon as one element at least is encrypted. This does not mean all elements were actually protected in the input. If detailed view is required then function `unPKCS12'` is also available.

unPKCS12' :: PKCS12 -> [OptProtected SafeContents] Source #

Read the contents of a PKCS #12.

unencrypted :: SafeContents -> PKCS12 Source #

Build a PKCS #12 without encryption. Usage scenario is when private keys are already encrypted with `PKCS8ShroudedKeyBag`.

encrypted :: EncryptionScheme -> ProtectionPassword -> SafeContents -> Either StoreError PKCS12 Source #

Build a PKCS #12 encrypted with the specified scheme and password.

# PKCS #12 contents and bags

newtype SafeContents Source #

Content objects stored in a PKCS #12.

Constructors

SafeContents |

Fields

- unSafeContents :: [SafeBag]

#### Instances

Instances details

Show SafeContents Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods showsPrec :: Int -> SafeContents -> ShowS Source # show :: SafeContents -> String Source # showList :: [SafeContents] -> ShowS Source #
Eq SafeContents Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (==) :: SafeContents -> SafeContents -> Bool Source # (/=) :: SafeContents -> SafeContents -> Bool Source #

type SafeBag = Bag SafeInfo Source #

Main bag type in a PKCS #12.

data Bag info Source #

Polymorphic PKCS #12 bag parameterized by the payload data type.

Constructors

Bag |

Fields

- bagInfo :: info

  bag payload

- bagAttributes :: [Attribute]

  attributes providing additional information

#### Instances

Instances details

Show info => Show (Bag info) Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods showsPrec :: Int -> Bag info -> ShowS Source # show :: Bag info -> String Source # showList :: [Bag info] -> ShowS Source #
Eq info => Eq (Bag info) Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (==) :: Bag info -> Bag info -> Bool Source # (/=) :: Bag info -> Bag info -> Bool Source #

data SafeInfo Source #

Main bag payload in PKCS #12 contents.

Constructors

KeyBag (FormattedKey PrivKey) | unencrypted private key
PKCS8ShroudedKeyBag PKCS5 | encrypted private key
CertBag (Bag CertInfo) | certificate
CRLBag (Bag CRLInfo) | CRL
SecretBag [ASN1] | arbitrary secret
SafeContentsBag SafeContents | safe contents embeded recursively

#### Instances

Instances details

Show SafeInfo Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods showsPrec :: Int -> SafeInfo -> ShowS Source # show :: SafeInfo -> String Source # showList :: [SafeInfo] -> ShowS Source #
Eq SafeInfo Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (==) :: SafeInfo -> SafeInfo -> Bool Source # (/=) :: SafeInfo -> SafeInfo -> Bool Source #

newtype CertInfo Source #

Certificate bags. Only X.509 certificates are supported.

Constructors

CertX509 SignedCertificate |

#### Instances

Instances details

Show CertInfo Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods showsPrec :: Int -> CertInfo -> ShowS Source # show :: CertInfo -> String Source # showList :: [CertInfo] -> ShowS Source #
Eq CertInfo Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (==) :: CertInfo -> CertInfo -> Bool Source # (/=) :: CertInfo -> CertInfo -> Bool Source #

newtype CRLInfo Source #

CRL bags. Only X.509 CRLs are supported.

Constructors

CRLX509 SignedCRL |

#### Instances

Instances details

Show CRLInfo Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods showsPrec :: Int -> CRLInfo -> ShowS Source # show :: CRLInfo -> String Source # showList :: [CRLInfo] -> ShowS Source #
Eq CRLInfo Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods (==) :: CRLInfo -> CRLInfo -> Bool Source # (/=) :: CRLInfo -> CRLInfo -> Bool Source #

data Attribute Source #

An attribute extending the parent structure with arbitrary data.

Constructors

Attribute |

Fields

- attrType :: OID

  Attribute type

- attrValues :: [ASN1]

  Attribute values

#### Instances

Instances details

Show Attribute Source # |
Instance details Defined in Crypto.Store.CMS.Attribute Methods showsPrec :: Int -> Attribute -> ShowS Source # show :: Attribute -> String Source # showList :: [Attribute] -> ShowS Source #
Eq Attribute Source # |
Instance details Defined in Crypto.Store.CMS.Attribute Methods (==) :: Attribute -> Attribute -> Bool Source # (/=) :: Attribute -> Attribute -> Bool Source #

getSafeKeys :: SafeContents -> [OptProtected PrivKey] Source #

Return all private keys contained in the safe contents.

getAllSafeKeys :: [SafeContents] -> OptProtected [PrivKey] Source #

Return all private keys contained in the safe content list. All shrouded private keys must derive from the same password.

This convenience function returns a `Protected` value as soon as one key at least is encrypted. This does not mean all keys were actually protected in the input. If detailed view is required then function `getSafeKeys` is available.

getSafeX509Certs :: SafeContents -> [SignedCertificate] Source #

Return all X.509 certificates contained in the safe contents.

getAllSafeX509Certs :: [SafeContents] -> [SignedCertificate] Source #

Return all X.509 certificates contained in the safe content list.

getSafeX509CRLs :: SafeContents -> [SignedCRL] Source #

Return all X.509 CRLs contained in the safe contents.

getAllSafeX509CRLs :: [SafeContents] -> [SignedCRL] Source #

Return all X.509 CRLs contained in the safe content list.

# PKCS #12 attributes

findAttribute :: OID -> [Attribute] -> Maybe [ASN1] Source #

Return the values for the first attribute with the specified type.

setAttribute :: OID -> [ASN1] -> [Attribute] -> [Attribute] Source #

Add or replace an attribute in a list of attributes.

filterAttributes :: (OID -> Bool) -> [Attribute] -> [Attribute] Source #

Filter a list of attributes based on a predicate applied to attribute type.

getFriendlyName :: [Attribute] -> Maybe String Source #

Return the value of the `friendlyName` attribute.

setFriendlyName :: String -> [Attribute] -> [Attribute] Source #

Add or replace the `friendlyName` attribute in a list of attributes.

getLocalKeyId :: [Attribute] -> Maybe ByteString Source #

Return the value of the `localKeyId` attribute.

setLocalKeyId :: ByteString -> [Attribute] -> [Attribute] Source #

Add or replace the `localKeyId` attribute in a list of attributes.

# Credentials

fromCredential :: Maybe EncryptionScheme -> EncryptionScheme -> ProtectionPassword -> (CertificateChain, PrivKey) -> Either StoreError PKCS12 Source #

Build a `PKCS12` value containing a private key and certificate chain. Distinct encryption is applied for both. Encrypting the certificate chain is optional.

Note: advice is to always generate fresh and independent `EncryptionScheme` values so that the salt is not reused twice in the encryption process.

fromNamedCredential :: String -> Maybe EncryptionScheme -> EncryptionScheme -> ProtectionPassword -> (CertificateChain, PrivKey) -> Either StoreError PKCS12 Source #

Build a `PKCS12` value containing a private key and certificate chain identified with the specified friendly name. Distinct encryption is applied for private key and certificates. Encrypting the certificate chain is optional.

Note: advice is to always generate fresh and independent `EncryptionScheme` values so that the salt is not reused twice in the encryption process.

toCredential :: PKCS12 -> OptProtected (Maybe (CertificateChain, PrivKey)) Source #

Extract the private key and certificate chain from a `PKCS12` value. A credential is returned when the structure contains exactly one private key and at least one X.509 certificate.

toNamedCredential :: String -> PKCS12 -> OptProtected (Maybe (CertificateChain, PrivKey)) Source #

Extract a private key and certificate chain with the specified friendly name from a `PKCS12` value. A credential is returned when the structure contains exactly one private key and one X.509 certificate with the name.

# Password-based protection

type Password = ByteString Source #

A password stored as a sequence of UTF-8 bytes.

Some key-derivation functions add restrictions to what characters are supported.

Beware: `fromString` truncates multi-byte characters. If the string may contain non-ASCII characters, prefer instead ``fromProtectionPassword` . `fromString``.

data OptAuthenticated a Source #

Data type for objects that are possibly authenticated with a password.

Content is verified and retrieved by providing a `Password` value. When verification is successful, a value of type `ProtectionPassword` is also returned and this value can be fed to an inner decryption layer that needs the same password (usual case for PKCS #12).

Constructors

Unauthenticated a | Value is not authenticated
Authenticated (Password -> Either StoreError (ProtectionPassword, a)) | Value is authenticated with a password

#### Instances

Instances details

Functor OptAuthenticated Source # |
Instance details Defined in Crypto.Store.PKCS12 Methods fmap :: (a -> b) -> OptAuthenticated a -> OptAuthenticated b Source # (<$) :: a -> OptAuthenticated b -> OptAuthenticated a Source #

recoverAuthenticated :: Password -> OptAuthenticated a -> Either StoreError (ProtectionPassword, a) Source #

Try to recover an `OptAuthenticated` content using the specified password.

When successful, the content is returned, as well as the password converted to type `ProtectionPassword`. This password value can then be fed to the inner decryption layer when both passwords are known to be same (usual case for PKCS #12).

data ProtectionPassword Source #

A password stored as a sequence of UTF-8 bytes.

Some key-derivation functions add restrictions to what characters are supported.

The data type provides a special value `emptyNotTerminated` that is used as alternate representation of empty passwords on some systems and that produces encryption results different than an empty bytearray.

Conversion to/from a regular sequence of bytes is possible with functions `toProtectionPassword` and `fromProtectionPassword`.

Beware: the `fromString` implementation correctly handles multi-byte characters, so here is not equivalent to the `ByteString` counterpart.

#### Instances

Instances details

IsString ProtectionPassword Source # |
Instance details Defined in Crypto.Store.PKCS5.PBES1 Methods fromString :: String -> ProtectionPassword Source #
Show ProtectionPassword Source # |
Instance details Defined in Crypto.Store.PKCS5.PBES1 Methods showsPrec :: Int -> ProtectionPassword -> ShowS Source # show :: ProtectionPassword -> String Source # showList :: [ProtectionPassword] -> ShowS Source #
Eq ProtectionPassword Source # |
Instance details Defined in Crypto.Store.PKCS5.PBES1 Methods (==) :: ProtectionPassword -> ProtectionPassword -> Bool Source # (/=) :: ProtectionPassword -> ProtectionPassword -> Bool Source #
ByteArrayAccess ProtectionPassword Source # |
Instance details Defined in Crypto.Store.PKCS5.PBES1 Methods length :: ProtectionPassword -> Int Source # withByteArray :: ProtectionPassword -> (Ptr p -> IO a) -> IO a Source # copyByteArrayToPtr :: ProtectionPassword -> Ptr p -> IO () Source #

emptyNotTerminated :: ProtectionPassword Source #

A value denoting an empty password, but having a special encoding when deriving a symmetric key on some systems, like the certificate export wizard on Windows.

This value is different from ``toProtectionPassword` ""` and can be tried when decrypting content with a password known to be empty.

fromProtectionPassword :: ProtectionPassword -> ByteString Source #

Extract the UTF-8 bytes in a password value.

toProtectionPassword :: ByteString -> ProtectionPassword Source #

Build a password value from a sequence of UTF-8 bytes.

When the password is empty, the special value `emptyNotTerminated` may be tried as well.

data OptProtected a Source #

Data type for objects that are possibly protected with a password.

Constructors

Unprotected a | Value is unprotected
Protected (ProtectionPassword -> Either StoreError a) | Value is protected with a password

#### Instances

Instances details

Functor OptProtected Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods fmap :: (a -> b) -> OptProtected a -> OptProtected b Source # (<$) :: a -> OptProtected b -> OptProtected a Source #

recover :: ProtectionPassword -> OptProtected a -> Either StoreError a Source #

Try to recover an `OptProtected` content using the specified password.

recoverA :: Applicative f => f ProtectionPassword -> OptProtected a -> f (Either StoreError a) Source #

Try to recover an `OptProtected` content in an applicative context. The applicative password is used if necessary.

    import qualified Data.ByteString as B
    import           Crypto.Store.PKCS8

    [encryptedKey] <- readKeyFile "privkey.pem"
    let askForPassword = putStr "Please enter password: " >> B.getLine
    result <- recoverA (toProtectionPassword <$> askForPassword) encryptedKey
    case result of
        Left err  -> putStrLn $ "Unable to recover key: " ++ show err
        Right key -> print key