module Data.X509.File
    ( readSignedObject
    , readKeyFile
    ) where

import Control.Applicative
import Data.ASN1.Types
import Data.ASN1.BinaryEncoding
import Data.ASN1.Encoding
import Data.Maybe
import qualified Data.X509 as X509
import           Data.X509.Memory (pemToKey)
import Data.PEM (pemParseLBS, pemContent, pemName, PEM)
import qualified Data.ByteString.Lazy as L

readPEMs :: FilePath -> IO [PEM]
readPEMs :: FilePath -> IO [PEM]
readPEMs FilePath
filepath = do
    ByteString
content <- FilePath -> IO ByteString
L.readFile FilePath
filepath
    [PEM] -> IO [PEM]
forall (m :: * -> *) a. Monad m => a -> m a
return ([PEM] -> IO [PEM]) -> [PEM] -> IO [PEM]
forall a b. (a -> b) -> a -> b
$ (FilePath -> [PEM])
-> ([PEM] -> [PEM]) -> Either FilePath [PEM] -> [PEM]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either FilePath -> [PEM]
forall a. HasCallStack => FilePath -> a
error [PEM] -> [PEM]
forall a. a -> a
id (Either FilePath [PEM] -> [PEM]) -> Either FilePath [PEM] -> [PEM]
forall a b. (a -> b) -> a -> b
$ ByteString -> Either FilePath [PEM]
pemParseLBS ByteString
content

-- | return all the signed objects in a file.
--
-- (only one type at a time).
readSignedObject :: (ASN1Object a, Eq a, Show a)
                 => FilePath
                 -> IO [X509.SignedExact a]
readSignedObject :: FilePath -> IO [SignedExact a]
readSignedObject FilePath
filepath = [PEM] -> [SignedExact a]
forall a. (Show a, Eq a, ASN1Object a) => [PEM] -> [SignedExact a]
decodePEMs ([PEM] -> [SignedExact a]) -> IO [PEM] -> IO [SignedExact a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO [PEM]
readPEMs FilePath
filepath
  where decodePEMs :: [PEM] -> [SignedExact a]
decodePEMs [PEM]
pems =
          [ SignedExact a
obj | PEM
pem <- [PEM]
pems, Right SignedExact a
obj <- [ByteString -> Either FilePath (SignedExact a)
forall a.
(Show a, Eq a, ASN1Object a) =>
ByteString -> Either FilePath (SignedExact a)
X509.decodeSignedObject (ByteString -> Either FilePath (SignedExact a))
-> ByteString -> Either FilePath (SignedExact a)
forall a b. (a -> b) -> a -> b
$ PEM -> ByteString
pemContent PEM
pem] ]

-- | return all the private keys that were successfully read from a file.
readKeyFile :: FilePath -> IO [X509.PrivKey]
readKeyFile :: FilePath -> IO [PrivKey]
readKeyFile FilePath
path = [Maybe PrivKey] -> [PrivKey]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe PrivKey] -> [PrivKey])
-> ([PEM] -> [Maybe PrivKey]) -> [PEM] -> [PrivKey]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Maybe PrivKey] -> PEM -> [Maybe PrivKey])
-> [Maybe PrivKey] -> [PEM] -> [Maybe PrivKey]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl [Maybe PrivKey] -> PEM -> [Maybe PrivKey]
pemToKey [] ([PEM] -> [PrivKey]) -> IO [PEM] -> IO [PrivKey]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO [PEM]
readPEMs FilePath
path