import { ErrorResult, Micro509Error } from "../result/result.js"; import { ParsedCertificate, ParsedName } from "../x509/parse.js"; import { CrlSource } from "./crl.js"; //#region src/revocation/ocsp.d.ts /** Hash algorithm used to compute OCSP CertID fields. RFC 9919 §3.1.1 requires SHA-256 for conforming clients; RFC 6960 defines no default. */ type OcspHashAlgorithm = "SHA-1" | "SHA-256"; /** PEM string, DER bytes, or already-parsed certificate. */ type OcspCertificateSource = string | Uint8Array | ParsedCertificate; /** PEM string, DER bytes, or already-parsed OCSP request. */ type OcspRequestSource = string | Uint8Array | ParsedOcspRequest; /** * One certificate whose status to query in an OCSP request. * Used as an element of {@linkcode CreateOcspRequestInput.requests}. */ interface CreateOcspRequestItemInput { /** Certificate whose revocation status is being queried. */ readonly certificate: OcspCertificateSource; /** Issuer of `certificate` — needed to compute the CertID hash. */ readonly issuerCertificate: OcspCertificateSource; } /** * Input for {@linkcode createOcspRequest}. */ interface CreateOcspRequestInput { /** One or more certificates to query (batched into a single OCSP request). */ readonly requests: readonly CreateOcspRequestItemInput[]; /** Hash algorithm for CertID computation. Defaults to `'SHA-256'`. */ readonly hashAlgorithm?: OcspHashAlgorithm; /** Random nonce for replay protection. Omit to skip the nonce extension. */ readonly nonce?: Uint8Array; } /** * Encoded OCSP request in multiple serialisation formats, returned by {@linkcode createOcspRequest}. */ interface OcspRequestMaterial { /** Raw DER bytes. */ readonly der: Uint8Array; /** PEM-encoded request (`-----BEGIN OCSP REQUEST-----`). */ readonly pem: string; /** Base64-encoded DER (no PEM armour). */ readonly base64: string; } /** * Decoded OCSP CertID — identifies a certificate by hashed issuer name, * hashed issuer key, and serial number. */ interface ParsedOcspCertId { /** OID of the hash algorithm used for the name and key hashes. */ readonly hashAlgorithmOid: string; /** Human-readable hash algorithm name (e.g. `"SHA-256"`). */ readonly hashAlgorithmName: string; /** Hex-encoded hash of the issuer's distinguished name DER. */ readonly issuerNameHashHex: string; /** Hex-encoded hash of the issuer's SubjectPublicKey BIT STRING content. */ readonly issuerKeyHashHex: string; /** Hex-encoded serial number of the certificate. */ readonly serialNumberHex: string; } /** * Decoded OCSP request, returned by {@linkcode parseOcspRequestDer} / {@linkcode parseOcspRequestPem}. */ interface ParsedOcspRequest { /** Original DER bytes when this object came from {@linkcode parseOcspRequestDer} or PEM parsing. */ readonly der?: Uint8Array; /** CertIDs of the certificates being queried. */ readonly requests: readonly ParsedOcspCertId[]; /** Hex-encoded nonce extension value, if present. */ readonly nonce?: string; } /** RFC 6960 certificate status reported by the responder for a single CertID. */ type OcspCertStatus = "good" | "revoked" | "unknown"; /** RFC 6960 overall response status — anything other than `'successful'` means the response body is absent or unusable. */ type OcspResponseStatus = "successful" | "malformedRequest" | "internalError" | "tryLater" | "sigRequired" | "unauthorized"; /** * Status of one certificate inside an OCSP BasicResponse. */ type ParsedOcspSingleResponse = { /** Which certificate this status applies to. */ readonly certId: ParsedOcspCertId; /** Start of the validity window for this status assertion. */ readonly thisUpdate: Date; /** End of the validity window. Absent if the responder does not commit to a schedule. */ readonly nextUpdate?: Date; } & ParsedOcspCertStatus; /** * RFC 6960 §4.2.1 `CertStatus ::= CHOICE { good [0] NULL, revoked [1] RevokedInfo, * unknown [2] UnknownInfo }`. * * Only `revoked` carries data, so `RevokedInfo`'s fields exist only on that * alternative. `revocationReasonCode` stays optional because `revocationReason` * is OPTIONAL within `RevokedInfo`. */ type ParsedOcspCertStatus = { /** Responder asserts the certificate is not revoked. */ readonly certStatus: "good"; } | { /** Responder asserts the certificate is revoked. */ readonly certStatus: "revoked"; /** `RevokedInfo.revocationTime`. */ readonly revokedAt: Date; /** `RevokedInfo.revocationReason` CRLReason integer, when present. */ readonly revocationReasonCode?: number; } | { /** Responder has no record of the certificate. */ readonly certStatus: "unknown"; }; /** * How the OCSP responder identifies itself — either by distinguished name or * by SHA-1 hash of its public key. */ type ParsedOcspResponderId = { /** Responder identified by its certificate subject name. */ readonly type: "byName"; /** Parsed distinguished name of the responder. */ readonly name: ParsedName; } | { /** Responder identified by public-key hash. */ readonly type: "byKeyHash"; /** Hex-encoded SHA-1 hash of the responder's SubjectPublicKey content. */ readonly keyHashHex: string; }; /** * Decoded OCSP response, returned by {@linkcode parseOcspResponseDer} / {@linkcode parseOcspResponsePem}. * * When `responseStatus` is not `'successful'`, most fields are absent. */ interface ParsedOcspResponse { /** Original DER bytes when this object came from {@linkcode parseOcspResponseDer} or PEM parsing. */ readonly der?: Uint8Array; /** Overall response status. Only `'successful'` carries a BasicOCSPResponse body. */ readonly responseStatus: OcspResponseStatus; /** OID of the response type (normally `id-pkix-ocsp-basic`). */ readonly responseTypeOid?: string; /** DER-encoded ResponseData — the signed payload for signature verification. */ readonly responseDataDer?: Uint8Array; /** How the responder identifies itself. */ readonly responderId?: ParsedOcspResponderId; /** OID of the algorithm used to sign this response. */ readonly signatureAlgorithmOid?: string; /** DER-encoded `parameters` field of the signature AlgorithmIdentifier. */ readonly signatureAlgorithmParametersDer?: Uint8Array; /** Human-readable signature algorithm name. */ readonly signatureAlgorithmName?: string; /** Raw signature bytes. */ readonly signatureValue?: Uint8Array; /** Timestamp when the responder produced this response. */ readonly producedAt?: Date; /** Per-certificate status entries. */ readonly responses?: readonly ParsedOcspSingleResponse[]; /** Hex-encoded nonce, if the response echoed one. */ readonly nonce?: string; /** Certificates embedded in the response (typically the responder's chain). */ readonly certificates?: readonly ParsedCertificate[]; } /** * One certificate's status entry for {@linkcode CreateOcspResponseInput.responses}. * Extends {@linkcode CreateOcspRequestItemInput} with status and timing fields. */ type CreateOcspSingleResponseInput = CreateOcspRequestItemInput & { /** Start of the validity window for this status assertion. Defaults to `new Date()`. */ readonly thisUpdate?: Date; /** End of the validity window. Omit for open-ended assertions. */ readonly nextUpdate?: Date; } & CreateOcspCertStatusInput; /** * Status to assert for one certificate, mirroring RFC 6960 §4.2.1 `CertStatus`. * * `RevokedInfo`'s fields are reachable only under `'revoked'`. */ type CreateOcspCertStatusInput = { /** Assert the certificate is not revoked. */ readonly certStatus: "good"; /** Unavailable unless `certStatus` is `'revoked'`. */ readonly revokedAt?: never; /** Unavailable unless `certStatus` is `'revoked'`. */ readonly revocationReasonCode?: never; } | { /** Assert the certificate is revoked. */ readonly certStatus: "revoked"; /** `RevokedInfo.revocationTime`. Defaults to `thisUpdate`. */ readonly revokedAt?: Date; /** `RevokedInfo.revocationReason` CRLReason integer code. */ readonly revocationReasonCode?: number; } | { /** Assert no record of the certificate exists. */ readonly certStatus: "unknown"; /** Unavailable unless `certStatus` is `'revoked'`. */ readonly revokedAt?: never; /** Unavailable unless `certStatus` is `'revoked'`. */ readonly revocationReasonCode?: never; }; /** Machine-readable reason an OCSP encoder rejected its construction input. */ type OcspEncoderErrorCode = "signer_certificate_key_mismatch"; /** * Input for {@linkcode createOcspResponse}. */ interface CreateOcspResponseInput { /** Private key used to sign the response. Algorithm is inferred from the key. */ readonly signerPrivateKey: CryptoKey; /** Certificate of the OCSP responder — used to build the responder ID (by key hash). */ readonly signerCertificate: OcspCertificateSource; /** Per-certificate status entries to include in the BasicOCSPResponse. */ readonly responses: readonly CreateOcspSingleResponseInput[]; /** Timestamp for the `producedAt` field. Defaults to `new Date()`. */ readonly producedAt?: Date; /** Nonce to echo back for replay protection. */ readonly nonce?: Uint8Array; /** Hash algorithm for CertID computation. Defaults to `'SHA-256'`. */ readonly hashAlgorithm?: OcspHashAlgorithm; /** Extra certificates to embed in the response (e.g. the responder's issuer chain). */ readonly includedCertificates?: readonly OcspCertificateSource[]; } /** * Encoded OCSP response in multiple serialisation formats, returned by {@linkcode createOcspResponse}. */ interface OcspResponseMaterial { /** Raw DER bytes. */ readonly der: Uint8Array; /** PEM-encoded response (`-----BEGIN OCSP RESPONSE-----`). */ readonly pem: string; /** Base64-encoded DER (no PEM armour). */ readonly base64: string; } /** Failure detail when OCSP response signature verification fails. */ interface VerifyOcspResponseSignatureFailure extends Micro509Error<"signature_invalid"> { /** Always `false` for failures. */ readonly ok: false; } /** * Result of {@linkcode verifyOcspResponseSignature}. * * On success, `value` is the parsed response whose signature has been verified. */ type VerifyOcspResponseSignatureResult = { readonly ok: true; /** Parsed response with a verified signature. */ readonly value: ParsedOcspResponse; } | ErrorResult<"signature_invalid", Record, VerifyOcspResponseSignatureFailure>; /** * Revocation policy for delegated OCSP responder certificates (RFC 6960 §4.2.2.2.1). * * - `'honor-nocheck'` (default): a responder carrying `id-pkix-ocsp-nocheck` * is exempt from revocation checking. Otherwise, CRL evidence from * {@linkcode ValidateOcspResponseInput.responderRevocationCrls} is consulted * when provided — a revoked responder rejects the response; missing or * unusable evidence is tolerated (soft). * - `'require-evidence'`: `nocheck` is ignored; CRL evidence must positively * show the responder is not revoked, otherwise the response is rejected. * - `'skip'`: no responder revocation checking. */ type OcspResponderRevocationPolicy = "honor-nocheck" | "require-evidence" | "skip"; /** * Input for {@linkcode validateOcspResponse}. */ interface ValidateOcspResponseInput { /** The OCSP response to validate. */ readonly response: string | Uint8Array | ParsedOcspResponse; /** Certificate of the CA that issued the target certificate. */ readonly issuerCertificate: OcspCertificateSource; /** Original request — enables nonce and request-coverage checks. */ readonly request?: OcspRequestSource; /** Explicit responder certificate — overrides embedded certificate discovery. */ readonly responderCertificate?: OcspCertificateSource; /** When `true`, allows delegated responder chain validation beyond direct issuance. */ readonly allowChainedResponderCertificate?: boolean; /** * Explicitly trusted responder certificates for this issuer's scope * (RFC 6960 §4.2.2.2 criterion 1 — local responder configuration). * * A response signer matching one of these certificates is accepted without * the delegated-responder issuance, chain, EKU, and revocation checks. * Signature verification and responder-ID binding are still enforced. * Also consulted during responder discovery when the response embeds no * matching certificate. */ readonly trustedOcspResponders?: readonly OcspCertificateSource[]; /** Revocation policy for delegated responder certificates. Defaults to `'honor-nocheck'`. */ readonly responderRevocationPolicy?: OcspResponderRevocationPolicy; /** CRLs used as revocation evidence for delegated responder certificates. */ readonly responderRevocationCrls?: readonly CrlSource[]; /** Evaluation time for freshness checks and delegated responder chain validation. Defaults to `new Date()`. */ readonly at?: Date; /** Clock-skew tolerance in milliseconds for `thisUpdate`/`nextUpdate`/`producedAt`. */ readonly clockSkewMs?: number; } /** Failure codes produced by {@linkcode validateOcspResponse}. */ type ValidateOcspResponseErrorCode = "response_status_invalid" | "signature_invalid" | "responder_id_mismatch" | "nonce_mismatch" | "request_mismatch" | "issuer_mismatch" | "responder_chain_invalid" | "ocsp_signing_missing" | "responder_revoked" | "responder_revocation_unknown" | "stale_response"; /** * Failure detail for {@linkcode validateOcspResponse}. * * Possible codes: `response_status_invalid`, `signature_invalid`, * `responder_id_mismatch`, `nonce_mismatch`, `request_mismatch`, * `issuer_mismatch`, `responder_chain_invalid`, `ocsp_signing_missing`, * `responder_revoked`, `responder_revocation_unknown`, `stale_response`. */ interface ValidateOcspResponseFailure extends Micro509Error { /** Always `false` for failures. */ readonly ok: false; } /** * Result of {@linkcode validateOcspResponse}. * * On success, the response has passed status, signature, responder binding, * authorization (including responder revocation policy), freshness, nonce, * and request-coverage checks. */ type ValidateOcspResponseResult = { readonly ok: true; /** Fully validated OCSP response. */ readonly value: ParsedOcspResponse; } | ErrorResult, ValidateOcspResponseFailure>; /** * Builds a DER-encoded OCSP request containing one or more CertID entries * and an optional nonce extension. * * @example * ```ts * import { createOcspRequest } from 'micro509'; * * const req = await createOcspRequest({ * requests: [{ certificate: leafPem, issuerCertificate: caPem }], * hashAlgorithm: 'SHA-256', * nonce: crypto.getRandomValues(new Uint8Array(16)), * }); * // POST req.der to the OCSP responder URI * ``` */ declare function createOcspRequest(input: CreateOcspRequestInput): Promise; /** Machine-readable failure reason for the OCSP request parsers. */ type ParseOcspRequestErrorCode = "malformed"; /** Structured failure payload for OCSP request parsing. */ interface ParseOcspRequestFailure extends Micro509Error { /** Always `false` for failures. */ readonly ok: false; } /** Success-or-failure result from {@linkcode parseOcspRequestDer} / {@linkcode parseOcspRequestPem}. */ type ParseOcspRequestResult = { readonly ok: true; readonly value: ParsedOcspRequest; } | ErrorResult, ParseOcspRequestFailure>; /** Throwing core for {@linkcode parseOcspRequestDer}. */ declare function parseOcspRequestDerOrThrow(der: Uint8Array): ParsedOcspRequest; /** Decodes a PEM-encoded OCSP request (`-----BEGIN OCSP REQUEST-----`). */ declare function parseOcspRequestPemOrThrow(pem: string): ParsedOcspRequest; /** * Decodes a DER-encoded OCSP request into a structured {@linkcode ParsedOcspRequest}. * * Returns a typed failure (`code: 'malformed'`) on malformed input. For the * throwing form use {@linkcode parseOcspRequestDerOrThrow}. */ declare function parseOcspRequestDer(der: Uint8Array): ParseOcspRequestResult; /** * Decodes a PEM-encoded OCSP request (`-----BEGIN OCSP REQUEST-----`). * * Returns a typed failure (`code: 'malformed'`) on malformed input. For the * throwing form use {@linkcode parseOcspRequestPemOrThrow}. */ declare function parseOcspRequestPem(pem: string): ParseOcspRequestResult; /** Machine-readable failure reason for the OCSP response parsers. */ type ParseOcspResponseErrorCode = "malformed"; /** Structured failure payload for OCSP response parsing. */ interface ParseOcspResponseFailure extends Micro509Error { /** Always `false` for failures. */ readonly ok: false; } /** Success-or-failure result from {@linkcode parseOcspResponseDer} / {@linkcode parseOcspResponsePem}. */ type ParseOcspResponseResult = { readonly ok: true; readonly value: ParsedOcspResponse; } | ErrorResult, ParseOcspResponseFailure>; /** Throwing core for {@linkcode parseOcspResponseDer}. */ declare function parseOcspResponseDerOrThrow(der: Uint8Array): ParsedOcspResponse; /** * Decodes a PEM-encoded OCSP response (`-----BEGIN OCSP RESPONSE-----`). * * @example * ```ts * import { parseOcspResponsePemOrThrow } from 'micro509'; * * const resp = parseOcspResponsePemOrThrow(pemString); * if (resp.responseStatus === 'successful') { * for (const entry of resp.responses ?? []) { * console.log(entry.certId.serialNumberHex, entry.certStatus); * } * } * ``` */ declare function parseOcspResponsePemOrThrow(pem: string): ParsedOcspResponse; /** * Decodes a DER-encoded OCSP response into a structured {@linkcode ParsedOcspResponse}. * * Returns a typed failure (`code: 'malformed'`) on malformed input. For the * throwing form use {@linkcode parseOcspResponseDerOrThrow}. */ declare function parseOcspResponseDer(der: Uint8Array): ParseOcspResponseResult; /** * Decodes a PEM-encoded OCSP response (`-----BEGIN OCSP RESPONSE-----`). * * Returns a typed failure (`code: 'malformed'`) on malformed input. For the * throwing form use {@linkcode parseOcspResponsePemOrThrow}. */ declare function parseOcspResponsePem(pem: string): ParseOcspResponseResult; /** * Signs and encodes an OCSP BasicResponse with a `successful` status. * * The responder is identified by key hash (SHA-1 of the signer's SubjectPublicKey). * Use `includedCertificates` to embed the responder's chain for relying parties. * * @example * ```ts * import { createOcspResponse } from 'micro509'; * * const resp = await createOcspResponse({ * signerPrivateKey: responderPrivateKey, * signerCertificate: responderCertPem, * responses: [ * { * certificate: leafPem, * issuerCertificate: caPem, * certStatus: 'good', * thisUpdate: new Date('2025-01-01'), * nextUpdate: new Date('2025-01-08'), * }, * ], * nonce: requestNonce, * }); * // resp.der, resp.pem, resp.base64 * ``` */ declare function createOcspResponse(input: CreateOcspResponseInput): Promise; /** * Verifies the OCSP response signature against the given signer certificate. * * Does **not** check responder binding, freshness, or nonce — use * {@linkcode validateOcspResponse} for full validation. */ declare function verifyOcspResponseSignature(response: string | Uint8Array | ParsedOcspResponse, signerCertificate: OcspCertificateSource): Promise; /** * Full OCSP response validation: response status check, signature verification, * responder ID binding (byName or byKeyHash), delegated-responder chain and * ocspSigning EKU checks, `producedAt`/`thisUpdate`/`nextUpdate` freshness, * nonce match, and request-coverage completeness. * * @example * ```ts * import { validateOcspResponse } from 'micro509'; * * const result = await validateOcspResponse({ * response: ocspResponseDer, * issuerCertificate: caPem, * request: ocspRequestDer, * }); * if (result.ok) { * const entry = result.value.responses?.[0]; * console.log(entry?.certStatus); // 'good' | 'revoked' | 'unknown' * } * ``` */ declare function validateOcspResponse(input: ValidateOcspResponseInput): Promise; /** * Reports whether a certificate carries the `id-pkix-ocsp-nocheck` extension * (RFC 6960 §4.2.2.2.1) — the CA's assertion that relying parties may trust * this OCSP responder certificate for its lifetime without revocation checks. */ declare function hasOcspNoCheckExtension(certificate: OcspCertificateSource): boolean; //#endregion export { CreateOcspCertStatusInput, CreateOcspRequestInput, CreateOcspRequestItemInput, CreateOcspResponseInput, CreateOcspSingleResponseInput, OcspCertStatus, OcspCertificateSource, OcspEncoderErrorCode, OcspHashAlgorithm, OcspRequestMaterial, OcspRequestSource, OcspResponderRevocationPolicy, OcspResponseMaterial, OcspResponseStatus, ParseOcspRequestErrorCode, ParseOcspRequestFailure, ParseOcspRequestResult, ParseOcspResponseErrorCode, ParseOcspResponseFailure, ParseOcspResponseResult, ParsedOcspCertId, ParsedOcspCertStatus, ParsedOcspRequest, ParsedOcspResponderId, ParsedOcspResponse, ParsedOcspSingleResponse, ValidateOcspResponseErrorCode, ValidateOcspResponseFailure, ValidateOcspResponseInput, ValidateOcspResponseResult, VerifyOcspResponseSignatureFailure, VerifyOcspResponseSignatureResult, createOcspRequest, createOcspResponse, hasOcspNoCheckExtension, parseOcspRequestDer, parseOcspRequestDerOrThrow, parseOcspRequestPem, parseOcspRequestPemOrThrow, parseOcspResponseDer, parseOcspResponseDerOrThrow, parseOcspResponsePem, parseOcspResponsePemOrThrow, validateOcspResponse, verifyOcspResponseSignature }; //# sourceMappingURL=ocsp.d.ts.map