x509-1.6.3: X509 reader and writer

License | BSD-style
Maintainer | Vincent Hanquez <vincent@snarc.org>
Stability | experimental
Portability | unknown
Safe Haskell | None
Language | Haskell98

Data.X509

Contents

- Types
- Common extension usually found in x509v3
- Accessor turning extension into a specific one
- Certificate Revocation List (CRL)
- Naming
- Certificate Chain
- marshall between CertificateChain and CertificateChainRaw
- Signed types and marshalling
- Parametrized Signed accessor
- Hash distinguished names related function

Description

Read/Write X509 Certificate, CRL and their signed equivalents.

Follows RFC5280 / RFC6818

Synopsis

- type SignedCertificate = SignedExact Certificate
- type SignedCRL = SignedExact CRL
- data Certificate = Certificate {
  - certVersion :: Int
  - certSerial :: Integer
  - certSignatureAlg :: SignatureALG
  - certIssuerDN :: DistinguishedName
  - certValidity :: (DateTime, DateTime)
  - certSubjectDN :: DistinguishedName
  - certPubKey :: PubKey
  - certExtensions :: Extensions
  }
- data PubKey
  - = PubKeyRSA PublicKey
  - | PubKeyDSA PublicKey
  - | PubKeyDH (Integer, Integer, Integer, Maybe Integer, ([Word8], Integer))
  - | PubKeyEC PubKeyEC
  - | PubKeyUnknown OID ByteString
- data PubKeyEC
  - = PubKeyEC_Prime {
    - pubkeyEC_pub :: SerializedPoint
    - pubkeyEC_a :: Integer
    - pubkeyEC_b :: Integer
    - pubkeyEC_prime :: Integer
    - pubkeyEC_generator :: SerializedPoint
    - pubkeyEC_order :: Integer
    - pubkeyEC_cofactor :: Integer
    - pubkeyEC_seed :: Integer
    }
  - | PubKeyEC_Named {
    - pubkeyEC_name :: CurveName
    - pubkeyEC_pub :: SerializedPoint
    }
- newtype SerializedPoint = SerializedPoint ByteString
- data PrivKey
  - = PrivKeyRSA PrivateKey
  - | PrivKeyDSA PrivateKey
- pubkeyToAlg :: PubKey -> PubKeyALG
- privkeyToAlg :: PrivKey -> PubKeyALG
- data HashALG
  - = HashMD2
  - | HashMD5
  - | HashSHA1
  - | HashSHA224
  - | HashSHA256
  - | HashSHA384
  - | HashSHA512
- data PubKeyALG
  - = PubKeyALG_RSA
  - | PubKeyALG_DSA
  - | PubKeyALG_EC
  - | PubKeyALG_DH
  - | PubKeyALG_Unknown OID
- data SignatureALG
  - = SignatureALG HashALG PubKeyALG
  - | SignatureALG_Unknown OID
- class Extension a where
  - extOID :: a -> OID
  - extEncode :: a -> [ASN1]
  - extDecode :: [ASN1] -> Either String a
- data ExtBasicConstraints = ExtBasicConstraints Bool (Maybe Integer)
- data ExtKeyUsage = ExtKeyUsage [ExtKeyUsageFlag]
- data ExtKeyUsageFlag
  - = KeyUsage_digitalSignature
  - | KeyUsage_nonRepudiation
  - | KeyUsage_keyEncipherment
  - | KeyUsage_dataEncipherment
  - | KeyUsage_keyAgreement
  - | KeyUsage_keyCertSign
  - | KeyUsage_cRLSign
  - | KeyUsage_encipherOnly
  - | KeyUsage_decipherOnly
- data ExtExtendedKeyUsage = ExtExtendedKeyUsage [ExtKeyUsagePurpose]
- data ExtKeyUsagePurpose
  - = KeyUsagePurpose_ServerAuth
  - | KeyUsagePurpose_ClientAuth
  - | KeyUsagePurpose_CodeSigning
  - | KeyUsagePurpose_EmailProtection
  - | KeyUsagePurpose_TimeStamping
  - | KeyUsagePurpose_OCSPSigning
  - | KeyUsagePurpose_Unknown OID
- data ExtSubjectKeyId = ExtSubjectKeyId ByteString
- data ExtSubjectAltName = ExtSubjectAltName [AltName]
- data ExtAuthorityKeyId = ExtAuthorityKeyId ByteString
- data ExtCrlDistributionPoints = ExtCrlDistributionPoints [DistributionPoint]
- data AltName
  - = AltNameRFC822 String
  - | AltNameDNS String
  - | AltNameURI String
  - | AltNameIP ByteString
  - | AltNameXMPP String
  - | AltNameDNSSRV String
- data DistributionPoint
  - = DistributionPointFullName [AltName]
  - | DistributionNameRelative DistinguishedName
- data ReasonFlag
  - = Reason_Unused
  - | Reason_KeyCompromise
  - | Reason_CACompromise
  - | Reason_AffiliationChanged
  - | Reason_Superseded
  - | Reason_CessationOfOperation
  - | Reason_CertificateHold
  - | Reason_PrivilegeWithdrawn
  - | Reason_AACompromise
- extensionGet :: Extension a => Extensions -> Maybe a
- extensionGetE :: Extension a => Extensions -> Maybe (Either String a)
- extensionDecode :: Extension a => ExtensionRaw -> Maybe (Either String a)
- extensionEncode :: Extension a => Bool -> a -> ExtensionRaw
- data ExtensionRaw = ExtensionRaw {
  - extRawOID :: OID
  - extRawCritical :: Bool
  - extRawASN1 :: [ASN1]
  }
- newtype Extensions = Extensions (Maybe [ExtensionRaw])
- data CRL = CRL {
  - crlVersion :: Integer
  - crlSignatureAlg :: SignatureALG
  - crlIssuer :: DistinguishedName
  - crlThisUpdate :: DateTime
  - crlNextUpdate :: Maybe DateTime
  - crlRevokedCertificates :: [RevokedCertificate]
  - crlExtensions :: Extensions
  }
- data RevokedCertificate = RevokedCertificate {
  - revokedSerialNumber :: Integer
  - revokedDate :: DateTime
  - revokedExtensions :: Extensions
  }
- newtype DistinguishedName = DistinguishedName {
  - getDistinguishedElements :: [(OID, ASN1CharacterString)]
  }
- data DnElement
  - = DnCommonName
  - | DnCountry
  - | DnOrganization
  - | DnOrganizationUnit
  - | DnEmailAddress
- data ASN1CharacterString :: * = ASN1CharacterString {
  - characterEncoding :: ASN1StringEncoding
  - getCharacterStringRawData :: ByteString
  }
- getDnElement :: DnElement -> DistinguishedName -> Maybe ASN1CharacterString
- newtype CertificateChain = CertificateChain [SignedExact Certificate]
- newtype CertificateChainRaw = CertificateChainRaw [ByteString]
- decodeCertificateChain :: CertificateChainRaw -> Either (Int, String) CertificateChain
- encodeCertificateChain :: CertificateChain -> CertificateChainRaw
- data (Show a, Eq a, ASN1Object a) => Signed a = Signed {
  - signedObject :: a
  - signedAlg :: SignatureALG
  - signedSignature :: ByteString
  }
- data (Show a, Eq a, ASN1Object a) => SignedExact a
- getSigned :: SignedExact a -> Signed a
- getSignedData :: (Show a, Eq a, ASN1Object a) => SignedExact a -> ByteString
- objectToSignedExact :: (Show a, Eq a, ASN1Object a) => (ByteString -> (ByteString, SignatureALG, r)) -> a -> (SignedExact a, r)
- encodeSignedObject :: SignedExact a -> ByteString
- decodeSignedObject :: (Show a, Eq a, ASN1Object a) => ByteString -> Either String (SignedExact a)
- getCertificate :: SignedCertificate -> Certificate
- getCRL :: SignedCRL -> CRL
- decodeSignedCertificate :: ByteString -> Either String SignedCertificate
- decodeSignedCRL :: ByteString -> Either String SignedCRL
- hashDN :: DistinguishedName -> ByteString
- hashDN_old :: DistinguishedName -> ByteString

# Types

type SignedCertificate = SignedExact Certificate Source

A Signed Certificate

type SignedCRL = SignedExact CRL Source

A Signed CRL

data Certificate Source

X.509 Certificate type.

This type doesn't include the signature, it's describe in the RFC as tbsCertificate.

Constructors

Certificate |

Fields

certVersion :: Int

  Version

certSerial :: Integer

  Serial number

certSignatureAlg :: SignatureALG

  Signature algorithm

certIssuerDN :: DistinguishedName

  Issuer DN

certValidity :: (DateTime, DateTime)

  Validity period (UTC)

certSubjectDN :: DistinguishedName

  Subject DN

certPubKey :: PubKey

  Public key

certExtensions :: Extensions

  Extensions

Instances

Eq Certificate Source |
Show Certificate Source |
ASN1Object Certificate Source |

data PubKey Source

Public key types known and used in X.509

Constructors

PubKeyRSA PublicKey | RSA public key
PubKeyDSA PublicKey | DSA public key
PubKeyDH (Integer, Integer, Integer, Maybe Integer, ([Word8], Integer)) | DH format with (p,g,q,j,(seed,pgenCounter))
PubKeyEC PubKeyEC | EC public key
PubKeyUnknown OID ByteString | unrecognized format

Instances

Eq PubKey Source |
Show PubKey Source |
ASN1Object PubKey Source |

data PubKeyEC Source

Elliptic Curve Public Key

TODO: missing support for binary curve.

Constructors

PubKeyEC_Prime |

Fields

pubkeyEC_pub :: SerializedPoint
pubkeyEC_a :: Integer
pubkeyEC_b :: Integer
pubkeyEC_prime :: Integer
pubkeyEC_generator :: SerializedPoint
pubkeyEC_order :: Integer
pubkeyEC_cofactor :: Integer
pubkeyEC_seed :: Integer

PubKeyEC_Named |

Fields

pubkeyEC_name :: CurveName
pubkeyEC_pub :: SerializedPoint

Instances

Eq PubKeyEC Source |
Show PubKeyEC Source |

newtype SerializedPoint Source

Serialized Elliptic Curve Point

Constructors

SerializedPoint ByteString |

Instances

Eq SerializedPoint Source |
Show SerializedPoint Source |

data PrivKey Source

Private key types known and used in X.509

Constructors

PrivKeyRSA PrivateKey | RSA private key
PrivKeyDSA PrivateKey | DSA private key

Instances

Eq PrivKey Source |
Show PrivKey Source |

pubkeyToAlg :: PubKey -> PubKeyALG Source

Convert a Public key to the Public Key Algorithm type

privkeyToAlg :: PrivKey -> PubKeyALG Source

Convert a Public key to the Public Key Algorithm type

data HashALG Source

Hash Algorithm

Constructors

HashMD2 |
HashMD5 |
HashSHA1 |
HashSHA224 |
HashSHA256 |
HashSHA384 |
HashSHA512 |

Instances

Eq HashALG Source |
Show HashALG Source |

data PubKeyALG Source

Public Key Algorithm

Constructors

PubKeyALG_RSA | RSA Public Key algorithm
PubKeyALG_DSA | DSA Public Key algorithm
PubKeyALG_EC | ECDSA & ECDH Public Key algorithm
PubKeyALG_DH | Diffie Hellman Public Key algorithm
PubKeyALG_Unknown OID | Unknown Public Key algorithm

Instances

Eq PubKeyALG Source |
Show PubKeyALG Source |
OIDable PubKeyALG Source |

data SignatureALG Source

Signature Algorithm often composed of a public key algorithm and a hash algorithm

Constructors

SignatureALG HashALG PubKeyALG |
SignatureALG_Unknown OID |

Instances

Eq SignatureALG Source |
Show SignatureALG Source |
ASN1Object SignatureALG Source |

class Extension a where Source

Extension class.

each extension have a unique OID associated, and a way to encode and decode an ASN1 stream.

Methods

extOID :: a -> OID Source

extEncode :: a -> [ASN1] Source

extDecode :: [ASN1] -> Either String a Source

Instances

Extension ExtCrlDistributionPoints Source |
Extension ExtAuthorityKeyId Source |
Extension ExtSubjectAltName Source |
Extension ExtSubjectKeyId Source |
Extension ExtExtendedKeyUsage Source |
Extension ExtKeyUsage Source |
Extension ExtBasicConstraints Source |

# Common extension usually found in x509v3

data ExtBasicConstraints Source

Basic Constraints

Constructors

ExtBasicConstraints Bool (Maybe Integer) |

Instances

Eq ExtBasicConstraints Source |
Show ExtBasicConstraints Source |
Extension ExtBasicConstraints Source |

data ExtKeyUsage Source

Describe key usage

Constructors

ExtKeyUsage [ExtKeyUsageFlag] |

Instances

Eq ExtKeyUsage Source |
Show ExtKeyUsage Source |
Extension ExtKeyUsage Source |

data ExtKeyUsageFlag Source

key usage flag that is found in the key usage extension field.

Constructors

KeyUsage_digitalSignature |
KeyUsage_nonRepudiation |
KeyUsage_keyEncipherment |
KeyUsage_dataEncipherment |
KeyUsage_keyAgreement |
KeyUsage_keyCertSign |
KeyUsage_cRLSign |
KeyUsage_encipherOnly |
KeyUsage_decipherOnly |

Instances

Enum ExtKeyUsageFlag Source |
Eq ExtKeyUsageFlag Source |
Ord ExtKeyUsageFlag Source |
Show ExtKeyUsageFlag Source |

data ExtExtendedKeyUsage Source

Extended key usage extension

Constructors

ExtExtendedKeyUsage [ExtKeyUsagePurpose] |

Instances

Eq ExtExtendedKeyUsage Source |
Show ExtExtendedKeyUsage Source |
Extension ExtExtendedKeyUsage Source |

data ExtKeyUsagePurpose Source

Key usage purposes for the ExtendedKeyUsage extension

Constructors

KeyUsagePurpose_ServerAuth |
KeyUsagePurpose_ClientAuth |
KeyUsagePurpose_CodeSigning |
KeyUsagePurpose_EmailProtection |
KeyUsagePurpose_TimeStamping |
KeyUsagePurpose_OCSPSigning |
KeyUsagePurpose_Unknown OID |

Instances

Eq ExtKeyUsagePurpose Source |
Ord ExtKeyUsagePurpose Source |
Show ExtKeyUsagePurpose Source |

data ExtSubjectKeyId Source

Provide a way to identify a public key by a short hash.

Constructors

ExtSubjectKeyId ByteString |

Instances

Eq ExtSubjectKeyId Source |
Show ExtSubjectKeyId Source |
Extension ExtSubjectKeyId Source |

data ExtSubjectAltName Source

Provide a way to supply alternate name that can be used for matching host name.

Constructors

ExtSubjectAltName [AltName] |

Instances

Eq ExtSubjectAltName Source |
Ord ExtSubjectAltName Source |
Show ExtSubjectAltName Source |
Extension ExtSubjectAltName Source |

data ExtAuthorityKeyId Source

Provide a mean to identify the public key corresponding to the private key used to signed a certificate.

Constructors

ExtAuthorityKeyId ByteString |

Instances

Eq ExtAuthorityKeyId Source |
Show ExtAuthorityKeyId Source |
Extension ExtAuthorityKeyId Source |

data ExtCrlDistributionPoints Source

Identify how CRL information is obtained

Constructors

ExtCrlDistributionPoints [DistributionPoint] |

Instances

Eq ExtCrlDistributionPoints Source |
Show ExtCrlDistributionPoints Source |
Extension ExtCrlDistributionPoints Source |

data AltName Source

Different naming scheme use by the extension.

Not all name types are available, missing: otherName x400Address directoryName ediPartyName registeredID

Constructors

AltNameRFC822 String |
AltNameDNS String |
AltNameURI String |
AltNameIP ByteString |
AltNameXMPP String |
AltNameDNSSRV String |

Instances

Eq AltName Source |
Ord AltName Source |
Show AltName Source |

data DistributionPoint Source

Distribution point as either some GeneralNames or a DN

Constructors

DistributionPointFullName [AltName] |
DistributionNameRelative DistinguishedName |

Instances

Eq DistributionPoint Source |
Show DistributionPoint Source |

data ReasonFlag Source

Reason flag for the CRL

Constructors

Reason_Unused |
Reason_KeyCompromise |
Reason_CACompromise |
Reason_AffiliationChanged |
Reason_Superseded |
Reason_CessationOfOperation |
Reason_CertificateHold |
Reason_PrivilegeWithdrawn |
Reason_AACompromise |

Instances

Enum ReasonFlag Source |
Eq ReasonFlag Source |
Ord ReasonFlag Source |
Show ReasonFlag Source |

# Accessor turning extension into a specific one

extensionGet :: Extension a => Extensions -> Maybe a Source

Get a specific extension from a lists of raw extensions

extensionGetE :: Extension a => Extensions -> Maybe (Either String a) Source

Get a specific extension from a lists of raw extensions

extensionDecode :: Extension a => ExtensionRaw -> Maybe (Either String a) Source

Try to decode an ExtensionRaw.

If this function return: * 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

extensionEncode :: Extension a => Bool -> a -> ExtensionRaw Source

Encode an Extension to extensionRaw

data ExtensionRaw Source

An undecoded extension

Constructors

ExtensionRaw |

Fields

extRawOID :: OID

  OID of this extension

extRawCritical :: Bool

  if this extension is critical

extRawASN1 :: [ASN1]

  the associated ASN1

Instances

Eq ExtensionRaw Source |
Show ExtensionRaw Source |
ASN1Object ExtensionRaw Source |

newtype Extensions Source

a Set of `ExtensionRaw`

Constructors

Extensions (Maybe [ExtensionRaw]) |

Instances

Eq Extensions Source |
Show Extensions Source |
ASN1Object Extensions Source |

# Certificate Revocation List (CRL)

data CRL Source

Describe a Certificate revocation list

Constructors

CRL |

Fields

crlVersion :: Integer
crlSignatureAlg :: SignatureALG
crlIssuer :: DistinguishedName
crlThisUpdate :: DateTime
crlNextUpdate :: Maybe DateTime
crlRevokedCertificates :: [RevokedCertificate]
crlExtensions :: Extensions

Instances

Eq CRL Source |
Show CRL Source |
ASN1Object CRL Source |

data RevokedCertificate Source

Describe a revoked certificate identifiable by serial number.

Constructors

RevokedCertificate |

Fields

revokedSerialNumber :: Integer
revokedDate :: DateTime
revokedExtensions :: Extensions

Instances

Eq RevokedCertificate Source |
Show RevokedCertificate Source |
ASN1Object RevokedCertificate Source |

# Naming

newtype DistinguishedName Source

A list of OID and strings.

Constructors

DistinguishedName |

Fields

getDistinguishedElements :: [(OID, ASN1CharacterString)]

Instances

Eq DistinguishedName Source |
Ord DistinguishedName Source |
Show DistinguishedName Source |
ASN1Object DistinguishedName Source |
Monoid DistinguishedName Source |

data DnElement Source

Elements commonly available in a `DistinguishedName` structure

Constructors

DnCommonName | CN
DnCountry | Country
DnOrganization | O
DnOrganizationUnit | OU
DnEmailAddress | Email Address (legacy)

Instances

Eq DnElement Source |
Show DnElement Source |
OIDable DnElement Source |

data ASN1CharacterString :: *

ASN1 Character String with encoding

Constructors

ASN1CharacterString |

Fields

characterEncoding :: ASN1StringEncoding
getCharacterStringRawData :: ByteString

Instances

Eq ASN1CharacterString |
Ord ASN1CharacterString |
Show ASN1CharacterString |
IsString ASN1CharacterString |

getDnElement :: DnElement -> DistinguishedName -> Maybe ASN1CharacterString Source

Try to get a specific element in a `DistinguishedName` structure

# Certificate Chain

newtype CertificateChain Source

A chain of X.509 certificates in exact form.

Constructors

CertificateChain [SignedExact Certificate] |

Instances

Eq CertificateChain Source |
Show CertificateChain Source |

newtype CertificateChainRaw Source

Represent a chain of X.509 certificates in bytestring form.

Constructors

CertificateChainRaw [ByteString] |

Instances

Eq CertificateChainRaw Source |
Show CertificateChainRaw Source |

# marshall between CertificateChain and CertificateChainRaw

decodeCertificateChain :: CertificateChainRaw -> Either (Int, String) CertificateChain Source

Decode a CertificateChainRaw into a CertificateChain if every raw certificate are decoded correctly, otherwise return the index of the failed certificate and the error associated.

encodeCertificateChain :: CertificateChain -> CertificateChainRaw Source

Convert a CertificateChain into a CertificateChainRaw

# Signed types and marshalling

data (Show a, Eq a, ASN1Object a) => Signed a Source

Represent a signed object using a traditional X509 structure.

When dealing with external certificate, use the SignedExact structure not this one.

Constructors

Signed |

Fields

signedObject :: a

  Object to sign

signedAlg :: SignatureALG

  Signature Algorithm used

signedSignature :: ByteString

  Signature as bytes

Instances

(Eq a, Show a, ASN1Object a) => Eq (Signed a) Source |
(Eq a, Show a, ASN1Object a) => Show (Signed a) Source |

data (Show a, Eq a, ASN1Object a) => SignedExact a Source

Represent the signed object plus the raw data that we need to keep around for non compliant case to be able to verify signature.

Instances

(Eq a, Show a, ASN1Object a) => Eq (SignedExact a) Source |
(Eq a, Show a, ASN1Object a) => Show (SignedExact a) Source |

getSigned :: SignedExact a -> Signed a Source

get the decoded Signed data

getSignedData :: (Show a, Eq a, ASN1Object a) => SignedExact a -> ByteString Source

Get the signed data for the signature

objectToSignedExact Source

Arguments

:: (Show a, Eq a, ASN1Object a) |
=> (ByteString -> (ByteString, SignatureALG, r)) | signature function
-> a | object to sign
-> (SignedExact a, r) |

Transform an object into a `SignedExact` object

encodeSignedObject :: SignedExact a -> ByteString Source

The raw representation of the whole signed structure

decodeSignedObject :: (Show a, Eq a, ASN1Object a) => ByteString -> Either String (SignedExact a) Source

Try to parse a bytestring that use the typical X509 signed structure format

# Parametrized Signed accessor

getCertificate :: SignedCertificate -> Certificate Source

Get the Certificate associated to a SignedCertificate

getCRL :: SignedCRL -> CRL Source

Get the CRL associated to a SignedCRL

decodeSignedCertificate :: ByteString -> Either String SignedCertificate Source

Try to decode a bytestring to a SignedCertificate

decodeSignedCRL :: ByteString -> Either String SignedCRL Source

Try to decode a bytestring to a SignedCRL

# Hash distinguished names related function

hashDN :: DistinguishedName -> ByteString Source

Make an OpenSSL style hash of distinguished name

OpenSSL algorithm is odd, and has been replicated here somewhat. only lower the case of ascii character.

hashDN_old :: DistinguishedName -> ByteString Source

Create an openssl style old hash of distinguished name