x509 1.7.1 → 1.7.2
raw patch · 6 files changed
+160/−5 lines, 6 filesdep ~cryptonite
Dependency ranges changed: cryptonite
Files
- Data/X509.hs +1/−0
- Data/X509/AlgorithmIdentifier.hs +2/−0
- Data/X509/Cert.hs +1/−1
- Data/X509/EC.hs +126/−0
- Data/X509/PrivateKey.hs +27/−2
- x509.cabal +3/−2
Data/X509.hs view
@@ -19,6 +19,7 @@ , PubKeyEC(..) , SerializedPoint(..) , PrivKey(..)+ , PrivKeyEC(..) , pubkeyToAlg , privkeyToAlg , module Data.X509.AlgorithmIdentifier
Data/X509/AlgorithmIdentifier.hs view
@@ -95,6 +95,8 @@ Right (oidSig oid, xs) fromASN1 (Start Sequence:OID [1,2,840,113549,1,1,10]:Start Sequence:Start _:Start Sequence:OID hash1:End Sequence:End _:Start _:Start Sequence:OID [1,2,840,113549,1,1,8]:Start Sequence:OID _hash2:End Sequence:End Sequence:End _:Start _: IntVal _iv: End _: End Sequence : End Sequence:xs) = Right (oidSig hash1, xs)+ fromASN1 (Start Sequence:OID [1,2,840,113549,1,1,10]:Start Sequence:Start _:Start Sequence:OID hash1:Null:End Sequence:End _:Start _:Start Sequence:OID [1,2,840,113549,1,1,8]:Start Sequence:OID _hash2:Null:End Sequence:End Sequence:End _:Start _: IntVal _iv: End _: End Sequence : End Sequence:xs) =+ Right (oidSig hash1, xs) fromASN1 _ = Left "fromASN1: X509.SignatureALG: unknown format" toASN1 signatureAlg@(SignatureALG hashAlg PubKeyALG_RSAPSS) = \xs -> Start Sequence:OID [1,2,840,113549,1,1,10]:Start Sequence:Start (Container Context 0):Start Sequence:OID (sigOID signatureAlg):End Sequence:End (Container Context 0):Start (Container Context 1): Start Sequence:OID [1,2,840,113549,1,1,8]:Start Sequence:OID (sigOID signatureAlg):End Sequence:End Sequence:End (Container Context 1):Start (Container Context 2):IntVal (saltLen hashAlg):End (Container Context 2):End Sequence:End Sequence:xs
Data/X509/Cert.hs view
@@ -53,7 +53,7 @@ parseCertHeaderVersion :: ParseASN1 Int parseCertHeaderVersion =- maybe 1 id <$> onNextContainerMaybe (Container Context 0) (getNext >>= getVer)+ maybe 0 id <$> onNextContainerMaybe (Container Context 0) (getNext >>= getVer) where getVer (IntVal v) = return $ fromIntegral v getVer _ = throwParseError "unexpected type for version"
+ Data/X509/EC.hs view
@@ -0,0 +1,126 @@+-- |+-- Module : Data.X509.EC+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : unknown+--+-- Utilities related to Elliptic Curve certificates and keys.+--+module Data.X509.EC+ (+ unserializePoint+ , ecPubKeyCurve+ , ecPubKeyCurveName+ , ecPrivKeyCurve+ , ecPrivKeyCurveName+ , lookupCurveNameByOID+ ) where++import Data.ASN1.OID+import Data.List (find)++import Data.X509.OID+import Data.X509.PublicKey+import Data.X509.PrivateKey++import qualified Crypto.PubKey.ECC.Prim as ECC+import qualified Crypto.PubKey.ECC.Types as ECC+import Crypto.Number.Serialize (os2ip)++import qualified Data.ByteString as B++-- | Read an EC point from a serialized format and make sure the point is+-- valid for the specified curve.+unserializePoint :: ECC.Curve -> SerializedPoint -> Maybe ECC.Point+unserializePoint curve (SerializedPoint bs) =+ case B.uncons bs of+ Nothing -> Nothing+ Just (ptFormat, input) ->+ case ptFormat of+ 4 -> if B.length input /= 2 * bytes+ then Nothing+ else+ let (x, y) = B.splitAt bytes input+ p = ECC.Point (os2ip x) (os2ip y)+ in if ECC.isPointValid curve p+ then Just p+ else Nothing+ -- 2 and 3 for compressed format.+ _ -> Nothing+ where bits = ECC.curveSizeBits curve+ bytes = (bits + 7) `div` 8++-- | Return the curve associated to an EC Public Key. This does not check+-- if a curve in explicit format is valid: if the input is not trusted one+-- should consider 'ecPubKeyCurveName' instead.+ecPubKeyCurve :: PubKeyEC -> Maybe ECC.Curve+ecPubKeyCurve (PubKeyEC_Named name _) = Just $ ECC.getCurveByName name+ecPubKeyCurve pub@PubKeyEC_Prime{} =+ fmap buildCurve $+ unserializePoint (buildCurve undefined) (pubkeyEC_generator pub)+ where+ prime = pubkeyEC_prime pub+ buildCurve g =+ let cc = ECC.CurveCommon+ { ECC.ecc_a = pubkeyEC_a pub+ , ECC.ecc_b = pubkeyEC_b pub+ , ECC.ecc_g = g+ , ECC.ecc_n = pubkeyEC_order pub+ , ECC.ecc_h = pubkeyEC_cofactor pub+ }+ in ECC.CurveFP (ECC.CurvePrime prime cc)++-- | Return the name of a standard curve associated to an EC Public Key+ecPubKeyCurveName :: PubKeyEC -> Maybe ECC.CurveName+ecPubKeyCurveName (PubKeyEC_Named name _) = Just name+ecPubKeyCurveName pub@PubKeyEC_Prime{} =+ find matchPrimeCurve $ enumFrom $ toEnum 0+ where+ matchPrimeCurve c =+ case ECC.getCurveByName c of+ ECC.CurveFP (ECC.CurvePrime p cc) ->+ ECC.ecc_a cc == pubkeyEC_a pub &&+ ECC.ecc_b cc == pubkeyEC_b pub &&+ ECC.ecc_n cc == pubkeyEC_order pub &&+ p == pubkeyEC_prime pub+ _ -> False++-- | Return the EC curve associated to an EC Private Key. This does not check+-- if a curve in explicit format is valid: if the input is not trusted one+-- should consider 'ecPrivKeyCurveName' instead.+ecPrivKeyCurve :: PrivKeyEC -> Maybe ECC.Curve+ecPrivKeyCurve (PrivKeyEC_Named name _) = Just $ ECC.getCurveByName name+ecPrivKeyCurve priv@PrivKeyEC_Prime{} =+ fmap buildCurve $+ unserializePoint (buildCurve undefined) (privkeyEC_generator priv)+ where+ prime = privkeyEC_prime priv+ buildCurve g =+ let cc = ECC.CurveCommon+ { ECC.ecc_a = privkeyEC_a priv+ , ECC.ecc_b = privkeyEC_b priv+ , ECC.ecc_g = g+ , ECC.ecc_n = privkeyEC_order priv+ , ECC.ecc_h = privkeyEC_cofactor priv+ }+ in ECC.CurveFP (ECC.CurvePrime prime cc)++-- | Return the name of a standard curve associated to an EC Private Key+ecPrivKeyCurveName :: PrivKeyEC -> Maybe ECC.CurveName+ecPrivKeyCurveName (PrivKeyEC_Named name _) = Just name+ecPrivKeyCurveName priv@PrivKeyEC_Prime{} =+ find matchPrimeCurve $ enumFrom $ toEnum 0+ where+ matchPrimeCurve c =+ case ECC.getCurveByName c of+ ECC.CurveFP (ECC.CurvePrime p cc) ->+ ECC.ecc_a cc == privkeyEC_a priv &&+ ECC.ecc_b cc == privkeyEC_b priv &&+ ECC.ecc_n cc == privkeyEC_order priv &&+ p == privkeyEC_prime priv+ _ -> False++-- | Return the curve name associated to an OID+lookupCurveNameByOID :: OID -> Maybe ECC.CurveName+lookupCurveNameByOID = lookupByOID curvesOIDTable
Data/X509/PrivateKey.hs view
@@ -5,25 +5,50 @@ -- Stability : experimental -- Portability : unknown ----- Public key handling in X.509 infrastructure+-- Private key handling in X.509 infrastructure -- module Data.X509.PrivateKey ( PrivKey(..)+ , PrivKeyEC(..) , privkeyToAlg ) where import Data.X509.AlgorithmIdentifier+import Data.X509.PublicKey (SerializedPoint(..)) import qualified Crypto.PubKey.RSA as RSA import qualified Crypto.PubKey.DSA as DSA+import qualified Crypto.PubKey.ECC.Types as ECC +-- | Elliptic Curve Private Key+--+-- TODO: missing support for binary curve.+data PrivKeyEC =+ PrivKeyEC_Prime+ { privkeyEC_priv :: Integer+ , privkeyEC_a :: Integer+ , privkeyEC_b :: Integer+ , privkeyEC_prime :: Integer+ , privkeyEC_generator :: SerializedPoint+ , privkeyEC_order :: Integer+ , privkeyEC_cofactor :: Integer+ , privkeyEC_seed :: Integer+ }+ | PrivKeyEC_Named+ { privkeyEC_name :: ECC.CurveName+ , privkeyEC_priv :: Integer+ }+ deriving (Show,Eq)+ -- | Private key types known and used in X.509 data PrivKey = PrivKeyRSA RSA.PrivateKey -- ^ RSA private key | PrivKeyDSA DSA.PrivateKey -- ^ DSA private key+ | PrivKeyEC PrivKeyEC -- ^ EC private key deriving (Show,Eq) --- | Convert a Public key to the Public Key Algorithm type+-- | Convert a Private key to the Public Key Algorithm type privkeyToAlg :: PrivKey -> PubKeyALG privkeyToAlg (PrivKeyRSA _) = PubKeyALG_RSA privkeyToAlg (PrivKeyDSA _) = PubKeyALG_DSA+privkeyToAlg (PrivKeyEC _) = PubKeyALG_EC
x509.cabal view
@@ -1,5 +1,5 @@ Name: x509-version: 1.7.1+version: 1.7.2 Description: X509 reader and writer License: BSD3 License-file: LICENSE@@ -25,8 +25,9 @@ , asn1-types >= 0.3.1 && < 0.4 , asn1-encoding >= 0.9 && < 0.10 , asn1-parse >= 0.9.3 && < 0.10- , cryptonite+ , cryptonite >= 0.8 Exposed-modules: Data.X509+ Data.X509.EC Other-modules: Data.X509.Internal Data.X509.CertificateChain Data.X509.AlgorithmIdentifier