X.509 Certificates
1 Introduction to Using Certificates
2 Certificates
certificate?
certificate<%>
get-subject
get-issuer
get-subject-common-names
get-subject-alt-names
get-subject-name-string
get-issuer-name-string
get-validity-seconds
get-spki
get-key-usages
get-extended-key-usages
get-der
bytes->certificate
read-pem-certificates
pem-file->certificates
x509-key-usage/  c
x509-general-name-tag/  c
3 Certificate Chains
certificate-chain?
certificate-chain<%>
get-certificate
get-certificates
get-issuer-chain
get-anchor
is-anchor?
get-subject
get-subject-alt-names
get-public-key
check-signature
get-security-level
get-security-strength
get-public-key-security-strength
trusted?
check-trust
get-validity-seconds
ok-key-usage?
ok-extended-key-usage?
suitable-for-CA?
suitable-for-tls-server?
suitable-for-tls-client?
4 Certificate Stores
certificate-store?
empty-store
default-store
certificate-store<%>
add
add-trusted-from-pem-file
add-trusted-from-openssl-directory
build-chain
build-chains
pem-file->chain
5 Certificate Revocation Checking
make-revocation-checker
revocation-checker<%>
check-ocsp
check-crl
Bibliography
8.12

X.509 Certificates🔗ℹ

 (require x509) package: x509-lib

This library provides support for X.509 certificates, specifically the profiles and interpretations defined by [PKIX] and the CA/Browser Forum’s Baseline Requirements.

1 Introduction to Using Certificates🔗ℹ

The following example shows how to configure a certificate store with trusted root certificates, load a PEM file to create a certificate chain, and check whether the chain is suitable for identifying a TLS server.

First, let’s use openssl s_client to connect to https://www.racket-lang.org and save the certificates that the server sends in the TLS handshake:

openssl s_client -connect www.racket-lang.org:443 -showcerts \

  < /dev/null > racket.pem

In general, the saved file will contain one or more PEM-encapsulated CERTIFICATE blocks: one for the server, and zero or more intermediate CA certificates necessary for building a certificate chain anchored by a trusted root CA.

If we try to load the PEM file using an empty certificate store, we get an error, because the store has no trusted roots:
> (send (empty-store) pem-file->chain "racket.pem")

pem-file->chain: failed to build complete chain

  end certificate: #<certificate: C=US/ST=California/L=San

Francisco/O=Cloudflare, Inc./CN=sni.cloudflaressl.com>

We must configure a certificate store with a reasonable set of trusted roots. We must also enable some crypto factories so that the store can verify certificate signatures.
> (define store
    (send (empty-store) add-trusted-from-openssl-directory "/etc/ssl/certs"))
> (crypto-factories libcrypto-factory)
Alternatively, we can use a store initialized with the OS’s default trusted certificates:
> (define store (default-store))

Now we can create a certificate chain from the saved PEM file:
> (define racket-chain (send store pem-file->chain "racket.pem"))
We can extract the chain’s end certificate; we can also extract all of the certificates in the chain:
> (send racket-chain get-certificate)

#<certificate: C=US/ST=California/L=San Francisco/O=Cloudflare, Inc./CN=sni.cloudflaressl.com>

> (send racket-chain get-certificates)

'(#<certificate: C=US/ST=California/L=San Francisco/O=Cloudflare, Inc./CN=sni.cloudflaressl.com>

  #<certificate: C=US/O=Cloudflare, Inc./CN=Cloudflare Inc ECC CA-3>

  #<certificate: C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root>)

We check whether the certificate (more precisely, the certificate chain) is suitable for identifying a TLS server—and specifically, "www.racket-lang.org":
> (send racket-chain suitable-for-tls-server? "www.racket-lang.org")

#t

> (send racket-chain suitable-for-tls-server? "www.scheme.com")

#f

Finally, we can extract the end certificate’s public key:
> (define racket-pk (send racket-chain get-public-key))

2 Certificates🔗ℹ

A certificate represents an assertion that a cryptographic public key is tied to an identity, to be used for a particular purpose. The assertion is cryptographically signed by another party, the issuer.

For example, a secure web site (serving HTTP over TLS) would present a certificate with their public key, their identity in the form of their DNS name, and the purpose of identifying a TLS server. That certificate’s issuer would own a certificate for the purpose of acting as a certificate authority (CA), and its public key should verify the signature on the TLS server’s certificate.

One does not decide whether to trust a certificate in isolation; it depends on whether the issuer is trusted, and that often involves obtaining a certificate for the issuer and deciding whether to trust it, and so on. In general, trust is evaluated for a certificate chain; chains are built and evaluated using a certificate store.

procedure

(certificate? v)  boolean?

  v : any/c
Returns #t if v is a certificate, #f otherwise. Certificates implement the certificate<%> interface.

Public interface for certificates.
Note that (certificate? v) implies (is-a? v certificate<%>), but not vice versa. That is, a certificate object implements additional internal interfaces not exposed to users.
> (define racket-cert (send racket-chain get-certificate))
> racket-cert

#<certificate: C=US/ST=California/L=San Francisco/O=Cloudflare, Inc./CN=sni.cloudflaressl.com>

Two certificates are equal? if they have the same DER encodings.

method

(send a-certificate get-subject)  any/c

Returns the Name of the certificate’s subject.

The result is a X.509 Name value represented according to the rules of the asn1 library. See [PKIX] for the definition of Name.

> (send racket-cert get-subject)

'(rdnSequence

  ((#hasheq((type . (2 5 4 6)) (value . "US")))

   (#hasheq((type . (2 5 4 8)) (value . (printableString "California"))))

   (#hasheq((type . (2 5 4 7)) (value . (printableString "San Francisco"))))

   (#hasheq((type . (2 5 4 10))

            (value . (printableString "Cloudflare, Inc."))))

   (#hasheq((type . (2 5 4 3))

            (value . (printableString "sni.cloudflaressl.com"))))))

method

(send a-certificate get-issuer)  any/c

Returns the Name of the certificate’s issuer.

> (send racket-cert get-issuer)

'(rdnSequence

  ((#hasheq((type . (2 5 4 6)) (value . "US")))

   (#hasheq((type . (2 5 4 10))

            (value . (printableString "Cloudflare, Inc."))))

   (#hasheq((type . (2 5 4 3))

            (value . (printableString "Cloudflare Inc ECC CA-3"))))))

method

(send a-certificate get-subject-common-names)

  (listof string?)
Returns a list of Common Names (CN) occuring in the certificate’s subject. A typical certificate has at most one Common Name.

> (send racket-cert get-subject-common-names)

'("sni.cloudflaressl.com")

method

(send a-certificate get-subject-alt-names [kind])

  (listof any/c)
  kind : (or/c #f x509-general-name-tag/c) = #f
Returns a list of the certificate’s Subject Alternative Names (SAN).

If kind is a symbol, only subject alternative names of the given kind are returned, and they are returned untagged. If kind is #f, then all SAN entries are returned, and each entry is tagged with a kind symbol (see x509-general-name-tag/c).

> (send racket-cert get-subject-alt-names)

'((dNSName "sni.cloudflaressl.com")

  (dNSName "racket-lang.org")

  (dNSName "*.racket-lang.org"))

> (send racket-cert get-subject-alt-names 'dNSName)

'("sni.cloudflaressl.com" "racket-lang.org" "*.racket-lang.org")

method

(send a-certificate get-subject-name-string)  string?

Returns a string summarizing the subject name of the certificate.

Warning: The format of the result may change in future versions of this library.

Example:
> (send racket-cert get-subject-name-string)

"C=US/ST=California/L=San Francisco/O=Cloudflare, Inc./CN=sni.cloudflaressl.com"

method

(send a-certificate get-issuer-name-string)  string?

Like get-subject-name-string, but returns a string representing the issuer.

Example:
> (send racket-cert get-issuer-name-string)

"C=US/O=Cloudflare, Inc./CN=Cloudflare Inc ECC CA-3"

Returns the validity period of the certificate (from notBefore to notAfter) in seconds (see current-seconds, seconds->date, etc).

> (send racket-cert get-validity-seconds)

'(1623448800 1654984799)

method

(send a-certificate get-spki)  bytes?

Gets the DER encoding of the certificate’s SubjectPublicKeyInfo (SPKI).

This can be converted to a public key with datum->pk-key, but it is usually better to validate the certificate first and then call the chain’s get-public-key method.

method

(send a-certificate get-key-usages)

  (listof x509-key-usage/c)
Gets the value of the KeyUsage extension, if present; if the extension is absent, returns null. See also ok-key-usage? in certificate-chain<%>.

> (send racket-cert get-key-usages)

'(digitalSignature)

method

(send a-certificate get-extended-key-usages)

  (listof asn1-oid?)
Gets the value of the ExtendedKeyUsage extension, if present; if the extension is absent, returns null. See also ok-extended-key-usage? in certificate-chain<%>.

> (send racket-cert get-extended-key-usages)

'((1 3 6 1 5 5 7 3 1) (1 3 6 1 5 5 7 3 2))

method

(send a-certificate get-der)  bytes?

Gets the DER encoding of the certificate.

procedure

(bytes->certificate bs)  certificate?

  bs : bytes?
Parses bs as a certificate. The byte string bs must contain exactly one DER-encoded certificate; otherwise, an exception is raised.

procedure

(read-pem-certificates in [#:count count])  (listof certificate?)

  in : input-port?
  count : (or/c exact-nonnegative-integer? +inf.0) = +inf.0
Reads up to count certificates from in. The certificates must be encoded in the RFC 7468 textual format [RFC7468]. (This format is often conflated with “PEM”, although technically the two formats are not completely compatible.)

Certificates are delimited by "----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" lines. Data outside of the delimiters is ignored and discarded, so certificates may be interleaved with other text. For example, the openssl s_client -showcerts command logs certificates intermixed with other diagnostic messages during TLS handshaking.

procedure

(pem-file->certificates pem-file    
  [#:count count])  (listof certificate?)
  pem-file : path-string?
  count : (or/c exact-nonnegative-integer? +inf.0) = +inf.0
Like read-pem-certificates, but reads from the given pem-file.

Contract for symbols representing members of a KeyUsage extension value. Equivalent to
(or/c 'digitalSignature 'nonRepudiation 'keyEncipherment 'dataEncipherment
      'keyAgreement 'keyCertSign 'cRLSign 'encipherOnly 'decipherOnly)

Contract for symbols tagging kinds of GeneralName. Equivalent to
(or/c 'otherName 'rfc822Name 'dNSName 'x400Address 'directoryName
      'ediPartyName 'uniformResourceIdentifier 'iPAddress 'registeredID)

3 Certificate Chains🔗ℹ

A certificate chain contains a non-empty list of certificates, starting with an anchor (also called a trust anchor, and typically a root CA certificate) and ending with the end certificate that is, the certificate whose identity, public key, and purpose are of interest to the application. The list of certificates satisfies the chain-validity properties:
  • Each certificate is the issuer of the next—that is, the subject name of each certificate “matches” [PKIX] the issuer name of the next certificate.

  • Each certificate that acts as an issuer (that is, every certificate in the chain except for the end certificate) is suitable as a CA certificate.

  • Each certificate’s public key verifies the signature of the next certificate in the chain. (Note that the anchor certificate’s signature is not checked; its trust is determined by the certificate store.)

  • The validity period of the chain is non-empty. The validity period of the chain is the intersection of the validity periods of all of the certificates in the chain. The certificates are not required to have strictly nested validity periods.

However, chain-validity is only a basic well-formedness property; it does not mean that the end certificate is valid for a given purpose. In particular:
  • A chain does not necessarily start with a trusted root CA.

  • A chain is not necessarily valid at the current time.

  • A chain’s end certificate is not necessarily valid for a given purpose (for example, for identifying particular a TLS server and creating a TLS connection).

Use trusted? to verify the first two properties and suitable-for-tls-server? to verify the third property (in the case of a TLS server).

Note: [PKIX] uses the term “certification path” instead of “certificate chain”.

procedure

(certificate-chain? v)  boolean?

  v : any/c
Returns #t if v is a certificate chain, #f otherwise. Certificate chains implement the certificate-chain<%> interface.

Public interface for certificate chains.
Note that (certificate-chain? v) implies (is-a? v certificate-chain<%>), but not vice versa. That is, a certificate chain object implements additional internal interfaces not exposed to users.

method

(send a-certificate-chain get-certificate)  certificate?

Returns the chain’s end certificate that is, the certificate that the chain certifies.

method

(send a-certificate-chain get-certificates)

  (listof certificate?)
Returns all of the certificates in a-certificate-chain, in “reversed” order: that is, the end certificate is the first element of the resulting list and the anchor is last.

method

(send a-certificate-chain get-issuer-chain)

  (or/c certificate-chain? #f)
Returns the prefix of the certificate chain corresponding to this certificate’s issuer, or #f if the current chain is an anchor.

method

(send a-certificate-chain get-anchor)  certificate-chain?

Returns the certificate chain’s anchor.

method

(send a-certificate-chain is-anchor?)  boolean?

Returns #t if a-certificate-chain is an anchor, #f otherwise. An anchor is a chain that has no issuer chain.

method

(send a-certificate-chain get-subject)  any/c

Equivalent to

(send (send a-certificate-chain get-certificate) get-subject)

method

(send a-certificate-chain get-subject-alt-names [kind])

  (listof any/c)
  kind : (or/c symbol? #f) = #f
Equivalent to
(send (send a-certificate-chain get-certificate)
      get-subject-alt-names kind)

method

(send a-certificate-chain get-public-key [factories])

  public-only-key?
  factories : (or/c crypto-factory? (listof crypto-factory?))
   = (crypto-factories)
Creates a public key from the end certificate’s SubjectPublicKeyInfo using an implementation from factories.

method

(send a-certificate-chain check-signature algid 
  msg 
  sig) 
  (result/c #t (listof symbol?))
  algid : (or/c bytes? asn1-algorithm-identifier/c)
  msg : bytes?
  sig : bytes?
Verifies that the signature sig is valid for the data msg using the end certificate’s public key and the signature algorithm specified by algid (an AlgorithmIdentifier, either DER-encoded as a byte string or the parsed representation).

The result is one of the following:
  • The result is (ok #t) if the signature is valid.

  • The result is (bad faults) if verification failed, where faults is a list of symbols describing the failure. The symbol 'signature:bad indicates a bad signature; other symbols indicate situations like problems interpreting algid and mismatches between the public key and the algorithm specified by algid.

method

(send a-certificate-chain get-security-level)

  security-level/c
Returns the security level of the chain. Equivalent to

Example:
> (send racket-chain get-security-level)

2

method

(send a-certificate-chain get-security-strength)

  exact-nonnegative-integer?
Returns the security strength of the chain, which is the minimum of the strengths of each public key and signature in the chain, except for the signature within the anchor.

Example:
> (send racket-chain get-security-strength)

112

Returns the security strength of the end certificate’s public key. Equivalent to

(pk-security-strength (send a-certificate-chain get-public-key))

Example:
> (send racket-chain get-public-key-security-strength)

128

method

(send a-certificate-chain trusted? 
  store 
  [from-time 
  to-time 
  #:security-level security-level]) 
  boolean?
  store : certificate-store?
  from-time : exact-integer? = (current-seconds)
  to-time : exact-integer? = from-time
  security-level : security-level/c = 2
Returns #t if the chain’s anchor certificate is trusted according to store, the validity of the chain includes the period from from-time to to-time, and the security level of all public keys and signatures in the chain is at least security-level; otherwise, returns #f.

Equivalent to
(ok? (send a-certificate-chain check-trust store from-time to-time
           #:security-level security-level))

method

(send a-certificate-chain check-trust 
  store 
  [from-time 
  to-time 
  #:security-level security-level]) 
  (result/c #t (listof (cons/c exact-nonnegative-integer? any/c)))
  store : certificate-store?
  from-time : exact-integer? = (current-seconds)
  to-time : exact-integer? = from-time
  security-level : security-level/c = 2
Similar to trusted?, but the result is one of the following:
  • The result is (ok #t) if the chain’s anchor certificate is trusted by store, the validity of the chain includes the period from from-time to to-time, and the security level of all public keys and signatures in the chain is at least security-level.

  • The result is (bad (list (cons cert-index fault) ...)) otherwise, where each cert-index is the index of the certificate where the problem occurred (starting with 0 for the anchor) and fault is a value (usually a symbol) describing the problem.

Examples:
> (send racket-chain check-trust (default-store) #:security-level 2)

'#s(ok #t)

> (send racket-chain check-trust (empty-store) #:security-level 3)

'#s(bad ((0 . anchor:not-trusted) (0 . security-level:weak-public-key)))

method

(send a-certificate-chain get-validity-seconds)

  (list/c exact-integer? exact-integer?)
Gets the validity period of the chain, which is the intersection of the validity periods of all certificates in the chain.

Example:
> (send racket-chain get-validity-seconds)

'(1623448800 1654984799)

method

(send a-certificate-chain ok-key-usage? usage    
  [default])  any/c
  usage : key-usage/c
  default : any/c = #f
Returns #t if the end certificate has the KeyUsage extension and the extension’s value contains the key usage named by usage. If the extension is present but does not contain usage, returns #f. If the end certificate does not have a KeyUsage extension, returns default.

Examples:
> (send racket-chain ok-key-usage? 'digitalSignature)

#t

> (send racket-chain ok-key-usage? 'keyCertSign)

#f

> (let ([ca-chain (send racket-chain get-issuer-chain)])
    (send ca-chain ok-key-usage? 'keyCertSign))

#t

method

(send a-certificate-chain ok-extended-key-usage? eku)

  boolean?
  eku : asn1-oid?
Returns #t if the extended key usage identified by eku (an OBJECT IDENTIFIER) is allowed for the end certificate of a-certificate-chain; returns #f otherwise.

The extended key usage eku is allowed if all of the following are true:
  • The end certificate contains an ExtendedKeyUsage extension and the extension’s value contains eku.

  • In every preceding certificate in the chain (that is, the anchor and intermediate CA certificates), if the ExtendedKeyUsage extension is present, then its value contains eku.

Note: this method does not treat anyExtendedKeyUsage specially.

Examples:
> (define id-kp-serverAuth '(1 3 6 1 5 5 7 3 1))
> (send racket-chain ok-extended-key-usage? id-kp-serverAuth)

#t

> (define id-kp-codeSigning '(1 3 6 1 5 5 7 3 3))
> (send racket-chain ok-extended-key-usage? id-kp-codeSigning)

#f

method

(send a-certificate-chain suitable-for-CA?)  boolean?

Returns #t if the chain ends with a certificate that is suitable for a certificate authority specifically, for signing other certificates. Returns #f otherwise.

Examples:
> (send racket-chain suitable-for-CA?)

#f

> (let ([issuer-chain (send racket-chain get-issuer-chain)])
    (send issuer-chain suitable-for-CA?))

#t

method

(send a-certificate-chain suitable-for-tls-server? host)

  boolean?
  host : (or/c string? #f)
Returns #t if the chain ends with a certificate that is suitable for identifying a TLS server, and if the certificate has a subject alternative name (SAN) that matches the given host DNS name; otherwise, returns #f. If host is #f, the DNS name check is omitted.

Examples:
> (send racket-chain suitable-for-tls-server? "racket-lang.org")

#t

> (send racket-chain suitable-for-tls-server? "example.com")

#f

> (send racket-chain suitable-for-tls-server? #f)

#t

method

(send a-certificate-chain suitable-for-tls-client? name)

  boolean?
  name : any/c
Returns #t if the chain’s certificate is suitable for identifying a client to a TLS server, and if the certificate has a subject name or subject alternative name (SAN) that matches the given name; otherwise, returns #f. If name is #f, then the name check is omitted.

4 Certificate Stores🔗ℹ

A certificate store determines which certificates are trusted a priori—usually, these trusted certificates correspond to root CAs, which are typically self-issued and self-signed. In this context, “trusted” means that the assertion that the certificate represents (binding a public key to identities and purposes) is accepted at face value; it does not mean that the certificate is automatically accepted as suitable for every purpose.

The store may also contain certificates that are not directly trusted, but may be used in the construction of chains.

procedure

(certificate-store? v)  boolean?

  v : any/c
Returns #f if v is a certificate store, #f otherwise. Certificate stores implement the certificate-store<%> interface.

procedure

(empty-store [#:security-level security-level])

  certificate-store?
  security-level : security-level/c = 2
Returns a certificate store containing no certificates (trusted or untrusted). The store’s security level is initialized to security-level.

procedure

(default-store [#:security-level security-level])

  certificate-store?
  security-level : security-level/c = 2
Returns a certificate store initialized with trusted certificates from the OS. The store’s security level is initialized to security-level. The trusted certificates are the same as those specified by the openssl library’s (ssl-default-verify-sources) initial value.

Public interface for certificate stores.
Note that (certificate-store? v) implies (is-a? v certificate-store<%>), but not vice versa. That is, a certificate store object implements additional internal interfaces not exposed to users.

method

(send a-certificate-store add [#:trusted trusted-certs 
  #:untrusted untrusted-certs]) 
  certificate-store?
  trusted-certs : (listof certificate?) = null
  untrusted-certs : (listof certificate?) = null
Creates a new certificate store like a-certificate-store but where
  • The trusted-certs and untrusted-certs are available for building certificate chains.

  • The trusted-certs are considered trusted.

Note: trust is monotonic. That is, if a certificate is already trusted, then adding it again as an untrusted certificate does not make it untrusted.

method

(send a-certificate-store add-trusted-from-pem-file pem-file)

  certificate-store?
  pem-file : path-string?
Creates a new certificate store like a-certificate-store, but trusting the certificates contained in PEM format in pem-file.

method

(send a-certificate-store add-trusted-from-openssl-directory dir)

  certificate-store?
  dir : path-string?
Creates a new certificate store like a-certificate-store, but trusting the certificates in dir, which uses OpenSSL-style hashing.

method

(send a-certificate-store build-chain end-cert 
  [other-untrusted-certs 
  valid-time]) 
  certificate-chain?
  end-cert : certificate?
  other-untrusted-certs : (listof certificate?) = null
  valid-time : exact-integer? = (current-seconds)
Builds a certificate chain starting with some trusted certificate and ending with end-cert. The chain may be built from intermediate certificates from other-untrusted-certs in addition to the certificates already in the store. The result chain is chain-valid; it is valid for a period including valid-time; and its anchor is trusted by a-certificate-store.

If no such chain can be constructed, an exception is raised. If multiple chains can be constructed, one is selected, but there are no guarantees about how it is selected.

method

(send a-certificate-store build-chains end-cert 
  [other-untrusted-certs 
  valid-time 
  #:empty-ok? empty-ok?]) 
  (listof certificate-chain?)
  end-cert : certificate?
  other-untrusted-certs : (listof certificate?) = null
  valid-time : exact-integer? = (current-seconds)
  empty-ok? : boolean? = #f
Like build-chain, but returns all chains that could be constructed. If no such chains can be constructed, an exception is raised, unless empty-ok? is true, in which case null is returned.

method

(send a-certificate-store pem-file->chain pem-file 
  [valid-time]) 
  certificate-chain?
  pem-file : path-string?
  valid-time : exact-integer? = (current-seconds)
Returns a certificate chain for the first certificate in PEM format in pem-file, using any remaining certificates in the file as other untrusted certificates. The result chain is chain-valid; it is valid for a period including valid-time; and its anchor is trusted by a-certificate-store.

5 Certificate Revocation Checking🔗ℹ

There are two main certificate revocation mechanisms: CRLs (Certificate Revocation Lists) and OCSP (Online Certificate Status Protocol).

Examples:
> (define rev (make-revocation-checker 'temporary #:fetch-crl? #f))
> (send rev check-ocsp racket-chain)

'#s(ok #t)

> (send rev check-crl racket-chain)

'#s(bad unknown)

procedure

(make-revocation-checker db-file 
  [#:trust-db? trust-db? 
  #:fetch-ocsp? fetch-ocsp? 
  #:fetch-crl? fetch-crl?]) 
  (is-a?/c revocation-checker<%>)
  db-file : (or/c path-string? 'memory 'temporary)
  trust-db? : boolean? = #t
  fetch-ocsp? : boolean? = #t
  fetch-crl? : boolean? = #t
Returns an object for performing certificate revocation checks using OCSP and CRLs.

The db-file is a SQLite3 database file used to cache OCSP and CRL responses. These responses carry signatures, so they can be cached even if the cache is untrusted. (When the cache contains a response, the response is re-verified, and if verification fails then the cached response is discarded and a new response is retrieved.)

If trust-db? is #t, then status information about individual certificates is also cached. This saves parsing and signature verification time, but these individual status records do not carry signatures, so they cannot be re-verified later. If trust-db? is #f, then only the re-verifiable parts of the cache are used.

If fetch-ocsp? is #t, then if the cache does not contain a trusted, unexpired OCSP response, a response is fetched from the OCSP responder URL (or URLs) in the certificate being checked. If fetch-ocsp? is #f, no new response is fetched; if a suitable response is not in the cache, the certificate’s status is unknown. Likewise, the fetch-crl? option controls requests for CRLs.

Public interface for checking revocation of certificates.
Both the check-ocsp and check-crl methods take certificate chains rather than certificates, because verifying revocation responses requires the public key of the certificate’s issuer. Both methods check only the end certificate of the chain for revocation.

method

(send a-revocation-checker check-ocsp chain)

  (result/c #t (or/c 'revoked 'unknown 'no-sources))
  chain : certificate-chain?
Returns one of the following:
  • (ok #t) Some OCSP response indicated that the end certificate is good.

  • (bad 'revoked) Some OCSP response indicated that the end certificate is revoked.

  • (bad 'unknown) No responder produced a valid response, or the response indicated that the responder does not know the certificate’s status.

  • (bad 'no-sources) The certificate has no usable OCSP responder URLs. This library uses only URLs with the scheme "http" or "https".

method

(send a-revocation-checker check-crl chain)

  (result/c #t (listof (or/c 'revoked 'unknown 'no-sources)))
  chain : certificate-chain?
Returns one of the following:
  • (ok #t) All usable CRLs were checked and the end certificate of chain was absent from all of the revocation lists.

  • (bad 'revoked) Some CRL indicated that the certificate is revoked.

  • (bad 'unknown) Some CRL source was unavailable or contained an invalid CRL, either because retrieving it failed (perhaps due to a network failure or server problem), or the retrieved CRL had a bad signature, or a-revocation-checker was configured not to fetch CRLs and it was not in the cache.

  • (bad 'no-sources) The certificate has no usable CRL sources. This library uses only URLs with the scheme "http" or "https".

Bibliography🔗ℹ

[PKIX] “RFC 5280: Internet X.509 Public Key Infrastructure: Certificate and CRL Profile.” https://tools.ietf.org/html/rfc5280
[RFC7468] “Textual Encodings of PKIX, PKCS, and CMS Structures.” https://tools.ietf.org/html/rfc7468
[CAB-BR] “Baseline Requirements for the Issuance and Management of Publicly-Trusted Certificates.” https://cabforum.org/baseline-requirements-documents/
[OCSP] “RFC 6960: X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP.” https://tools.ietf.org/html/rfc6960
[LightOCSP] “RFC 5019: The Lightweight Online Certificate Status Protocol (OCSP) Profile for High-Volume Environments.” https://tools.ietf.org/html/rfc5019
[SP800-57-1] “NIST Special Publication 800-57 Part 1 Revision 5: Recommendation for Key Management: Part 1 - General.” https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final