import { ErrorResult, Micro509Error } from "../result/result.js"; import { ImportKeyResult, PublicKeyImportInput } from "../keys/keys.js"; import { NameFieldKey } from "./name.js"; import { AuthorityInformationAccess, BasicConstraints, CertificatePolicies, DistributionPointReason, ExtendedKeyUsage, GeneralName, GeneralSubtree, InhibitAnyPolicy, KeyUsage, NameConstraints, ParsedBitFlags, ParsedNameConstraintForm, PolicyConstraints, PolicyMappings, SubjectAltName } from "./extensions.js"; //#region src/x509/parse.d.ts /** Machine-readable failure reason for {@linkcode parseCertificateDer} / {@linkcode parseCertificatePem}. */ type ParseCertificateErrorCode = "malformed"; /** Structured failure payload for certificate parsing. */ interface ParseCertificateFailure extends Micro509Error { /** Always `false` for failures. */ readonly ok: false; } /** Success-or-failure result from {@linkcode parseCertificateDer} / {@linkcode parseCertificatePem}. */ type ParseCertificateResult> = { readonly ok: true; readonly value: ParsedCertificate; } | ErrorResult, ParseCertificateFailure>; /** Success-or-failure result from {@linkcode parseCertificateChainPem}. */ type ParseCertificateChainResult> = { readonly ok: true; readonly value: readonly ParsedCertificate[]; } | ErrorResult, ParseCertificateFailure>; /** Machine-readable failure reason for the CSR parsers. */ type ParseCertificateSigningRequestErrorCode = "malformed"; /** Structured failure payload for CSR parsing. */ interface ParseCertificateSigningRequestFailure extends Micro509Error { /** Always `false` for failures. */ readonly ok: false; } /** * Success-or-failure result from {@linkcode parseCertificateSigningRequestDer} / * {@linkcode parseCertificateSigningRequestPem}. */ type ParseCertificateSigningRequestResult> = { readonly ok: true; readonly value: ParsedCertificateSigningRequest; } | ErrorResult, ParseCertificateSigningRequestFailure>; /** * A single decoded name attribute from an X.501 RelativeDistinguishedName. * * RFC 5280 / X.501 call this structure an `AttributeTypeAndValue`. * * @see {@link https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1 RFC 5280 Appendix A.1} */ interface ParsedNameAttribute { /** Dotted-decimal OID of the attribute type (e.g. `"2.5.4.3"` for CN). */ readonly oid: string; /** Friendly key when the OID maps to a well-known field (CN, O, etc.). */ readonly key?: NameFieldKey; /** ASN.1 tag of the value encoding (UTF8String = 0x0c, PrintableString = 0x13, etc.). */ readonly valueTag: number; /** Decoded string content of the attribute value. */ readonly value: string; } /** * An X.501 Distinguished Name decoded from an issuer or subject field. * * Provides three views of the same data: ordered RDNs, a flat attribute * list, and a convenience key-value map for well-known fields. */ interface ParsedName { /** Hex-encoded DER of the complete Name SEQUENCE, usable for byte-exact comparisons. */ readonly derHex: string; /** Ordered list of RelativeDistinguishedNames, preserving multi-valued RDN structure. */ readonly rdns: readonly ParsedRelativeDistinguishedName[]; /** Flat list of every attribute across all RDNs, in encounter order. */ readonly attributes: readonly ParsedNameAttribute[]; /** First-occurrence map of well-known fields (CN, O, OU, etc.) for quick lookups. */ readonly values: Readonly>>; } /** A single RelativeDistinguishedName SET from an X.501 Name. */ interface ParsedRelativeDistinguishedName { /** Hex-encoded DER of this RDN SET element. */ readonly derHex: string; /** Attributes within this RDN (usually one, but multi-valued RDNs are legal). */ readonly attributes: readonly ParsedNameAttribute[]; /** First-occurrence map of well-known fields within this RDN. */ readonly values: Readonly>>; } /** * The name component of a CRL Distribution Point, mirroring RFC 5280 §4.2.1.13 * `DistributionPointName ::= CHOICE { fullName [0] GeneralNames, * nameRelativeToCRLIssuer [1] RelativeDistinguishedName }`. */ type ParsedDistributionPointName = { /** The `fullName [0]` alternative. */ readonly type: "fullName"; /** Absolute GeneralName(s) identifying the distribution point. */ readonly fullName: readonly GeneralName[]; } | { /** The `nameRelativeToCRLIssuer [1]` alternative. */ readonly type: "relativeName"; /** Name relative to the CRL issuer's distinguished name. */ readonly relativeName: ParsedRelativeDistinguishedName; }; /** A decoded DistributionPoint from the CRL Distribution Points extension. */ interface ParsedDistributionPoint { /** Where to fetch the CRL — a fullName URI or relativeName. */ readonly distributionPoint?: ParsedDistributionPointName; /** Revocation reason subset this distribution point covers. Absent means all reasons. */ readonly reasons?: ParsedBitFlags; /** Entity that signed the CRL, when different from the certificate issuer. */ readonly crlIssuer?: readonly GeneralName[]; } /** * Decoded Issuing Distribution Point CRL extension (RFC 5280 §5.2.5). * Constrains which certificates a CRL covers (scope, reasons, indirection). */ type ParsedIssuingDistributionPoint = ParsedIssuingDistributionPointBase & ParsedIssuingDistributionPointScope; /** Scope-independent fields of a decoded Issuing Distribution Point. */ interface ParsedIssuingDistributionPointBase { /** Where to fetch this CRL, if specified. */ readonly distributionPoint?: ParsedDistributionPointName; /** Limits the CRL to these revocation reasons. Absent means all reasons. */ readonly onlySomeReasons?: ParsedBitFlags; /** When true, this CRL may contain entries from CAs other than the issuer. Default false. */ readonly indirectCrl?: boolean; } /** * Which certificate kind a CRL is scoped to. RFC 5280 §5.2.5 allows at most one * of `onlyContainsUserCerts`, `onlyContainsCACerts`, and * `onlyContainsAttributeCerts` to be TRUE, so the union admits one at a time. * * A flag is absent when the encoding omitted it and `false` when the encoding * carried an explicit FALSE. */ type ParsedIssuingDistributionPointScope = { /** No scope restriction; this CRL covers every certificate kind. */ readonly onlyContainsUserCerts?: false; /** No scope restriction. */ readonly onlyContainsCACerts?: false; /** No scope restriction. */ readonly onlyContainsAttributeCerts?: false; } | { /** This CRL only covers end-entity certificates. */ readonly onlyContainsUserCerts: true; /** Excluded by the user-cert scope. */ readonly onlyContainsCACerts?: false; /** Excluded by the user-cert scope. */ readonly onlyContainsAttributeCerts?: false; } | { /** Excluded by the CA-cert scope. */ readonly onlyContainsUserCerts?: false; /** This CRL only covers CA certificates. */ readonly onlyContainsCACerts: true; /** Excluded by the CA-cert scope. */ readonly onlyContainsAttributeCerts?: false; } | { /** Excluded by the attribute-cert scope. */ readonly onlyContainsUserCerts?: false; /** Excluded by the attribute-cert scope. */ readonly onlyContainsCACerts?: false; /** This CRL only covers attribute certificates. */ readonly onlyContainsAttributeCerts: true; }; /** A raw X.509v3 extension before type-specific decoding. */ interface ParsedExtension { /** Dotted-decimal OID identifying this extension. */ readonly oid: string; /** Whether a validator MUST reject the certificate if it cannot process this extension. */ readonly critical: boolean; /** DER-encoded OCTET STRING payload (extnValue). */ readonly valueDer: Uint8Array; /** Hex-encoded form of `valueDer` for display and comparison. */ readonly valueHex: string; } /** * User-supplied decoder for a single extension OID. * * Register with {@linkcode ParseOptions.decoders} or {@linkcode ParseOptions.decoderMap} * to decode custom extensions during parsing. */ interface ExtensionDecoder { /** OID this decoder handles. */ readonly oid: string; /** Decode the raw {@linkcode ParsedExtension} into a typed value. */ decode(extension: ParsedExtension): TValue; } /** * Identity helper that narrows the type of a custom {@linkcode ExtensionDecoder} literal. * * @param decoder Decoder definition to return unchanged. * @returns The same decoder, properly typed. */ declare function defineExtensionDecoder(decoder: ExtensionDecoder): ExtensionDecoder; /** * Identity helper that narrows the type of a custom {@linkcode ExtensionDecoderMap} literal. * * @param decoderMap Map of named decoders to return unchanged. * @returns The same map, properly typed. */ declare function defineExtensionDecoderMap(decoderMap: TMap): TMap; /** String-keyed map of {@linkcode ExtensionDecoder}s, used with {@linkcode ParseOptions.decoderMap}. */ type ExtensionDecoderMap = Record>; /** Inferred result type when decoding extensions via an {@linkcode ExtensionDecoderMap}. */ type DecodedExtensionMap = { [TKey in keyof TMap]?: TMap[TKey] extends ExtensionDecoder ? DecodedExtensionValue : never; }; /** A successfully decoded extension value paired with its OID and criticality. */ interface DecodedExtensionValue { /** Dotted-decimal OID of the decoded extension. */ readonly oid: string; /** Whether the extension was marked critical in the certificate. */ readonly critical: boolean; /** Typed value produced by the {@linkcode ExtensionDecoder}. */ readonly value: TValue; } /** * Options for {@linkcode parseCertificateDer}, {@linkcode parseCertificatePem}, * and CSR parse functions. * * Supply custom extension decoders to have their results included in the parsed output alongside * the built-in extensions. */ interface ParseOptions> { /** Array of decoders; decoded values appear in `decodedExtensions`. */ readonly decoders?: readonly ExtensionDecoder[]; /** Named decoder map; decoded values appear in `decodedExtensionMap` keyed by map key. */ readonly decoderMap?: TMap; } /** * A fully decoded X.509 certificate. * * Built-in extensions (basicConstraints, keyUsage, etc.) are decoded into * typed fields automatically.\ * Supply {@linkcode ParseOptions} to also decode custom extensions. */ interface ParsedCertificate> { /** Complete DER encoding of the certificate (copied from the input). */ readonly der: Uint8Array; /** X.509 version number (1, 2, or 3). Almost always 3. */ readonly version: number; /** Hex-encoded serial number assigned by the issuing CA. */ readonly serialNumberHex: string; /** DER encoding of the TBSCertificate, used for signature verification. */ readonly tbsCertificateDer: Uint8Array; /** DER encoding of the SubjectPublicKeyInfo, used for key import. */ readonly subjectPublicKeyInfoDer: Uint8Array; /** Raw signature bytes (BIT STRING content, padding removed). */ readonly signatureValue: Uint8Array; /** Distinguished name of the certificate issuer. */ readonly issuer: ParsedName; /** Distinguished name of the certificate subject. */ readonly subject: ParsedName; /** Start of the certificate validity period. */ readonly notBefore: Date; /** End of the certificate validity period. */ readonly notAfter: Date; /** OID of the algorithm used to sign this certificate (e.g. `"1.2.840.113549.1.1.11"` for SHA-256 with RSA). */ readonly signatureAlgorithmOid: string; /** Human-readable signature algorithm name (e.g. `"ECDSA with SHA-256"`). */ readonly signatureAlgorithmName: string; /** DER-encoded parameters for the signature algorithm. Absent for algorithms with no parameters. */ readonly signatureAlgorithmParametersDer?: Uint8Array; /** OID of the subject's public key algorithm (e.g. `"1.2.840.10045.2.1"` for EC). */ readonly publicKeyAlgorithmOid: string; /** Human-readable public key algorithm name (e.g. `"EC P-256"`). */ readonly publicKeyAlgorithmName: string; /** DER-encoded parameters for the public key algorithm. Absent when implicit. */ readonly publicKeyAlgorithmParametersDer?: Uint8Array; /** OID of the named curve or other key sub-parameter, when present. */ readonly publicKeyParametersOid?: string; /** All extensions as raw {@linkcode ParsedExtension}s, in certificate order. */ readonly extensions: readonly ParsedExtension[]; /** Decoded Basic Constraints (RFC 5280 §4.2.1.9). */ readonly basicConstraints?: BasicConstraints; /** Decoded Key Usage bit flags (RFC 5280 §4.2.1.3). */ readonly keyUsage?: ParsedBitFlags; /** Decoded Extended Key Usage purposes (RFC 5280 §4.2.1.12). */ readonly extendedKeyUsage?: readonly ExtendedKeyUsage[]; /** Decoded Subject Alternative Names (RFC 5280 §4.2.1.6). */ readonly subjectAltNames?: readonly SubjectAltName[]; /** Decoded Issuer Alternative Names (RFC 5280 §4.2.1.7). */ readonly issuerAltNames?: readonly SubjectAltName[]; /** Decoded Name Constraints (RFC 5280 §4.2.1.10). */ readonly nameConstraints?: NameConstraints; /** Decoded Certificate Policies (RFC 5280 §4.2.1.4). */ readonly certificatePolicies?: CertificatePolicies; /** Decoded Policy Mappings (RFC 5280 §4.2.1.5). */ readonly policyMappings?: PolicyMappings; /** Decoded Policy Constraints (RFC 5280 §4.2.1.11). */ readonly policyConstraints?: PolicyConstraints; /** Decoded Inhibit anyPolicy (RFC 5280 §4.2.1.14). */ readonly inhibitAnyPolicy?: InhibitAnyPolicy; /** Decoded Authority Information Access — GeneralName access locations (RFC 5280 §4.2.2.1). */ readonly authorityInfoAccess?: readonly AuthorityInformationAccess[]; /** Decoded CRL Distribution Points (RFC 5280 §4.2.1.13). */ readonly crlDistributionPoints?: readonly ParsedDistributionPoint[]; /** Custom-decoded extensions from {@linkcode ParseOptions.decoders}. */ readonly decodedExtensions?: readonly DecodedExtensionValue[]; /** Custom-decoded extensions from {@linkcode ParseOptions.decoderMap}, keyed by map key. */ readonly decodedExtensionMap?: DecodedExtensionMap; /** Hex-encoded Subject Key Identifier (RFC 5280 §4.2.1.2). */ readonly subjectKeyIdentifier?: string; /** Hex-encoded Authority Key Identifier (RFC 5280 §4.2.1.1). */ readonly authorityKeyIdentifier?: string; } /** * A fully decoded PKCS#10 Certificate Signing Request. * * Extension fields mirror {@linkcode ParsedCertificate} but come from the * CSR's extensionRequest attribute rather than the v3 extensions block. */ interface ParsedCertificateSigningRequest> { /** PKCS#10 version, normalized to the v1 ordinal `1`. The encoded CertificationRequestInfo version INTEGER is `0` (RFC 2986 §4.1). */ readonly version: number; /** DER encoding of the CertificationRequestInfo, used for signature verification. */ readonly certificationRequestInfoDer: Uint8Array; /** DER encoding of the SubjectPublicKeyInfo. */ readonly subjectPublicKeyInfoDer: Uint8Array; /** Raw signature bytes (BIT STRING content, padding removed). */ readonly signatureValue: Uint8Array; /** Distinguished name the requester wants on the certificate. */ readonly subject: ParsedName; /** OID of the algorithm used to sign this CSR. */ readonly signatureAlgorithmOid: string; /** Human-readable signature algorithm name (e.g. `"ECDSA with SHA-256"`). */ readonly signatureAlgorithmName: string; /** DER-encoded parameters for the signature algorithm. Absent for algorithms with no parameters. */ readonly signatureAlgorithmParametersDer?: Uint8Array; /** OID of the subject's public key algorithm. */ readonly publicKeyAlgorithmOid: string; /** Human-readable public key algorithm name (e.g. `"EC P-256"`). */ readonly publicKeyAlgorithmName: string; /** DER-encoded parameters for the public key algorithm. */ readonly publicKeyAlgorithmParametersDer?: Uint8Array; /** OID of the named curve or other key sub-parameter, when present. */ readonly publicKeyParametersOid?: string; /** All requested extensions as raw {@linkcode ParsedExtension}s. */ readonly requestedExtensions: readonly ParsedExtension[]; /** Decoded Basic Constraints from the extensionRequest attribute. */ readonly basicConstraints?: BasicConstraints; /** Decoded Key Usage from the extensionRequest attribute. */ readonly keyUsage?: ParsedBitFlags; /** Decoded Extended Key Usage from the extensionRequest attribute. */ readonly extendedKeyUsage?: readonly ExtendedKeyUsage[]; /** Decoded Subject Alternative Names from the extensionRequest attribute. */ readonly subjectAltNames?: readonly SubjectAltName[]; /** Decoded Name Constraints from the extensionRequest attribute. */ readonly nameConstraints?: NameConstraints; /** Decoded Certificate Policies from the extensionRequest attribute. */ readonly certificatePolicies?: CertificatePolicies; /** Decoded Policy Mappings from the extensionRequest attribute. */ readonly policyMappings?: PolicyMappings; /** Decoded Policy Constraints from the extensionRequest attribute. */ readonly policyConstraints?: PolicyConstraints; /** Decoded Inhibit anyPolicy from the extensionRequest attribute. */ readonly inhibitAnyPolicy?: InhibitAnyPolicy; /** Decoded Authority Information Access from the extensionRequest attribute. */ readonly authorityInfoAccess?: readonly AuthorityInformationAccess[]; /** Decoded CRL Distribution Points from the extensionRequest attribute. */ readonly crlDistributionPoints?: readonly ParsedDistributionPoint[]; /** Custom-decoded extensions from {@linkcode ParseOptions.decoders}. */ readonly decodedExtensions?: readonly DecodedExtensionValue[]; /** Custom-decoded extensions from {@linkcode ParseOptions.decoderMap}. */ readonly decodedExtensionMap?: DecodedExtensionMap; } /** * Throwing core for {@linkcode parseCertificateDer}. * * Decodes a DER-encoded X.509 certificate into a {@linkcode ParsedCertificate}, * throwing on malformed input. All built-in extensions (basicConstraints, * keyUsage, subjectAltNames, etc.) are decoded automatically.\ * Pass {@linkcode ParseOptions} to also decode custom extensions. * * @param der Raw DER bytes of an X.509 certificate. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateDerOrThrow>(der: Uint8Array, options?: ParseOptions): ParsedCertificate; /** * Decode a DER-encoded X.509 certificate into a {@linkcode ParsedCertificate}. * * @example * ```ts * import { parseCertificateDer } from 'micro509'; * * const result = parseCertificateDer(derBytes); * if (result.ok) { * console.log(result.value.subject.values.commonName); // "example.com" * } * ``` * * @param der Raw DER bytes of an X.509 certificate. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateDer>(der: Uint8Array, options?: ParseOptions): ParseCertificateResult; /** * Decode a PEM-encoded X.509 certificate into a {@linkcode ParsedCertificate}. * * Expects a single `-----BEGIN CERTIFICATE-----` block. For bundles * containing multiple certificates, use {@linkcode parseCertificateChainPem}. * * @example * Throws on malformed input. For a typed failure instead, use the * Result-returning {@linkcode parseCertificatePem}. * * ```ts * const certificate = parseCertificatePemOrThrow(pemString); // throws if malformed * console.log(certificate.issuer.values.organization); // "Let's Encrypt" * ``` * * @param pem PEM string with a CERTIFICATE block. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificatePemOrThrow>(pem: string, options?: ParseOptions): ParsedCertificate; /** * Decode a PEM-encoded X.509 certificate into a {@linkcode ParsedCertificate}. * * Expects a single `-----BEGIN CERTIFICATE-----` block. For bundles * containing multiple certificates, use {@linkcode parseCertificateChainPem}. * * **Synchronous:** returns a {@linkcode ParseCertificateResult} directly. Do * not `await` this function. * * @param pem PEM string with a CERTIFICATE block. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificatePem>(pem: string, options?: ParseOptions): ParseCertificateResult; /** Normalizes a PEM bundle or single DER certificate source into parsed certificates. */ declare function parseCertificatesFromSource>(source: string | Uint8Array, options?: ParseOptions): readonly ParsedCertificate[]; /** Normalizes a PEM, DER, or already-parsed certificate source into one parsed certificate. */ declare function parseCertificateFromSource>(source: ParsedCertificate | string | Uint8Array, options?: ParseOptions): ParsedCertificate; /** * Decode a PEM bundle containing one or more certificates, throwing on malformed input. * * Non-CERTIFICATE blocks (e.g. private keys) are silently skipped. * * @param pemBundle PEM text that may contain multiple CERTIFICATE blocks. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateChainPemOrThrow>(pemBundle: string, options?: ParseOptions): readonly ParsedCertificate[]; /** * Decode a PEM bundle containing one or more certificates. * * Non-CERTIFICATE blocks (e.g. private keys) are silently skipped. Returns a * typed `malformed` failure for invalid PEM or certificate DER. * * @param pemBundle PEM text that may contain multiple CERTIFICATE blocks. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateChainPem>(pemBundle: string, options?: ParseOptions): ParseCertificateChainResult; /** * Decode a DER-encoded PKCS#10 CSR into a {@linkcode ParsedCertificateSigningRequest}. * * @param der Raw DER bytes of a PKCS#10 certificate signing request. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateSigningRequestDerOrThrow>(der: Uint8Array, options?: ParseOptions): ParsedCertificateSigningRequest; /** * Decode a DER-encoded PKCS#10 CSR into a {@linkcode ParsedCertificateSigningRequest}. * * @param der Raw DER bytes of a PKCS#10 certificate signing request. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateSigningRequestDer>(der: Uint8Array, options?: ParseOptions): ParseCertificateSigningRequestResult; /** * Decode a PEM-encoded PKCS#10 CSR into a {@linkcode ParsedCertificateSigningRequest}. * * @param pem PEM string with a CERTIFICATE REQUEST block. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateSigningRequestPemOrThrow>(pem: string, options?: ParseOptions): ParsedCertificateSigningRequest; /** * Decode a PEM-encoded PKCS#10 CSR into a {@linkcode ParsedCertificateSigningRequest}. * * @param pem PEM string with a CERTIFICATE REQUEST block. * @param options Custom extension decoders to apply during parsing. */ declare function parseCertificateSigningRequestPem>(pem: string, options?: ParseOptions): ParseCertificateSigningRequestResult; /** * Import the subject public key of a parsed certificate or CSR as a WebCrypto `CryptoKey`. * * The key algorithm — and, for EC keys, the curve — is inferred from the * SubjectPublicKeyInfo's own AlgorithmIdentifier (the same resolution * {@linkcode importSpkiDerOrThrow} applies when no algorithm is given), so * callers never map {@linkcode ParsedCertificate.publicKeyAlgorithmOid} / * {@linkcode ParsedCertificate.publicKeyParametersOid} by hand.\ * RSA keys import with the default `pkcs1-v1_5`/`SHA-256` parameters (a plain * `rsaEncryption` SPKI encodes neither padding scheme nor hash); pass * `algorithm` to choose other RSA parameters or to assert an expected * algorithm. * * @param parsed Parsed certificate or CSR whose subject public key to import. * @param algorithm Optional expected algorithm; must match the key contents when given. * @returns Extractable `CryptoKey` with `verify` usage. * * @throws {Error} If the SubjectPublicKeyInfo is malformed, encodes an * unsupported algorithm, or doesn't match `algorithm` * * @example * ```ts * const parsed = parseCertificatePemOrThrow(pem); * const publicKey = await getSubjectPublicKeyOrThrow(parsed); * ``` * * @see {@linkcode getSubjectPublicKey} for the non-throwing variant */ declare function getSubjectPublicKeyOrThrow>(parsed: ParsedCertificate | ParsedCertificateSigningRequest, algorithm?: PublicKeyImportInput): Promise; /** * Import the subject public key of a parsed certificate or CSR as a WebCrypto `CryptoKey`. * * @see `getSubjectPublicKeyOrThrow` for the throwing variant */ declare function getSubjectPublicKey>(parsed: ParsedCertificate | ParsedCertificateSigningRequest, algorithm?: PublicKeyImportInput): Promise>; /** * Check whether a certificate's subject public key belongs to a private key. * * Confirming that an uploaded private key actually matches the certificate it * was submitted with is the first thing a key-intake or issuance endpoint must * do. This derives the public half of `privateKey`, exports it as * SubjectPublicKeyInfo DER, and compares those bytes against the certificate's * own SubjectPublicKeyInfo — the canonical, algorithm-agnostic way to test key * ownership. (Comparing JWKs field by field, or signing a probe and verifying * it, are both more fragile.) * * A private key of a different type — e.g. an ECDSA key against an RSA * certificate — simply produces different SPKI DER and returns `false`, so * callers get a single boolean without branching on the kind of mismatch. Reach * for {@linkcode matchCertificatePrivateKey} when you need the reason a match * failed (or a typed failure instead of a thrown error) at a trust boundary. * * The comparison is over the exact DER encoding. A certificate whose * SubjectPublicKeyInfo pins RSASSA-PSS parameters (rather than the plain * `rsaEncryption` OID that WebCrypto emits) therefore will not match even for * the same modulus; such certificates are rare in practice. * * @param certificate PEM string, DER bytes, or an already-parsed certificate. * @param privateKey An extractable private `CryptoKey`. * @returns `true` when the private key's public half matches the certificate's * subject public key. * * @throws {Error} If `certificate` is malformed, or `privateKey` is not an * extractable private key of a supported type (propagated from * {@linkcode derivePublicKey}). Use {@linkcode matchCertificatePrivateKey} for a * typed `Result` instead of thrown errors. * * @example * ```ts * const privateKey = await importPkcs8PemOrThrow(keyPem, { kind: 'ecdsa', curve: 'P-256' }); * if (!(await certificateMatchesPrivateKey(certificatePem, privateKey))) { * throw new Error('uploaded key does not match the certificate'); * } * ``` * * @see {@linkcode matchCertificatePrivateKey} for the typed-`Result` variant with a mismatch reason * @see {@linkcode getSubjectPublicKeyOrThrow} to obtain the certificate's public key directly * @see {@linkcode derivePublicKey} for the private-to-public bridge this builds on */ declare function certificateMatchesPrivateKey>(certificate: ParsedCertificate | string | Uint8Array, privateKey: CryptoKey): Promise; /** Machine-readable failure reason for {@linkcode matchCertificatePrivateKey}. */ type MatchCertificatePrivateKeyErrorCode = "malformed_certificate" | "unsupported_private_key" | "key_type_mismatch" | "key_mismatch"; /** Structured failure payload for {@linkcode matchCertificatePrivateKey}. */ interface MatchCertificatePrivateKeyFailure extends Micro509Error { /** Always `false` for failures. */ readonly ok: false; } /** A successful match: the private key's public half is the certificate's subject public key. */ interface MatchCertificatePrivateKeySuccess { /** Always `true` for success. */ readonly ok: true; /** No payload on success — the match itself is the signal. */ readonly value: undefined; } /** Failure branch of {@linkcode MatchCertificatePrivateKeyResult} with structured error details. */ type MatchCertificatePrivateKeyFailureResult = ErrorResult, MatchCertificatePrivateKeyFailure>; /** Result of {@linkcode matchCertificatePrivateKey}. */ type MatchCertificatePrivateKeyResult = MatchCertificatePrivateKeySuccess | MatchCertificatePrivateKeyFailureResult; /** * Check whether a certificate's subject public key belongs to a private key, * returning a typed {@linkcode MatchCertificatePrivateKeyResult}. * * The `Result`-returning companion to {@linkcode certificateMatchesPrivateKey}: * where the boolean helper answers only "does it match?" (and throws on bad * input), this surfaces the expected failures a key-intake or issuance endpoint * meets on untrusted input as typed codes rather than exceptions — matching the * house rule of returning `Result` for expected failures and throwing only for * invariants. `ok: true` means the key owns the certificate; a failure carries * one of: * * - `malformed_certificate` — `certificate` could not be parsed. * - `unsupported_private_key` — `privateKey` is not an extractable private key * of a supported type (from {@linkcode derivePublicKey}). * - `key_type_mismatch` — the key is a different algorithm than the * certificate's subject public key. * - `key_mismatch` — the key is the right algorithm but a different key. * * As with {@linkcode certificateMatchesPrivateKey}, the comparison is over exact * SPKI DER, so a certificate pinning RSASSA-PSS parameters reports * `key_type_mismatch` against the `rsaEncryption` SPKI WebCrypto emits. * * @param certificate PEM string, DER bytes, or an already-parsed certificate. * @param privateKey An extractable private `CryptoKey`. * @returns A success when the key matches, or a typed failure otherwise. * * @example * ```ts * const result = await matchCertificatePrivateKey(certificatePem, privateKey); * if (!result.ok) { * // result.code is 'malformed_certificate' | 'unsupported_private_key' * // | 'key_type_mismatch' | 'key_mismatch' * throw new Error(`key does not match certificate: ${result.code}`); * } * ``` * * @see {@linkcode certificateMatchesPrivateKey} for the plain-boolean variant */ declare function matchCertificatePrivateKey>(certificate: ParsedCertificate | string | Uint8Array, privateKey: CryptoKey): Promise; /** * Find a raw extension by OID within a parsed extension list. * * @param extensions Extension list from a {@linkcode ParsedCertificate} or CSR. * @param oid Dotted-decimal OID to look up. * @returns The matching extension, or `undefined` if not present. */ declare function findExtension(extensions: readonly ParsedExtension[], oid: string): ParsedExtension | undefined; /** * Decode a single extension using a custom {@linkcode ExtensionDecoder}. * * @param extensions Extension list to search. * @param decoder Decoder whose OID will be matched. * @returns The decoded value, or `undefined` if the extension is absent. */ declare function decodeExtension(extensions: readonly ParsedExtension[], decoder: ExtensionDecoder): TValue | undefined; /** * Decode all matching extensions using an array of {@linkcode ExtensionDecoder}s. * * @param extensions Extension list to search. * @param decoders Decoders to apply. Only matching OIDs produce output. */ declare function decodeExtensions(extensions: readonly ParsedExtension[], decoders: readonly ExtensionDecoder[]): readonly DecodedExtensionValue[]; /** * Decode all matching extensions using a named {@linkcode ExtensionDecoderMap}. * * @param extensions Extension list to search. * @param decoderMap Named decoders. Results are keyed by the same map keys. */ declare function decodeExtensionMap(extensions: readonly ParsedExtension[], decoderMap: TMap): DecodedExtensionMap; /** Decodes the Basic Constraints extension value DER. */ declare function parseBasicConstraints(bytes: Uint8Array): BasicConstraints; /** Decodes the Key Usage BIT STRING extension value. */ declare function parseKeyUsage(bytes: Uint8Array): ParsedBitFlags; /** Decodes the Extended Key Usage SEQUENCE OF OIDs. */ declare function parseExtendedKeyUsage(bytes: Uint8Array): readonly ExtendedKeyUsage[]; /** Decodes the Certificate Policies extension value. */ declare function parseCertificatePolicies(bytes: Uint8Array): CertificatePolicies; /** Decodes the Policy Mappings extension value. */ declare function parsePolicyMappings(bytes: Uint8Array): PolicyMappings; /** Decodes the Policy Constraints extension value. */ declare function parsePolicyConstraints(bytes: Uint8Array): PolicyConstraints; /** Decodes the Inhibit anyPolicy extension (single INTEGER). */ declare function parseInhibitAnyPolicy(bytes: Uint8Array): InhibitAnyPolicy; /** Decodes a subjectAltName or issuerAltName SEQUENCE OF GeneralName. */ declare function parseSubjectAltNames(bytes: Uint8Array, label?: string): readonly SubjectAltName[]; /** Decodes a bare DER-encoded X.501 Name, as carried in a `directoryName` GeneralName. */ declare function parseDistinguishedNameDer(bytes: Uint8Array): ParsedName; /** Decodes the Authority Information Access extension value. */ declare function parseAuthorityInfoAccess(bytes: Uint8Array): readonly AuthorityInformationAccess[]; /** Decodes the CRL Distribution Points extension value. */ declare function parseCrlDistributionPoints(bytes: Uint8Array): readonly ParsedDistributionPoint[]; /** Decodes the Name Constraints extension value. */ declare function parseNameConstraints(bytes: Uint8Array): NameConstraints; /** Decodes the Authority Key Identifier extension, returning the keyIdentifier hex or undefined. */ declare function parseAuthorityKeyIdentifier(bytes: Uint8Array): string | undefined; //#endregion export { DecodedExtensionMap, DecodedExtensionValue, ExtensionDecoder, ExtensionDecoderMap, MatchCertificatePrivateKeyErrorCode, MatchCertificatePrivateKeyFailure, MatchCertificatePrivateKeyFailureResult, MatchCertificatePrivateKeyResult, MatchCertificatePrivateKeySuccess, ParseCertificateChainResult, ParseCertificateErrorCode, ParseCertificateFailure, ParseCertificateResult, ParseCertificateSigningRequestErrorCode, ParseCertificateSigningRequestFailure, ParseCertificateSigningRequestResult, ParseOptions, type ParsedBitFlags, ParsedCertificate, ParsedCertificateSigningRequest, ParsedDistributionPoint, ParsedDistributionPointName, ParsedExtension, ParsedIssuingDistributionPoint, ParsedIssuingDistributionPointBase, ParsedIssuingDistributionPointScope, ParsedName, ParsedNameAttribute, ParsedRelativeDistinguishedName, certificateMatchesPrivateKey, decodeExtension, decodeExtensionMap, decodeExtensions, defineExtensionDecoder, defineExtensionDecoderMap, findExtension, getSubjectPublicKey, getSubjectPublicKeyOrThrow, matchCertificatePrivateKey, parseAuthorityInfoAccess, parseAuthorityKeyIdentifier, parseBasicConstraints, parseCertificateChainPem, parseCertificateChainPemOrThrow, parseCertificateDer, parseCertificateDerOrThrow, parseCertificateFromSource, parseCertificatePem, parseCertificatePemOrThrow, parseCertificatePolicies, parseCertificateSigningRequestDer, parseCertificateSigningRequestDerOrThrow, parseCertificateSigningRequestPem, parseCertificateSigningRequestPemOrThrow, parseCertificatesFromSource, parseCrlDistributionPoints, parseDistinguishedNameDer, parseExtendedKeyUsage, parseInhibitAnyPolicy, parseKeyUsage, parseNameConstraints, parsePolicyConstraints, parsePolicyMappings, parseSubjectAltNames }; //# sourceMappingURL=parse.d.ts.map