certificate 1.0.1 → 1.1.0
raw patch · 5 files changed
+101/−54 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.Certificate.X509: ExtAuthorityKeyId :: ByteString -> Ext
- Data.Certificate.X509: ExtBasicConstraints :: Bool -> Ext
- Data.Certificate.X509: ExtKeyUsage :: [ExtKeyUsageFlag] -> Ext
- Data.Certificate.X509: ExtSubjectKeyId :: ByteString -> Ext
- Data.Certificate.X509: KeyUsage_cRLSign :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_dataEncipherment :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_decipherOnly :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_digitalSignature :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_encipherOnly :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_keyAgreement :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_keyCertSign :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_keyEncipherment :: ExtKeyUsageFlag
- Data.Certificate.X509: KeyUsage_nonRepudiation :: ExtKeyUsageFlag
- Data.Certificate.X509: data Ext
- Data.Certificate.X509: data ExtKeyUsageFlag
- Data.Certificate.X509: extDecode :: CertificateExt -> Maybe Ext
- Data.Certificate.X509: type CertificateExt = (OID, Bool, [ASN1])
- Data.Certificate.X509.Cert: type CertificateExt = (OID, Bool, [ASN1])
- Data.Certificate.X509.Ext: data Ext
- Data.Certificate.X509.Ext: instance Eq Ext
- Data.Certificate.X509.Ext: instance Show Ext
- Data.Certificate.X509.Ext: type CertificateExt = (OID, Bool, [ASN1])
+ Data.Certificate.X509.Ext: ExtSubjectAltName :: [String] -> ExtSubjectAltName
+ Data.Certificate.X509.Ext: class Extension a
+ Data.Certificate.X509.Ext: data ExtAuthorityKeyId
+ Data.Certificate.X509.Ext: data ExtBasicConstraints
+ Data.Certificate.X509.Ext: data ExtKeyUsage
+ Data.Certificate.X509.Ext: data ExtSubjectAltName
+ Data.Certificate.X509.Ext: data ExtSubjectKeyId
+ Data.Certificate.X509.Ext: extEncode :: Extension a => a -> [ASN1]
+ Data.Certificate.X509.Ext: extOID :: Extension a => a -> OID
+ Data.Certificate.X509.Ext: extensionGet :: Extension a => [ExtensionRaw] -> Maybe a
+ Data.Certificate.X509.Ext: instance Eq ExtAuthorityKeyId
+ Data.Certificate.X509.Ext: instance Eq ExtBasicConstraints
+ Data.Certificate.X509.Ext: instance Eq ExtKeyUsage
+ Data.Certificate.X509.Ext: instance Eq ExtSubjectAltName
+ Data.Certificate.X509.Ext: instance Eq ExtSubjectKeyId
+ Data.Certificate.X509.Ext: instance Extension ExtAuthorityKeyId
+ Data.Certificate.X509.Ext: instance Extension ExtBasicConstraints
+ Data.Certificate.X509.Ext: instance Extension ExtKeyUsage
+ Data.Certificate.X509.Ext: instance Extension ExtSubjectAltName
+ Data.Certificate.X509.Ext: instance Extension ExtSubjectKeyId
+ Data.Certificate.X509.Ext: instance Show ExtAuthorityKeyId
+ Data.Certificate.X509.Ext: instance Show ExtBasicConstraints
+ Data.Certificate.X509.Ext: instance Show ExtKeyUsage
+ Data.Certificate.X509.Ext: instance Show ExtSubjectAltName
+ Data.Certificate.X509.Ext: instance Show ExtSubjectKeyId
+ Data.Certificate.X509.Ext: type ExtensionRaw = (OID, Bool, [ASN1])
- Data.Certificate.X509: Certificate :: Int -> Integer -> SignatureALG -> [(OID, ASN1String)] -> [(OID, ASN1String)] -> (Time, Time) -> PubKey -> Maybe [CertificateExt] -> Certificate
+ Data.Certificate.X509: Certificate :: Int -> Integer -> SignatureALG -> [(OID, ASN1String)] -> [(OID, ASN1String)] -> (Time, Time) -> PubKey -> Maybe [ExtensionRaw] -> Certificate
- Data.Certificate.X509: certExtensions :: Certificate -> Maybe [CertificateExt]
+ Data.Certificate.X509: certExtensions :: Certificate -> Maybe [ExtensionRaw]
- Data.Certificate.X509.Cert: Certificate :: Int -> Integer -> SignatureALG -> [(OID, ASN1String)] -> [(OID, ASN1String)] -> (Time, Time) -> PubKey -> Maybe [CertificateExt] -> Certificate
+ Data.Certificate.X509.Cert: Certificate :: Int -> Integer -> SignatureALG -> [(OID, ASN1String)] -> [(OID, ASN1String)] -> (Time, Time) -> PubKey -> Maybe [ExtensionRaw] -> Certificate
- Data.Certificate.X509.Cert: certExtensions :: Certificate -> Maybe [CertificateExt]
+ Data.Certificate.X509.Cert: certExtensions :: Certificate -> Maybe [ExtensionRaw]
- Data.Certificate.X509.Ext: ExtAuthorityKeyId :: ByteString -> Ext
+ Data.Certificate.X509.Ext: ExtAuthorityKeyId :: ByteString -> ExtAuthorityKeyId
- Data.Certificate.X509.Ext: ExtBasicConstraints :: Bool -> Ext
+ Data.Certificate.X509.Ext: ExtBasicConstraints :: Bool -> ExtBasicConstraints
- Data.Certificate.X509.Ext: ExtKeyUsage :: [ExtKeyUsageFlag] -> Ext
+ Data.Certificate.X509.Ext: ExtKeyUsage :: [ExtKeyUsageFlag] -> ExtKeyUsage
- Data.Certificate.X509.Ext: ExtSubjectKeyId :: ByteString -> Ext
+ Data.Certificate.X509.Ext: ExtSubjectKeyId :: ByteString -> ExtSubjectKeyId
- Data.Certificate.X509.Ext: extDecode :: CertificateExt -> Maybe Ext
+ Data.Certificate.X509.Ext: extDecode :: Extension a => [ASN1] -> Either String a
Files
- Certificate.hs +14/−2
- Data/Certificate/X509.hs +1/−4
- Data/Certificate/X509/Cert.hs +6/−4
- Data/Certificate/X509/Ext.hs +79/−43
- certificate.cabal +1/−1
Certificate.hs view
@@ -36,8 +36,20 @@ showDN dn = mapM_ (\(oid, (_,t)) -> putStrLn (" " ++ show oid ++ ": " ++ t)) dn -showExts es = mapM_ (putStrLn . (" " ++) . showExt) es- where showExt e = maybe ("unknown: " ++ show e) show $ X509.extDecode e+showExts es = do+ mapM_ showExt es+ putStrLn "known extensions decoded: "+ showKnownExtension (X509.extensionGet es :: Maybe X509.ExtBasicConstraints)+ showKnownExtension (X509.extensionGet es :: Maybe X509.ExtKeyUsage)+ showKnownExtension (X509.extensionGet es :: Maybe X509.ExtSubjectKeyId)+ showKnownExtension (X509.extensionGet es :: Maybe X509.ExtSubjectAltName)+ showKnownExtension (X509.extensionGet es :: Maybe X509.ExtAuthorityKeyId)+ where+ showExt (oid,critical,asn1) = do+ putStrLn (" OID: " ++ show oid ++ " critical: " ++ show critical)+ putStrLn (" " ++ show asn1)+ showKnownExtension Nothing = return ()+ showKnownExtension (Just e) = putStrLn (" " ++ show e) showCert :: X509.X509 -> IO () showCert (X509.X509 cert _ _ sigalg sigbits) = do
Data/Certificate/X509.hs view
@@ -20,10 +20,7 @@ , ASN1StringType(..) , ASN1String , Certificate(..)- , CertificateExt- , Ext(..)- , ExtKeyUsageFlag(..)- , extDecode+ , module Data.Certificate.X509.Ext -- * helper for signing/veryfing certificate , getSigningData
Data/Certificate/X509/Cert.hs view
@@ -7,7 +7,6 @@ , PubKey(..) , ASN1StringType(..) , ASN1String- , CertificateExt , Certificate(..) -- various OID@@ -23,6 +22,9 @@ -- * certificate to/from asn1 , parseCertificate , encodeCertificateHeader++ -- * extensions+ , module Data.Certificate.X509.Ext ) where import Data.Word@@ -99,7 +101,7 @@ , certSubjectDN :: [ (OID, ASN1String) ] -- ^ Certificate Subject DN , certValidity :: (Time, Time) -- ^ Certificate Validity period , certPubKey :: PubKey -- ^ Certificate Public key- , certExtensions :: Maybe [CertificateExt] -- ^ Certificate Extensions+ , certExtensions :: Maybe [ExtensionRaw] -- ^ Certificate Extensions } deriving (Show,Eq) oidCommonName, oidCountry, oidOrganization, oidOrganizationUnit :: OID@@ -267,7 +269,7 @@ BitString bits -> return $ bitArrayGetData bits _ -> throwError "expecting bitstring" -parseCertExtensions :: ParseASN1 (Maybe [CertificateExt])+parseCertExtensions :: ParseASN1 (Maybe [ExtensionRaw]) parseCertExtensions = onNextContainerMaybe (Container Context 3) (sortByOID . mapMaybe extractExtension <$> onNextContainer Sequence getSequences) where sortByOID = sortBy (\(a,_,_) (b,_,_) -> a `compare` b)@@ -349,7 +351,7 @@ where pkalg = OID $ pubkeyalgOID $ pubkeyToAlg k -encodeExts :: Maybe [CertificateExt] -> [ASN1]+encodeExts :: Maybe [ExtensionRaw] -> [ASN1] encodeExts Nothing = [] encodeExts (Just l) = asn1Container (Container Context 3) $ concatMap encodeExt l where encodeExt (oid, critical, asn1) = case encodeASN1Stream asn1 of
Data/Certificate/X509/Ext.hs view
@@ -8,19 +8,27 @@ -- extension processing module. -- module Data.Certificate.X509.Ext- ( CertificateExt- , Ext(..)+ ( ExtensionRaw+ , Extension(..)+ -- * Common extension usually found in x509v3+ , ExtBasicConstraints(..)+ , ExtKeyUsage(..) , ExtKeyUsageFlag(..)- , extDecode+ , ExtSubjectKeyId(..)+ , ExtSubjectAltName(..)+ , ExtAuthorityKeyId(..)+ -- * Accessor turning extension into a specific one+ , extensionGet ) where import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC import qualified Data.ByteString.Lazy as L import Data.ASN1.DER import Data.ASN1.BitArray import Data.Certificate.X509.Internal -type CertificateExt = (OID, Bool, [ASN1])+type ExtensionRaw = (OID, Bool, [ASN1]) -- | key usage flag that is found in the key usage extension field. data ExtKeyUsageFlag =@@ -35,51 +43,79 @@ | KeyUsage_decipherOnly -- (8) deriving (Show,Eq,Ord,Enum) +{- -- RFC 5280-oidSubjectKeyId, oidKeyUsage, oidBasicConstraints, oidDistributionPoints,- oidPolicies, oidPoliciesMapping, oidAuthorityKeyId :: OID-oidSubjectKeyId = [2,5,29,14]-oidKeyUsage = [2,5,29,15]-oidBasicConstraints = [2,5,29,19]+oidDistributionPoints, oidPolicies, oidPoliciesMapping :: OID oidDistributionPoints = [2,5,29,31] oidPolicies = [2,5,29,32] oidPoliciesMapping = [2,5,29,33]-oidAuthorityKeyId = [2,5,29,35]+-} --- | known X509v3 extensions-data Ext =- ExtBasicConstraints Bool- | ExtKeyUsage [ExtKeyUsageFlag]- | ExtSubjectKeyId L.ByteString- | ExtAuthorityKeyId B.ByteString+class Extension a where+ extOID :: a -> OID+ extEncode :: a -> [ASN1]+ extDecode :: [ASN1] -> Either String a++extensionGet :: Extension a => [ExtensionRaw] -> Maybe a+extensionGet [] = Nothing+extensionGet ((oid,_,asn1):xs) = case extDecode asn1 of+ Right b+ | oid == extOID b -> Just b+ | otherwise -> extensionGet xs+ Left _ -> extensionGet xs++data ExtBasicConstraints = ExtBasicConstraints Bool deriving (Show,Eq) --- | try decoding a certificateExt tuple into a known extension.-extDecode :: CertificateExt -> Maybe Ext-extDecode (oid, _, asn1)- | oid == oidBasicConstraints = decodeBasicConstraints asn1- | oid == oidSubjectKeyId = decodeSubjectKeyId asn1- | oid == oidAuthorityKeyId = decodeAuthorityKeyId asn1- | oid == oidKeyUsage = decodeKeyUsage asn1- | otherwise = Nothing- where- -- basic constraints- decodeBasicConstraints [Start Sequence,Boolean b,End Sequence] =- Just (ExtBasicConstraints b)- decodeBasicConstraints _ = Nothing- -- subject key id- decodeSubjectKeyId [OctetString o] =- Just (ExtSubjectKeyId o)- decodeSubjectKeyId _ = Nothing- -- key usage- decodeKeyUsage [BitString bits] = Just $ ExtKeyUsage $ bitsToFlags bits- decodeKeyUsage _ = Nothing+instance Extension ExtBasicConstraints where+ extOID = const [2,5,29,19]+ extEncode (ExtBasicConstraints b) = [Start Sequence,Boolean b,End Sequence]+ extDecode [Start Sequence,Boolean b,End Sequence] = Right (ExtBasicConstraints b)+ extDecode [Start Sequence,End Sequence] = Right (ExtBasicConstraints False)+ extDecode _ = Left "unknown sequence" - decodeAuthorityKeyId [Start Sequence,Other Context 0 keyid,End Sequence] = Just $ ExtAuthorityKeyId keyid- decodeAuthorityKeyId _ = Nothing+data ExtKeyUsage = ExtKeyUsage [ExtKeyUsageFlag]+ deriving (Show,Eq) - bitsToFlags bits =- let nb = bitArrayLength bits in- concat $ flip map [0..(nb-1)] $ \i -> do- let isSet = bitArrayGetBit bits i- if isSet then [toEnum $ fromIntegral i] else []+instance Extension ExtKeyUsage where+ extOID = const [2,5,29,15]+ extEncode (ExtKeyUsage _) = undefined+ extDecode [BitString bits] = Right $ ExtKeyUsage $ bitsToFlags bits+ extDecode _ = Left "unknown sequence"++data ExtSubjectKeyId = ExtSubjectKeyId L.ByteString+ deriving (Show,Eq)++instance Extension ExtSubjectKeyId where+ extOID = const [2,5,29,14]+ extEncode (ExtSubjectKeyId _) = undefined+ extDecode [OctetString o] = Right $ ExtSubjectKeyId o+ extDecode _ = Left "unknown sequence"++data ExtSubjectAltName = ExtSubjectAltName [String]+ deriving (Show,Eq)++instance Extension ExtSubjectAltName where+ extOID = const [2,5,29,17]+ extEncode (ExtSubjectAltName _) = undefined+ extDecode l = runParseASN1 parse l where+ parse = do+ c <- getNextContainer Sequence+ return $ ExtSubjectAltName $ map toStringy c+ toStringy (Other Context 2 b) = BC.unpack b+ toStringy b = error ("not coping with anything else " ++ show b)++data ExtAuthorityKeyId = ExtAuthorityKeyId B.ByteString+ deriving (Show,Eq)++instance Extension ExtAuthorityKeyId where+ extOID _ = [2,5,29,35]+ extEncode (ExtAuthorityKeyId _) = undefined+ extDecode [Start Sequence,Other Context 0 keyid,End Sequence] =+ Right $ ExtAuthorityKeyId keyid+ extDecode _ = Left "unknown sequence"++bitsToFlags :: Enum a => BitArray -> [a]+bitsToFlags bits = concat $ flip map [0..(bitArrayLength bits-1)] $ \i -> do+ let isSet = bitArrayGetBit bits i+ if isSet then [toEnum $ fromIntegral i] else []
certificate.cabal view
@@ -1,5 +1,5 @@ Name: certificate-Version: 1.0.1+Version: 1.1.0 Description: Certificates and Key reader/writer .