On this page
- The problem: a certificate that should stop working
- The parts of a PKI
- The hierarchy: an offline root and an issuing CA
- Key ceremonies
- Certificate profiles
- Trust stores are policy
- Expiry is not revocation
- CRLs: a signed list of serial numbers
- OCSP: ask about one certificate
- Planning for compromise
- Certificate policy and certification practice statement
- Run your own CA or use an external one?
- Mariama’s certificate is revoked, Ibrahima checks
- Try it: revoke a certificate, check a CRL and ask OCSP
- Step 1: a CA and two certificates
- Step 2: revoke, publish a CRL, check
- Step 3: an OCSP responder
- Where SEDEYA fits
- Risks and misconceptions
- Summary
- Check your understanding
- Next step
Who this is for
Software engineers, security engineers and technical decision-makers who have read Articles 1 to 3 and know what a certificate, a chain and an HSM are.
Read first
You will learn
- Lay out a two-tier PKI with an offline root and an online issuing CA, and say which RFC rules and which industry practices shape it
- Choose the extensions that separate a CA certificate from a signer's certificate, including path length, key usage, CRL distribution points and AIA
- Tell expiry from revocation, and explain how a CRL and an OCSP response each report that a certificate was revoked
- Read an OCSP answer correctly: what good, revoked and unknown mean, and why freshness matters
- Revoke a certificate with OpenSSL and watch both a CRL check and an OCSP query report it
- Say what a certificate policy (CP) and a certification practice statement (CPS) are, and how they differ
The problem: a certificate that should stop working
Mariama’s certificate from Article 2 is valid for a year. Three months in, the token that holds her signing key is stolen, and her PIN with it. The certificate still says, under a CA’s signature, that this public key is hers. Until something changes, any signature the thief makes will verify.
Ibrahima needs a way to learn that the certificate should no longer be trusted, even though its dates look fine, and someone must have decided in writing who can ask for a revocation and where the answer is published. Issuing a certificate is one command; building a PKI is the system around it.
The parts of a PKI
A working PKI arranges Article 2’s roles into a hierarchy and adds services that report certificate status.
The hierarchy: an offline root and an issuing CA
RFC 5280 does not impose a shape: a path runs from an end-entity certificate through zero or more CA certificates back to a key the relying party trusts (RFC 5280, §3.2). A common private design has two tiers: a root that signs only issuing-CA certificates and CRLs, and an issuing CA that signs everything else. The word “offline” does not appear in RFC 5280, RFC 6960 or RFC 3647 for a root CA. The practice comes from industry; the CA/Browser Forum’s rules for publicly trusted TLS certificate authorities write down the controls around it.
One regulated industry's rules, as an illustration
The CA/Browser Forum documents quoted here bind CAs that issue publicly trusted TLS certificates, not a private document-signing PKI.
The Network and Certificate System Security Requirements allow root CA systems that are “Air-Gapped and otherwise” (CABF-NSR, Definitions), so they do not require an offline root. They do require that systems holding a root key sit on networks physically separate from all other CA infrastructure (§1.2.1), and physical access to them needs multi-party control: two or more authorized people, each with their own credentials (§2.2.4). The Baseline Requirements add that each root signing operation needs an authorized person to “deliberately issue a direct command”, so root signing is never automated (CABF-BR, §4.3.1.1).
Our reading, which no source states as a rationale: a root that only signs CA certificates and CRLs is used a few times a year, so its key is rarely exposed. The issuing CA can be online because, if it is compromised, the root is intact and can revoke it and sign a replacement; its pathlen:0 stops it creating further CAs (RFC 5280, §4.2.1.9), which limits the damage to end-entity certificates.
Key ceremonies
A root key is generated once, in a ceremony. The Baseline Requirements describe one: follow a written script, have a qualified auditor witness it or video-record it, with trusted roles under multi-person control and split knowledge, inside cryptographic modules, and log everything (CABF-BR, §6.1.1.1). The module is the HSM of Article 3; the ceremony adds people and witnesses around it.
RFC 3647 asks the same questions without fixing answers: how many people each task needs (“n out of m”) (RFC 3647, §4.5.2), whether the key is split so any n of m parts rebuild it (§4.6.2, §7), and how the CA’s public key reaches relying parties securely (§4.6.1).
Certificate profiles
A profile is the set of fields and extensions a CA puts in each kind of certificate.
| Extension | Root | Issuing CA | Signer (end entity) |
|---|---|---|---|
basicConstraints |
CA:TRUE, critical |
CA:TRUE, pathlen:0, critical |
CA:FALSE |
keyUsage |
keyCertSign, cRLSign, critical |
keyCertSign, cRLSign, critical |
digitalSignature, nonRepudiation |
| CRL distribution points | none: a root has no issuer | where the root’s CRL lives | where the issuing CA’s CRL lives |
| Authority information access | none: a root has no issuer | root certificate location | OCSP responder URL, issuer certificate location |
The table follows RFC 5280: a CA certificate needs critical basicConstraints with cA true (RFC 5280, §4.2.1.9) and keyUsage with keyCertSign, which should be critical (§4.2.1.3); an HTTP CRL distribution point serves one DER-encoded CRL (§4.2.1.13); and AIA carries OCSP and issuer-certificate locations, never CRLs (§4.2.2.1).
Trust stores are policy
As Article 2 showed, choosing a trust anchor is a matter of policy (RFC 5280, §6), and adding your root to Ibrahima’s store says “I accept what this CA and everything below it vouches for”. OpenSSL still checks the root’s validity period, but its self-signature only with -check_ss_sig (openssl-verification-options).
Expiry is not revocation
Expiry is the planned end of a certificate. Revocation is the CA ending it early, for a reason such as a name change or a compromised key (RFC 5280, §3.3). A revoked certificate’s CRL entry must stay until it has appeared on one scheduled CRL issued after the certificate expires; after that it can drop off (§3.3, §5). And a certificate cannot be validated for a time outside its validity period (§6.1). Proving Mariama signed while her certificate was valid needs a trusted time for the signature, which is Article 7’s subject.
CRLs: a signed list of serial numbers
A certificate revocation list (CRL) is a time-stamped list, signed by the CA or a delegated CRL issuer, of revoked certificates identified by serial number (RFC 5280, §3.3). A relying party “acquires a suitably recent CRL”, with “suitably recent” left to local policy. A signed CRL can travel over untrusted servers; its weakness is latency, since CRLs come out on a schedule and a revocation shows only in the next one.
When a CA issues CRLs, they must be version 2 and include nextUpdate, a CRL Number and an Authority Key Identifier (§5). thisUpdate is the issue date and nextUpdate the date by which the next CRL will appear, never later (§5.1.2.4, §5.1.2.5); the CRL Number only goes up (§5.2.3). Each entry has a serial number and revocation date (§5.1.2.6), and optionally:
- a reason code, such as keyCompromise, cACompromise, superseded or cessationOfOperation. RFC 5280 says to omit it rather than write “unspecified” (§5.3.1);
- an invalidity date, when the compromise happened or was suspected, which can be earlier than the revocation date (§5.3.2). For Mariama’s stolen token, the invalidity date is where the thief’s window starts; it closes only when relying parties see the revocation.
OCSP: ask about one certificate
The Online Certificate Status Protocol lets an application ask about specific certificates, “in lieu of, or as a supplement to” CRLs, when it needs more timely information (RFC 6960, §2). The request names the certificate by its issuer’s name and key hashes and its serial number (§4.1.1).
Definitive responses are signed, by the issuing CA, a responder the client trusts directly, or a responder the CA has authorized (§2.2). There are three statuses:
good: no certificate with that serial is revoked within its validity interval. It “does not necessarily mean that the certificate was ever issued”.revoked: revoked permanently or on hold. Reject.unknown: this responder does not know the certificate, usually because it does not serve that issuer. Try another source, such as a CRL.
Error responses such as tryLater are not signed (§2.3); treat them as no status at all.
A response carries thisUpdate, nextUpdate and producedAt (§2.4), and may be pre-produced (§2.5). One whose nextUpdate has passed is unreliable; with no nextUpdate, newer information is always available (§4.2.2.1). A client accepts a response only if it matches the certificate, its signer is authorised and valid, and it is fresh (§3.2).
A CA delegates signing by giving a responder a certificate with the id-kp-OCSPSigning extended key usage, issued directly by the CA that issued the certificate being checked. A client accepts a response only if it is signed by that CA itself, by such a delegated responder, or by a responder it trusts locally; any other signer must be rejected (§2.6, §4.2.2.2). Against replay, a request can carry a nonce: 1 to 128 octets, and at least 32 from requesters (RFC 9654, §2.1). A responder may omit the nonce, so a short thisUpdate-to-nextUpdate interval is the fallback defence (§3.1).
Which one? Online checking cuts latency, but the validator must trust the online service, while a CRL repository need not be trusted (RFC 5280, §3.3). A PKI can publish both. A responder may also keep revocation data past expiry, back to an “archive cutoff” date (RFC 6960, §4.4.4); Articles 6 and 7 show how a signed PDF embeds CRLs and OCSP responses so nobody has to ask years later.
Planning for compromise
A stolen token means revoking one certificate. A compromised issuing-CA key means the root revokes the issuing CA, with the cACompromise reason, and everything below it loses its valid path. A responder that knows a CA key is compromised may answer revoked for every certificate that CA issued (RFC 6960, §2.7). RFC 3647 asks the practice statement to plan incident reporting, recovery after a key compromise and business continuity (RFC 3647, §4.5.7). A root compromise means a new trust anchor in every relying party’s store, which, in our reading, is why the root stays offline.
Certificate policy and certification practice statement
A certificate policy (CP) is “A named set of rules that indicates the applicability of a certificate to a particular community and/or class of application with common security requirements” (RFC 3647, §2). A certification practice statement (CPS) is “A statement of the practices that a certification authority employs in issuing, managing, revoking, and renewing or re-keying certificates”.
The CP says what participants must do; the CPS says how one CA does it. A CP often spans several CAs; a CPS covers one and is more detailed (§3.5). A certificate names its CP by OID in the certificate policies extension and can point to the CPS by URL (§3.3.1).
Both follow one nine-part outline (§3.7): introduction; publication and repository; identification and authentication; certificate life-cycle operations; facilities, management and operational controls; technical security controls; certificate, CRL and OCSP profiles; compliance audit; other business and legal matters.
A topic can say “no stipulation”, but RFC 3647 recommends keeping every heading, to show the decision was deliberate (§4). A CPS is not automatically a contract; it binds only where another agreement brings it in (§3.4). RFC 3647 dates from 2003 and is US-centric; what a CPS means legally in a given country is a question for a lawyer.
Run your own CA or use an external one?
Running your own PKI gives full control, and makes you responsible for everything above. Relying parties outside your organization accept your certificates only if they add your root (RFC 5280, §6). An external CA may already be in the trust stores your relying parties use (ask which) and publishes its own CP and CPS; ask it this article’s questions: which policy, which status services, how fast. The same thinking applies to choosing an e-signature provider.
Mariama’s certificate is revoked, Ibrahima checks
- Mariama reports the theft through the channel her CA’s CPS names, and the CA confirms it is her.
- The CA revokes serial 1000 with reason keyCompromise, issues a new CRL with a higher CRL number, and its OCSP responder starts answering
revoked. - A contract arrives, signed with her old key after the theft. The signature is mathematically valid and the chain builds to Ibrahima’s root.
- His software finds serial 1000 on a current CRL, or gets a signed
revoked, and rejects the signature.
Had his software used a CRL from before step 2, it would have accepted the signature.
Try it: revoke a certificate, check a CRL and ask OCSP
A minimal CA built with openssl ca issues certificates to Mariama and Ibrahima, revokes Mariama’s, publishes a CRL and checks both against it, then asks an OCSP responder about each. To stay short, this demo uses one CA for everything: its key is online, it signs certificates, CRLs and OCSP responses, and its certificates carry no CRL distribution point or AIA. A real deployment splits these as described above. The manual calls openssl ca a “sample minimal CA application” that “does not have production quality” and advises keeping signing keys in an HSM or smart card (openssl-ca).
Save the scripts under each step as step1.sh, step2.sh and step3.sh in one directory and run this command from it. Your directory is mounted read-only; the CA’s keys and files stay in a throwaway container. Never reuse them.
Executable educational example · Docker · alpine:3.22 · OpenSSL 3.5.8 25 Aug 2026
docker run --rm --mount type=bind,src="$PWD",dst=/in,readonly -w /work alpine:3.22 sh -c '
apk add --no-cache openssl >/dev/null
openssl version
cp /in/step1.sh /in/step2.sh /in/step3.sh .
echo "### Step 1: a CA and two certificates ###"
sh step1.sh
echo "### Step 2: revoke, publish a CRL, check ###"
sh step2.sh
echo "### Step 3: an OCSP responder ###"
sh step3.sh
'
It prints the OpenSSL version, then each script’s output under a ### Step N ### line.
Step 1: a CA and two certificates
Executable educational example · Docker · alpine:3.22 · OpenSSL 3.5.8 25 Aug 2026
DS="dig""ital""Signature"
mkdir -p newcerts
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber
cat > ca.cnf <<CFG
[ca]
default_ca = CA_default
[CA_default]
dir = .
database = ./index.txt
serial = ./serial
crlnumber = ./crlnumber
new_certs_dir = ./newcerts
certificate = ./ca.pem
private_key = ./ca.key
default_md = sha256
default_days = 825
default_crl_days = 30
policy = policy_any
x509_extensions = usr_cert
copy_extensions = none
crl_extensions = crl_ext
[policy_any]
commonName = supplied
[req]
distinguished_name = req_dn
prompt = no
x509_extensions = v3_ca
[req_dn]
CN = Demo Root CA
[v3_ca]
basicConstraints = critical,CA:true
keyUsage = critical,keyCertSign,cRLSign
[usr_cert]
basicConstraints = CA:FALSE
keyUsage = ${DS},nonRepudiation
[ocsp]
basicConstraints = CA:FALSE
keyUsage = critical,${DS}
extendedKeyUsage = critical,OCSPSigning
[crl_ext]
authorityKeyIdentifier = keyid:always
CFG
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ca.key
openssl req -config ca.cnf -new -x509 -key ca.key -out ca.pem -days 3650
openssl x509 -in ca.pem -noout -subject -dates
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out mariama.key
openssl req -new -key mariama.key -out mariama.csr -subj "/CN=Mariama Diallo"
openssl ca -config ca.cnf -batch -notext -in mariama.csr -out mariama.pem
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ibrahima.key
openssl req -new -key ibrahima.key -out ibrahima.csr -subj "/CN=Ibrahima Bah"
openssl ca -config ca.cnf -batch -notext -in ibrahima.csr -out ibrahima.pem
openssl verify -CAfile ca.pem mariama.pem
openssl verify -CAfile ca.pem ibrahima.pem
openssl ca keeps its state in files: index.txt lists issued certificates, serial holds the next serial and crlnumber the next CRL number. copy_extensions = none matters: with copyall, a CSR asking for CA:TRUE could yield a working CA certificate (openssl-ca). The DS= line only works around a quirk of the capture tooling; you can type digitalSignature directly.
Expected output
OpenSSL 3.5.8 25 Aug 2026 (Library: OpenSSL 3.5.8 25 Aug 2026)
### Step 1: a CA and two certificates ###
subject=CN=Demo Root CA
notBefore=Sep 23 08:55:44 2026 GMT
notAfter=Sep 20 08:55:44 2036 GMT
Using configuration from ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'Mariama Diallo'
Certificate is to be certified until Dec 26 08:55:44 2028 GMT (825 days)
Write out database with 1 new entries
Database updated
Using configuration from ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'Ibrahima Bah'
Certificate is to be certified until Dec 26 08:55:44 2028 GMT (825 days)
Write out database with 1 new entries
Database updated
mariama.pem: OK
ibrahima.pem: OKEach openssl ca run checks the CSR’s signature, shows the subject and records the certificate in index.txt. Both certificates verify against the CA.
Step 2: revoke, publish a CRL, check
Executable educational example · Docker · alpine:3.22 · OpenSSL 3.5.8 25 Aug 2026
openssl ca -config ca.cnf -revoke mariama.pem -crl_reason keyCompromise
cat index.txt
openssl ca -config ca.cnf -gencrl -out crl.pem
openssl crl -in crl.pem -noout -text
cat ca.pem crl.pem > ca-chain.pem
openssl verify -crl_check -CAfile ca-chain.pem mariama.pem
echo "mariama exit=$?"
openssl verify -crl_check -CAfile ca-chain.pem ibrahima.pem
echo "ibrahima exit=$?"
openssl crl only prints the CRL that openssl ca -gencrl made (openssl-crl). openssl verify -crl_check checks the end-entity certificate against a CRL, and -crl_check_all the whole chain (openssl-verification-options). The CRL travels in the same -CAfile as the CA certificate (observed here; the documented option is -CRLfile) (openssl-verify).
Expected output
### Step 2: revoke, publish a CRL, check ###
Using configuration from ca.cnf
Revoking Certificate 1000.
Database updated
R 281226085544Z 260923085544Z,keyCompromise 1000 unknown /CN=Mariama Diallo
V 281226085544Z 1001 unknown /CN=Ibrahima Bah
Using configuration from ca.cnf
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN=Demo Root CA
Last Update: Sep 23 08:55:44 2026 GMT
Next Update: Oct 23 08:55:44 2026 GMT
CRL extensions:
X509v3 Authority Key Identifier:
5A:15:EC:BF:28:81:0B:6F:19:C6:4B:B6:A3:0A:74:6E:DC:F5:C2:D8
X509v3 CRL Number:
4096
Revoked Certificates:
Serial Number: 1000
Revocation Date: Sep 23 08:55:44 2026 GMT
CRL entry extensions:
X509v3 CRL Reason Code:
Key Compromise
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:46:02:21:00:b3:1f:45:39:94:d9:a5:0a:2c:0e:bc:96:22:
56:31:47:6d:47:d5:2c:29:90:b4:1f:74:ad:44:0b:f8:86:e1:
b8:02:21:00:e1:b1:a6:63:da:e3:71:d3:61:0f:5e:3b:6d:ae:
85:1c:81:1f:f3:55:69:a1:74:38:16:f0:d7:8e:7f:1b:63:e9
CN=Mariama Diallo
error 23 at 0 depth lookup: certificate revoked
error mariama.pem: verification failed
mariama exit=2
ibrahima.pem: OK
ibrahima exit=0-revoke flipped Mariama’s index.txt line from V to R, with time and reason; Ibrahima’s stays V. The printed CRL has what RFC 5280 requires of a conforming CA (§5): it is Version 2; Last Update and Next Update are thisUpdate and nextUpdate, 30 days apart because of default_crl_days; the Authority Key Identifier names the CA key that signed it; and the CRL Number, 4096, lets a verifier tell which CRL is newer. openssl ca adds the number only because the crlnumber file exists, and writes a version 2 CRL with the identifier only because of the crl_extensions section (openssl-ca).
For Mariama, error 23 at 0 depth lookup: certificate revoked, depth 0 being her own certificate, and exit status 2. Ibrahima’s passes against the same CRL. OpenSSL rejects a CRL whose nextUpdate has passed (error 12, CRL has expired), but it accepts any current CRL you hand it, even one issued before the revocation. Getting the latest CRL is your job.
Step 3: an OCSP responder
Executable educational example · Docker · alpine:3.22 · OpenSSL 3.5.8 25 Aug 2026
openssl ocsp -index index.txt -port 8080 -rsigner ca.pem -rkey ca.key -CA ca.pem -nrequest 2 -text -out responder.log &
RESPONDER_PID=$!
sleep 1
echo "=== query: mariama.pem (revoked) ==="
openssl ocsp -CAfile ca.pem -issuer ca.pem -cert mariama.pem -url http://127.0.0.1:8080 -resp_text -no_nonce | tail -n 15
echo "=== query: ibrahima.pem (good, not revoked) ==="
openssl ocsp -CAfile ca.pem -issuer ca.pem -cert ibrahima.pem -url http://127.0.0.1:8080 -resp_text -no_nonce | tail -n 15
wait $RESPONDER_PID 2>/dev/null
Given -index, openssl ocsp becomes a responder, which the manual says is “only useful for test and demonstration purposes” (openssl-ocsp). It runs in the background and exits after two requests (-nrequest 2). The CA’s own key signs the responses, which RFC 6960 allows. On the client, -issuer comes before -cert, and -no_nonce turns off the default nonce to keep the exchange minimal.
Expected output
### Step 3: an OCSP responder ###
ACCEPT 0.0.0.0:8080 PID=35
ocsp: waiting for OCSP client connections...
=== query: mariama.pem (revoked) ===
ocsp: received request, 1st line: POST / HTTP/1.0
ocsp: sending response, 1st line: HTTP/1.0 200 OK
Response verify OK
75:29:de:81:b5:28:1b:df:0e:8d:03:b9:d2:48:e0:41
-----BEGIN CERTIFICATE-----
MIIBcTCCARigAwIBAgIUfbAvE1eIfl/ZEa3LTsMWDPFrwMwwCgYIKoZIzj0EAwIw
FzEVMBMGA1UEAwwMRGVtbyBSb290IENBMB4XDTI2MDkyMzA4NTU0NFoXDTM2MDky
MDA4NTU0NFowFzEVMBMGA1UEAwwMRGVtbyBSb290IENBMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAE5/RwiFcQa5qkK6lO4Vf4/YGRMFhloWVVFX5LZsXqnheS63Zw
juGKh0SSZy0PWfTmTriWISJSm2z1b+9Hi5iDwqNCMEAwDwYDVR0TAQH/BAUwAwEB
/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFFoV7L8ogQtvGcZLtqMKdG7c9cLY
MAoGCCqGSM49BAMCA0cAMEQCIG1RdDajaYRqI8qNLl5Zv+klwvf5swgb+/FuZ5Ny
Wcx6AiBbGt3CqR9YgN9LRlvSUy3IdSnegbUoG98OjQO50kjgQQ==
-----END CERTIFICATE-----
mariama.pem: revoked
This Update: Sep 23 08:55:45 2026 GMT
Reason: keyCompromise
Revocation Time: Sep 23 08:55:44 2026 GMT
=== query: ibrahima.pem (good, not revoked) ===
ocsp: received request, 1st line: POST / HTTP/1.0
ocsp: sending response, 1st line: HTTP/1.0 200 OK
Response verify OK
bf:e9:25:c2:f7:f9:b3:08:1b:fb:f1:6e:67:93:72:59:cc:7a:
02:20:5b:1a:dd:c2:a9:1f:58:80:df:4b:46:5b:d2:53:2d:c8:
75:29:de:81:b5:28:1b:df:0e:8d:03:b9:d2:48:e0:41
-----BEGIN CERTIFICATE-----
MIIBcTCCARigAwIBAgIUfbAvE1eIfl/ZEa3LTsMWDPFrwMwwCgYIKoZIzj0EAwIw
FzEVMBMGA1UEAwwMRGVtbyBSb290IENBMB4XDTI2MDkyMzA4NTU0NFoXDTM2MDky
MDA4NTU0NFowFzEVMBMGA1UEAwwMRGVtbyBSb290IENBMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAE5/RwiFcQa5qkK6lO4Vf4/YGRMFhloWVVFX5LZsXqnheS63Zw
juGKh0SSZy0PWfTmTriWISJSm2z1b+9Hi5iDwqNCMEAwDwYDVR0TAQH/BAUwAwEB
/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFFoV7L8ogQtvGcZLtqMKdG7c9cLY
MAoGCCqGSM49BAMCA0cAMEQCIG1RdDajaYRqI8qNLl5Zv+klwvf5swgb+/FuZ5Ny
Wcx6AiBbGt3CqR9YgN9LRlvSUy3IdSnegbUoG98OjQO50kjgQQ==
-----END CERTIFICATE-----
ibrahima.pem: good
This Update: Sep 23 08:55:45 2026 GMTResponse verify OK means the response’s signature checked out against the trusted CA. Above the status, tail -n 15 leaves the end of the signature and the signer’s certificate. Then the status: revoked for Mariama, with the CRL’s keyCompromise reason, and good for Ibrahima. Without -ndays, responses carry no nextUpdate, so only a This Update line appears; with no nonce either, this demo has no replay protection. A real client keeps the nonce and a real responder sets nextUpdate.
Keys and signatures are random, so key identifiers, signature bytes and the certificate block differ on every run, and dates follow the clock. Serials are printed in hex (1000 and 1001, that is 4096 and 4097) and the CRL Number in decimal (4096); both come from the serial and crlnumber files that Step 1 starts at 1000, not from OpenSSL. The responder’s PID can differ too, and so can the OpenSSL version line, since alpine:3.22 tracks the latest 3.22.x build.
Where SEDEYA fits
SEDEYA signs PDFs in PAdES up to B-LTA, with RFC 3161 timestamps and the validation data embedded in the file; revocation information such as CRLs and OCSP responses is part of that data. Its signing keys are held in an HSM (PKCS#11) or a KMS. Ibrahima does not need openssl verify: he can upload the PDF to SEDEYA’s public verification page or scan its QR code. Later articles in this series cover the signing transaction and how long a signature stays verifiable.
Risks and misconceptions
“`openssl crl -gencrl` creates a CRL.”
-gencrl belongs to openssl ca. openssl crl has no such option (openssl-ca, openssl-crl).
“Once revoked, every relying party knows at once.”
A CRL shows it from the next scheduled issue (RFC 5280, §3.3). OCSP answers carry thisUpdate and
nextUpdate and may be pre-produced (RFC 6960, §2.4, §2.5).
“OCSP `good` proves the CA issued the certificate.”
good “does not necessarily mean that the certificate was ever issued” (RFC 6960, §2.2).
“`unknown` means revoked.”
unknown means this responder cannot say; it is not revoked. Whether missing status is fatal is
local policy (RFC 6960, §2.2). Error responses are not even signed (§2.3).
“The root must be offline because RFC 5280 says so.”
No RFC read for this article says so. Industry practice goes further than any RFC. The CA/Browser Forum, for public TLS CAs, requires root systems on separate networks under multi-party control (CABF-NSR, §1.2.1, §2.2.4).
“An OCSP nonce is at most 32 bytes.”
That was RFC 8954, now obsolete. RFC 9654 allows up to 128 octets and has requesters send at least 32 (§2.1).
Summary
- A private PKI commonly has an offline root that signs only CA certificates and CRLs, and an online issuing CA held to
pathlen:0, following industry practice rather than an RFC rule. - CA certificates need critical
basicConstraintswithCA:TRUEandkeyCertSign. CRL distribution points and AIA tell relying parties where to check status. - A CRL is a signed list of revoked serials, current until
nextUpdate. OCSP gives a signedgood,revokedorunknownper certificate. - In the hands-on, both the CRL check (error 23) and OCSP reported Mariama’s certificate revoked; Ibrahima’s stayed good.
- A CP says what a certificate is for and what participants must do; a CPS says how one CA does it.
Check your understanding
Check your understanding
Mariama's certificate was revoked on Monday. On Tuesday, Ibrahima's software checks it against a CRL issued the previous Friday, whose nextUpdate is next Friday. What does it conclude?
Show the answer
Not revoked. The Friday CRL is current by its own dates but predates the revocation. RFC 5280 leaves “suitably recent” to local policy; a stricter policy, a fresh CRL or an OCSP query would catch it.
Check your understanding
An OCSP responder answers unknown. Should Ibrahima reject the signature?
Show the answer
Not on that answer alone. unknown means this responder does not know the certificate. He should
get status elsewhere, such as the issuing CA’s CRL, and reject on revoked or when his policy
says missing status is fatal.
Check your understanding
Why can the issuing CA be online when the root stays offline?
Show the answer
If its key is compromised, the offline root can revoke it and sign a replacement, and its
pathlen:0 limits the damage to end-entity certificates. A root compromise has no such fallback:
every relying party must replace the trust anchor.
Next step
A certificate, a chain and a status check tell Ibrahima whose key signed and whether it was still good, but not what Mariama agreed to sign. Article 5 covers the signing transaction. Meanwhile, talk to us and we will show you a SEDEYA-signed PDF that carries its own validation data, and how anyone can verify it.
References
- Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile, RFC 5280, IETF, May 2008, updated by RFCs 6818, 8398, 8399, 9549, 9598, 9608, 9618, 9925, 10007 (§3.2, §3.3, §4.2.1.3, §4.2.1.9, §4.2.1.13, §4.2.2.1, §5, §5.1.2.4–5.1.2.6, §5.2.3, §5.3.1, §5.3.2, §6, §6.1)
- X.509 Internet Public Key Infrastructure Online Certificate Status Protocol (OCSP), RFC 6960, IETF, June 2013, updated by RFC 8954 and RFC 9654 (§2, §2.2–2.7, §3.1, §3.2, §4.1.1, §4.2.2.1, §4.2.2.2, §4.2.2.2.1, §4.4.4)
- Online Certificate Status Protocol (OCSP) Nonce Extension, RFC 9654, IETF, August 2024 (§2.1, §3.1)
- Internet X.509 Public Key Infrastructure Certificate Policy and Certification Practices Framework, RFC 3647, IETF, November 2003 (§2, §3.3.1, §3.4, §3.5, §3.7, §4, §4.5.2, §4.5.7, §4.6.1, §4.6.2, §7)
- Network and Certificate System Security Requirements, CA/Browser Forum, Version 2.0.5, 9 July 2025 (Definitions, §1.2.1, §2.2.4)
- Baseline Requirements for the Issuance and Management of Publicly-Trusted TLS Server Certificates, CA/Browser Forum, Version 2.3.0, 7 September 2026, as read from the servercert repository (§4.3.1.1, §5.2.2, §6.1.1.1)
- openssl-ca(1), OpenSSL Project, 3.5 (Description, CRL options, Configuration file options, Warnings)
- openssl-crl(1), OpenSSL Project, 3.5 (Synopsis)
- openssl-verify(1), OpenSSL Project, 3.5 (-CRLfile, -crl_download, Diagnostics)
- openssl-verification-options(1), OpenSSL Project, 3.5 (Trust Anchors, Certification Path Building, Certification Path Validation, -crl_check, -crl_check_all, -partial_chain, -x509_strict)
- openssl-ocsp(1), OpenSSL Project, 3.5 (OCSP Server Options, OCSP Response Verification, Notes, -issuer, -nonce)

