x509 1.7.0 → 1.7.1
raw patch · 3 files changed
+68/−25 lines, 3 filesdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.X509: [extRawASN1] :: ExtensionRaw -> [ASN1]
+ Data.X509: ExtNetscapeComment :: ByteString -> ExtNetscapeComment
+ Data.X509: [extRawContent] :: ExtensionRaw -> ByteString
+ Data.X509: data ExtNetscapeComment
+ Data.X509: extDecodeBs :: Extension a => ByteString -> Either String a
+ Data.X509: extEncodeBs :: Extension a => a -> ByteString
+ Data.X509: extHasNestedASN1 :: Extension a => Proxy a -> Bool
+ Data.X509: extRawASN1 :: ExtensionRaw -> [ASN1]
+ Data.X509: tryExtRawASN1 :: ExtensionRaw -> Either String [ASN1]
- Data.X509: ExtensionRaw :: OID -> Bool -> [ASN1] -> ExtensionRaw
+ Data.X509: ExtensionRaw :: OID -> Bool -> ByteString -> ExtensionRaw
- Data.X509: class Extension a
+ Data.X509: class Extension a where extDecodeBs = (either (Left . show) Right . decodeASN1' BER) >=> extDecode extEncodeBs = encodeASN1' DER . extEncode
- Data.X509: extensionDecode :: Extension a => ExtensionRaw -> Maybe (Either String a)
+ Data.X509: extensionDecode :: forall a. Extension a => ExtensionRaw -> Maybe (Either String a)
- Data.X509: extensionEncode :: Extension a => Bool -> a -> ExtensionRaw
+ Data.X509: extensionEncode :: forall a. Extension a => Bool -> a -> ExtensionRaw
Files
- Data/X509/Ext.hs +49/−12
- Data/X509/ExtensionRaw.hs +18/−12
- x509.cabal +1/−1
Data/X509/Ext.hs view
@@ -8,7 +8,7 @@ -- extension processing module. -- {-# LANGUAGE FlexibleContexts #-}-+{-# LANGUAGE ScopedTypeVariables #-} module Data.X509.Ext ( Extension(..) -- * Common extension usually found in x509v3@@ -21,6 +21,7 @@ , ExtSubjectAltName(..) , ExtAuthorityKeyId(..) , ExtCrlDistributionPoints(..)+ , ExtNetscapeComment(..) , AltName(..) , DistributionPoint(..) , ReasonFlag(..)@@ -35,11 +36,15 @@ import qualified Data.ByteString.Char8 as BC import Data.ASN1.Types import Data.ASN1.Parse+import Data.ASN1.Encoding+import Data.ASN1.BinaryEncoding import Data.ASN1.BitArray+import Data.Proxy import Data.List (find) import Data.X509.ExtensionRaw import Data.X509.DistinguishedName import Control.Applicative+import Control.Monad -- | key usage flag that is found in the key usage extension field. data ExtKeyUsageFlag =@@ -65,11 +70,24 @@ -- -- each extension have a unique OID associated, and a way -- to encode and decode an ASN1 stream.+--+-- Errata: turns out, the content is not necessarily ASN1,+-- it could be data that is only parsable by the extension+-- e.g. raw ascii string. Add method to parse and encode with+-- ByteString class Extension a where- extOID :: a -> OID- extEncode :: a -> [ASN1]- extDecode :: [ASN1] -> Either String a+ extOID :: a -> OID+ extHasNestedASN1 :: Proxy a -> Bool+ extEncode :: a -> [ASN1]+ extDecode :: [ASN1] -> Either String a + extDecodeBs :: B.ByteString -> Either String a+ extDecodeBs = (either (Left . show) Right . decodeASN1' BER) >=> extDecode++ extEncodeBs :: a -> B.ByteString+ extEncodeBs = encodeASN1' DER . extEncode++ -- | Get a specific extension from a lists of raw extensions extensionGet :: Extension a => Extensions -> Maybe a extensionGet (Extensions Nothing) = Nothing@@ -94,16 +112,17 @@ -- * Nothing, the OID doesn't match -- * Just Left, the OID matched, but the extension couldn't be decoded -- * Just Right, the OID matched, and the extension has been succesfully decoded-extensionDecode :: Extension a => ExtensionRaw -> Maybe (Either String a)-extensionDecode = doDecode undefined- where doDecode :: Extension a => a -> ExtensionRaw -> Maybe (Either String a)- doDecode dummy (ExtensionRaw oid _ asn1)- | extOID dummy == oid = Just (extDecode asn1)- | otherwise = Nothing+extensionDecode :: forall a . Extension a => ExtensionRaw -> Maybe (Either String a)+extensionDecode er@(ExtensionRaw oid _ content)+ | extOID (undefined :: a) /= oid = Nothing+ | extHasNestedASN1 (Proxy :: Proxy a) = Just (tryExtRawASN1 er >>= extDecode)+ | otherwise = Just (extDecodeBs content) -- | Encode an Extension to extensionRaw-extensionEncode :: Extension a => Bool -> a -> ExtensionRaw-extensionEncode critical ext = ExtensionRaw (extOID ext) critical (extEncode ext)+extensionEncode :: forall a . Extension a => Bool -> a -> ExtensionRaw+extensionEncode critical ext+ | extHasNestedASN1 (Proxy :: Proxy a) = ExtensionRaw (extOID ext) critical (encodeASN1' DER $ extEncode ext)+ | otherwise = ExtensionRaw (extOID ext) critical (extEncodeBs ext) -- | Basic Constraints data ExtBasicConstraints = ExtBasicConstraints Bool (Maybe Integer)@@ -111,6 +130,7 @@ instance Extension ExtBasicConstraints where extOID = const [2,5,29,19]+ extHasNestedASN1 = const True extEncode (ExtBasicConstraints b Nothing) = [Start Sequence,Boolean b,End Sequence] extEncode (ExtBasicConstraints b (Just i)) = [Start Sequence,Boolean b,IntVal i,End Sequence] @@ -127,6 +147,7 @@ instance Extension ExtKeyUsage where extOID = const [2,5,29,15]+ extHasNestedASN1 = const True extEncode (ExtKeyUsage flags) = [BitString $ flagsToBits flags] extDecode [BitString bits] = Right $ ExtKeyUsage $ bitsToFlags bits extDecode _ = Left "unknown sequence"@@ -158,6 +179,7 @@ instance Extension ExtExtendedKeyUsage where extOID = const [2,5,29,37]+ extHasNestedASN1 = const True extEncode (ExtExtendedKeyUsage purposes) = [Start Sequence] ++ map (OID . lookupRev) purposes ++ [End Sequence] where lookupRev (KeyUsagePurpose_Unknown oid) = oid@@ -174,6 +196,7 @@ instance Extension ExtSubjectKeyId where extOID = const [2,5,29,14]+ extHasNestedASN1 = const True extEncode (ExtSubjectKeyId o) = [OctetString o] extDecode [OctetString o] = Right $ ExtSubjectKeyId o extDecode _ = Left "unknown sequence"@@ -203,6 +226,7 @@ instance Extension ExtSubjectAltName where extOID = const [2,5,29,17]+ extHasNestedASN1 = const True extEncode (ExtSubjectAltName names) = encodeGeneralNames names extDecode l = runParseASN1 (ExtSubjectAltName <$> parseGeneralNames) l @@ -213,6 +237,7 @@ instance Extension ExtAuthorityKeyId where extOID _ = [2,5,29,35]+ extHasNestedASN1 = const True extEncode (ExtAuthorityKeyId keyid) = [Start Sequence,Other Context 0 keyid,End Sequence] extDecode [Start Sequence,Other Context 0 keyid,End Sequence] =@@ -244,6 +269,7 @@ instance Extension ExtCrlDistributionPoints where extOID _ = [2,5,29,31]+ extHasNestedASN1 = const True extEncode = error "extEncode ExtCrlDistributionPoints unimplemented" extDecode = error "extDecode ExtCrlDistributionPoints unimplemented" --extEncode (ExtCrlDistributionPoints )@@ -311,3 +337,14 @@ flagsToBits :: Enum a => [a] -> BitArray flagsToBits flags = foldl bitArraySetBit bitArrayEmpty $ map (fromIntegral . fromEnum) flags where bitArrayEmpty = toBitArray (B.pack [0,0]) 7++data ExtNetscapeComment = ExtNetscapeComment B.ByteString+ deriving (Show,Eq)++instance Extension ExtNetscapeComment where+ extOID _ = [2,16,840,1,113730,1,13]+ extHasNestedASN1 = const False+ extEncode = error "Extension: Netscape Comment do not contain nested ASN1"+ extDecode = error "Extension: Netscape Comment do not contain nested ASN1"+ extEncodeBs (ExtNetscapeComment b) = b+ extDecodeBs = Right . ExtNetscapeComment
Data/X509/ExtensionRaw.hs view
@@ -9,6 +9,8 @@ -- module Data.X509.ExtensionRaw ( ExtensionRaw(..)+ , tryExtRawASN1+ , extRawASN1 , Extensions(..) ) where @@ -17,14 +19,25 @@ import Data.ASN1.Encoding import Data.ASN1.BinaryEncoding import Data.X509.Internal+import qualified Data.ByteString as B -- | An undecoded extension data ExtensionRaw = ExtensionRaw { extRawOID :: OID -- ^ OID of this extension , extRawCritical :: Bool -- ^ if this extension is critical- , extRawASN1 :: [ASN1] -- ^ the associated ASN1+ , extRawContent :: B.ByteString -- ^ undecoded content } deriving (Show,Eq) +tryExtRawASN1 :: ExtensionRaw -> Either String [ASN1]+tryExtRawASN1 (ExtensionRaw oid _ content) =+ case decodeASN1' BER content of+ Left err -> Left $ "fromASN1: X509.ExtensionRaw: OID=" ++ show oid ++ ": cannot decode data: " ++ show err+ Right r -> Right r++extRawASN1 :: ExtensionRaw -> [ASN1]+extRawASN1 extRaw = either error id $ tryExtRawASN1 extRaw+{-# DEPRECATED extRawASN1 "use tryExtRawASN1 instead" #-}+ -- | a Set of 'ExtensionRaw' newtype Extensions = Extensions (Maybe [ExtensionRaw]) deriving (Show,Eq)@@ -41,19 +54,12 @@ toASN1 extraw = \xs -> encodeExt extraw ++ xs fromASN1 (Start Sequence:OID oid:xs) = case xs of- Boolean b:OctetString obj:End Sequence:xs2 -> extractExt b obj xs2- OctetString obj:End Sequence:xs2 -> extractExt False obj xs2+ Boolean b:OctetString obj:End Sequence:xs2 -> Right (ExtensionRaw oid b obj, xs2)+ OctetString obj:End Sequence:xs2 -> Right (ExtensionRaw oid False obj, xs2) _ -> Left ("fromASN1: X509.ExtensionRaw: unknown format:" ++ show xs)- where- extractExt critical bs remainingStream =- case decodeASN1' BER bs of- Left err -> Left ("fromASN1: X509.ExtensionRaw: OID=" ++ show oid ++- ": cannot decode data: " ++ show err)- Right r -> Right (ExtensionRaw oid critical r, remainingStream) fromASN1 l = Left ("fromASN1: X509.ExtensionRaw: unknown format:" ++ show l) encodeExt :: ExtensionRaw -> [ASN1]-encodeExt (ExtensionRaw oid critical asn1) =- let bs = encodeASN1' DER asn1- in asn1Container Sequence ([OID oid] ++ (if critical then [Boolean True] else []) ++ [OctetString bs])+encodeExt (ExtensionRaw oid critical content) =+ asn1Container Sequence ([OID oid] ++ (if critical then [Boolean True] else []) ++ [OctetString content])
x509.cabal view
@@ -1,5 +1,5 @@ Name: x509-version: 1.7.0+version: 1.7.1 Description: X509 reader and writer License: BSD3 License-file: LICENSE