1-- | 2-- Module : Data.X509 3-- License : BSD-style 4-- Maintainer : Vincent Hanquez <vincent@snarc.org> 5-- Stability : experimental 6-- Portability : unknown 7-- 8-- Read/Write X509 Certificate, CRL and their signed equivalents. 9-- 10-- Follows RFC5280 / RFC6818 11-- 12module Data.X509 13 ( 14 -- * Types 15 SignedCertificate 16 , SignedCRL 17 , Certificate(..) 18 , PubKey(..) 19 , PubKeyEC(..) 20 , SerializedPoint(..) 21 , PrivKey(..) 22 , PrivKeyEC(..) 23 , pubkeyToAlg 24 , privkeyToAlg 25 , module Data.X509.AlgorithmIdentifier 26 , module Data.X509.Ext 27 , module Data.X509.ExtensionRaw 28 29 -- * Certificate Revocation List (CRL) 30 , module Data.X509.CRL 31 32 -- * Naming 33 , DistinguishedName(..) 34 , DnElement(..) 35 , ASN1CharacterString(..) 36 , getDnElement 37 38 -- * Certificate Chain 39 , module Data.X509.CertificateChain 40 41 -- * Signed types and marshalling 42 , Signed(..) 43 , SignedExact 44 , getSigned 45 , getSignedData 46 , objectToSignedExact 47 , objectToSignedExactF 48 , encodeSignedObject 49 , decodeSignedObject 50 51 -- * Parametrized Signed accessor 52 , getCertificate 53 , getCRL 54 , decodeSignedCertificate 55 , decodeSignedCRL 56 57 -- * Hash distinguished names related function 58 , hashDN 59 , hashDN_old 60 ) where 61 62import Control.Arrow (second) 63 64import Data.ASN1.Types 65import Data.ASN1.Encoding 66import Data.ASN1.BinaryEncoding 67import qualified Data.ByteString as B 68import qualified Data.ByteArray as BA 69 70import Data.X509.Cert 71import Data.X509.Ext 72import Data.X509.ExtensionRaw 73import Data.X509.CRL 74import Data.X509.CertificateChain 75import Data.X509.DistinguishedName 76import Data.X509.Signed 77import Data.X509.PublicKey 78import Data.X509.PrivateKey 79import Data.X509.AlgorithmIdentifier 80 81import Crypto.Hash 82 83-- | A Signed Certificate 84type SignedCertificate = SignedExact Certificate 85 86-- | A Signed CRL 87type SignedCRL = SignedExact CRL 88 89-- | Get the Certificate associated to a SignedCertificate 90getCertificate :: SignedCertificate -> Certificate 91getCertificate = signedObject . getSigned 92 93-- | Get the CRL associated to a SignedCRL 94getCRL :: SignedCRL -> CRL 95getCRL = signedObject . getSigned 96 97-- | Try to decode a bytestring to a SignedCertificate 98decodeSignedCertificate :: B.ByteString -> Either String SignedCertificate 99decodeSignedCertificate = decodeSignedObject 100 101-- | Try to decode a bytestring to a SignedCRL 102decodeSignedCRL :: B.ByteString -> Either String SignedCRL 103decodeSignedCRL = decodeSignedObject 104 105-- | Make an OpenSSL style hash of distinguished name 106-- 107-- OpenSSL algorithm is odd, and has been replicated here somewhat. 108-- only lower the case of ascii character. 109hashDN :: DistinguishedName -> B.ByteString 110hashDN = shorten . hashWith SHA1 . encodeASN1' DER . flip toASN1 [] . DistinguishedNameInner . dnLowerUTF8 111 where dnLowerUTF8 (DistinguishedName l) = DistinguishedName $ map (second toLowerUTF8) l 112 toLowerUTF8 (ASN1CharacterString _ s) = ASN1CharacterString UTF8 (B.map asciiToLower s) 113 asciiToLower c 114 | c >= w8A && c <= w8Z = fromIntegral (fromIntegral c - fromEnum 'A' + fromEnum 'a') 115 | otherwise = c 116 w8A = fromIntegral $ fromEnum 'A' 117 w8Z = fromIntegral $ fromEnum 'Z' 118 119-- | Create an openssl style old hash of distinguished name 120hashDN_old :: DistinguishedName -> B.ByteString 121hashDN_old = shorten . hashWith MD5 . encodeASN1' DER . flip toASN1 [] 122 123shorten :: Digest a -> B.ByteString 124shorten b = B.pack $ map i [3,2,1,0] 125 where i n = BA.index b n 126