-- | -- Module : Network.TLS.Extra.File -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unknown -- -- Simple helpers to load private key and certificate files -- to be handled by the TLS stack module Network.TLS.Extra.File ( fileReadCertificate , fileReadPrivateKey ) where import Control.Applicative ((<$>)) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Data.Either import Data.PEM (PEM(..), pemParseBS) import Data.Certificate.X509 import qualified Data.Certificate.KeyRSA as KeyRSA import Network.TLS -- | read one X509 certificate from a file. -- -- the certificate must be in the usual PEM format with the -- TRUSTED CERTIFICATE or CERTIFICATE pem name. -- -- If no valid PEM encoded certificate is found in the file -- this function will raise an error. fileReadCertificate :: FilePath -> IO X509 fileReadCertificate filepath = do certs <- rights . parseCerts . pemParseBS <$> B.readFile filepath case certs of [] -> error "no valid certificate found" (x:_) -> return x where parseCerts (Right pems) = map (decodeCertificate . L.fromChunks . (:[]) . pemContent) $ filter (flip elem ["CERTIFICATE", "TRUSTED CERTIFICATE"] . pemName) pems parseCerts (Left err) = error ("cannot parse PEM file " ++ show err) -- | read one private key from a file. -- -- the private key must be in the usual PEM format and at the moment only -- RSA PRIVATE KEY are supported. -- -- If no valid PEM encoded private key is found in the file -- this function will raise an error. fileReadPrivateKey :: FilePath -> IO PrivateKey fileReadPrivateKey filepath = do pk <- rights . parseKey . pemParseBS <$> B.readFile filepath case pk of [] -> error "no valid RSA key found" (x:_) -> return x where parseKey (Right pems) = map (fmap (PrivRSA . snd) . KeyRSA.decodePrivate . L.fromChunks . (:[]) . pemContent) $ filter ((== "RSA PRIVATE KEY") . pemName) pems parseKey (Left err) = error ("Cannot parse PEM file " ++ show err)