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.PKCS8

Contents

- Serialization formats
- Password-based protection
- Reading and writing PEM files

Description

Private-Key Information Syntax, aka PKCS #8.

Presents an API similar to Data.X509.Memory and Data.X509.File but allows to write private keys and provides support for password-based encryption.

Functions to read a private key return an object wrapped in the `OptProtected` data type.

Functions related to public keys, certificates and CRLs are available from Crypto.Store.X509.

Synopsis

- readKeyFile :: FilePath -> IO [OptProtected PrivKey]
- readKeyFileFromMemory :: ByteString -> [OptProtected PrivKey]
- pemToKey :: [Maybe (OptProtected PrivKey)] -> PEM -> [Maybe (OptProtected PrivKey)]
- writeKeyFile :: PrivateKeyFormat -> FilePath -> [PrivKey] -> IO ()
- writeKeyFileToMemory :: PrivateKeyFormat -> [PrivKey] -> ByteString
- keyToPEM :: PrivateKeyFormat -> PrivKey -> PEM
- writeEncryptedKeyFile :: FilePath -> EncryptionScheme -> ProtectionPassword -> PrivKey -> IO (Either StoreError ())
- writeEncryptedKeyFileToMemory :: EncryptionScheme -> ProtectionPassword -> PrivKey -> Either StoreError ByteString
- encryptKeyToPEM :: EncryptionScheme -> ProtectionPassword -> PrivKey -> Either StoreError PEM
- data PrivateKeyFormat
  - = TraditionalFormat
  - | PKCS8Format
- data FormattedKey a = FormattedKey PrivateKeyFormat 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)
- readPEMs :: FilePath -> IO [PEM]
- writePEMs :: FilePath -> [PEM] -> IO ()

# Documentation

readKeyFile :: FilePath -> IO [OptProtected PrivKey] Source #

Read private keys from a PEM file.

readKeyFileFromMemory :: ByteString -> [OptProtected PrivKey] Source #

Read private keys from a bytearray in PEM format.

pemToKey :: [Maybe (OptProtected PrivKey)] -> PEM -> [Maybe (OptProtected PrivKey)] Source #

Read a private key from a `PEM` element and add it to the accumulator list.

writeKeyFile :: PrivateKeyFormat -> FilePath -> [PrivKey] -> IO () Source #

Write unencrypted private keys to a PEM file.

writeKeyFileToMemory :: PrivateKeyFormat -> [PrivKey] -> ByteString Source #

Write unencrypted private keys to a bytearray in PEM format.

keyToPEM :: PrivateKeyFormat -> PrivKey -> PEM Source #

Generate an unencrypted PEM for a private key.

writeEncryptedKeyFile :: FilePath -> EncryptionScheme -> ProtectionPassword -> PrivKey -> IO (Either StoreError ()) Source #

Write a PKCS #8 encrypted private key to a PEM file.

If multiple keys need to be stored in the same file, use functions `encryptKeyToPEM` and `writePEMs`.

Fresh `EncryptionScheme` parameters should be generated for each key to encrypt.

writeEncryptedKeyFileToMemory :: EncryptionScheme -> ProtectionPassword -> PrivKey -> Either StoreError ByteString Source #

Write a PKCS #8 encrypted private key to a bytearray in PEM format.

If multiple keys need to be stored in the same bytearray, use functions `encryptKeyToPEM` and `pemWriteBS` or `pemWriteLBS`.

Fresh `EncryptionScheme` parameters should be generated for each key to encrypt.

encryptKeyToPEM :: EncryptionScheme -> ProtectionPassword -> PrivKey -> Either StoreError PEM Source #

Generate a PKCS #8 encrypted PEM for a private key.

Fresh `EncryptionScheme` parameters should be generated for each key to encrypt.

# Serialization formats

data PrivateKeyFormat Source #

Private-key serialization format.

Encryption in traditional format is not supported currently.

Constructors

TraditionalFormat | SSLeay compatible
PKCS8Format | PKCS #8

#### Instances

Instances details

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

data FormattedKey a Source #

A key associated with format. Allows to implement `ASN1Object` instances.

Constructors

FormattedKey PrivateKeyFormat a |

#### Instances

Instances details

Functor FormattedKey Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods fmap :: (a -> b) -> FormattedKey a -> FormattedKey b Source # (<$) :: a -> FormattedKey b -> FormattedKey a Source #
ASN1Object (FormattedKey KeyPair) Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods toASN1 :: FormattedKey KeyPair -> ASN1S Source # fromASN1 :: [ASN1] -> Either String (FormattedKey KeyPair, [ASN1]) Source #
ASN1Object (FormattedKey PrivateKey) Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods toASN1 :: FormattedKey PrivateKey -> ASN1S Source # fromASN1 :: [ASN1] -> Either String (FormattedKey PrivateKey, [ASN1]) Source #
ASN1Object (FormattedKey PrivKey) Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods toASN1 :: FormattedKey PrivKey -> ASN1S Source # fromASN1 :: [ASN1] -> Either String (FormattedKey PrivKey, [ASN1]) Source #
ASN1Object (FormattedKey PrivKeyEC) Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods toASN1 :: FormattedKey PrivKeyEC -> ASN1S Source # fromASN1 :: [ASN1] -> Either String (FormattedKey PrivKeyEC, [ASN1]) Source #
Show a => Show (FormattedKey a) Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods showsPrec :: Int -> FormattedKey a -> ShowS Source # show :: FormattedKey a -> String Source # showList :: [FormattedKey a] -> ShowS Source #
Eq a => Eq (FormattedKey a) Source # |
Instance details Defined in Crypto.Store.PKCS8 Methods (==) :: FormattedKey a -> FormattedKey a -> Bool Source # (/=) :: FormattedKey a -> FormattedKey a -> Bool Source #

# Password-based protection

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

# Reading and writing PEM files

readPEMs :: FilePath -> IO [PEM] Source #

Read a PEM file from disk.

writePEMs :: FilePath -> [PEM] -> IO () Source #

Write a PEM file to disk.