X.509 Certificates
X509Certificate is an immutable certificate facade.
It reads and writes strict PEM and canonical DER, exposes commonly needed RFC 5280 fields as typed values, and retains
the exact encoded certificate, TBSCertificate, signature, and SubjectPublicKeyInfo bytes needed for signature
verification.
An empty certificate is only a missing-storage state; it says nothing about trust, hostname matching, signature
validity, intended purpose, or the current time.
Reading and Writing
The non-throwing fromPem(), fromDer(), and fromFile() factories return an empty certificate for every
failure.
The matching OrThrow factories preserve parse, range, and file diagnostics.
Singular factories require exactly one certificate, while
X509CertificateBundle accepts one or more ordered PEM
blocks.
A bundle can produce DER only when it contains exactly one certificate.
PemDerFormat controls file conversion for every DER-based
cryptographic artifact.
.pem is a strong PEM hint and .der is a strong DER hint.
The common ambiguous .crt and .cer suffixes are sniffed when reading; when writing, .crt selects PEM and
.cer selects DER.
Unknown output suffixes require an explicit format.
PEM parsing accepts only exact CERTIFICATE boundaries and strict Base64, with whitespace outside blocks.
PEM output uses the canonical boundary and 64-character Base64 lines.
DER parsing requires one complete, canonical, definite-length value and rejects trailing data.
The DER implementation follows ITU-T X.690, while certificate schema and profile checks follow RFC 5280 and PEM
boundaries follow RFC 7468. DER parse errors carry the byte index at which the malformed or noncanonical value was
detected; PEM structure errors carry a code-point index in the decoded text.
Fixed limits bound the encoded size, tree depth, node count, certificate count, and PEM input size before allocation or
recursion can grow without control.
Creating Certificates and Requests
X509CertificateBuilder configures one subject identity and
one safe X509CertificateProfile.
The same builder creates a self-signed CA certificate, an issuer-signed certificate, or an immutable
X509CertificateSigningRequest.
This keeps subject, Subject Alternative Name, Key Usage, Extended Key Usage, and Basic Constraints policy identical
between direct test issuance and an enterprise CSR workflow.
CA certificates receive critical Basic Constraints with cA=true and a default path length of zero, critical
keyCertSign and cRLSign, and regenerated Subject and Authority Key Identifiers.
TLS server profiles require at least one DNS name or IP address and request serverAuth; client profiles request
clientAuth and permit an empty SAN; dual-use profiles request both purposes.
Every leaf receives digitalSignature, while RSA leaves additionally receive keyEncipherment.
All profiles require a nonempty common name. Default validity begins five minutes before creation and ends ten calendar years later for a CA or 397 days later for a leaf. Issued defaults are clipped to the issuer validity, while an explicitly configured range or lifetime outside the issuer range is rejected. Issuance verifies that the issuer key matches the certificate and that Basic Constraints, Key Usage, and path-length constraints authorize the requested child. Every result has a fresh positive nonzero random serial and regenerated key identifiers.
Certificates and requests are signed over their exact encoded content. RSA uses RSA-PSS with SHA-256 for RSA-2048/3072 and SHA-384 for RSA-4096, matching MGF1 and digest-sized salt. ECDSA uses the curve-matched SHA-2 hash. Generated certificates are reparsed by the strict X.509 parser and their signatures are verified before they are returned; generated requests likewise pass the strict DER parser and a signature self-check.
fromCertificate() provides controlled reissuance.
It copies the complete subject and supported identity/profile fields, preserves unknown noncritical extensions, and
rejects unknown critical extensions.
It never copies the old serial, issuer, validity, key identifiers, or signature.
Standard subject setters replace matching attributes without discarding unrelated relative distinguished names.
See Creating TLS Certificates and Requests for complete root, intermediate, leaf, encrypted-key, and enterprise-request workflows.
Typed Certificate Data
X509Name preserves the ordered relative distinguished names and their
attributes.
X509GeneralName represents DNS, email, URI, IP-address,
directory-name, and registered-ID alternatives while retaining unsupported alternatives as raw nodes.
X509Extension preserves every extension in encoded order.
Convenience accessors decode Subject Alternative Name, Subject and Authority Key Identifier, Basic Constraints, Key
Usage, and Extended Key Usage.
X509AlgorithmIdentifier retains an algorithm OID and its
optional parameters.
PublicKey retains the exact SubjectPublicKeyInfo and key BIT STRING
and verifies supported RSA, ECDSA, or Ed25519 signatures over caller-supplied exact message bytes.
Both types can also parse their standalone canonical DER representation, which lets certificate-chain validation use an
issuer key and a child’s complete signature AlgorithmIdentifier without reconstructing either value.
RSA Signature Verification
RSA verification follows RSAVP1 and the EMSA verification procedures in RFC 8017 sections 5.2.2, 8, and 9. It accepts RSASSA-PSS and RSASSA-PKCS1-v1_5 with SHA-256 or SHA-384. PSS algorithm and key parameters follow RFC 4055 sections 3.1 and 3.3: the message and MGF1 hashes must match, only trailer field 1 is accepted, and the salt length cannot exceed the selected hash length. General-purpose RSA public-key encoding follows RFC 3279 section 2.3.1.
The RSA modulus must be odd and between 2048 and 8192 bits. The public exponent must be odd, greater than 65536, and at most 256 bits. These checks implement the lower security bounds from FIPS 186-5 section 5.1 and impose a fixed upper work and storage bound before modular arithmetic starts. The verifier uses a dedicated, statically bounded integer representation rather than the library’s general-purpose arithmetic types. Its running time can depend on the modulus, public exponent, and signature because every RSA operand in verification is public; no private exponent, prime, secret scalar, or other secret state is created or retained.
ECDSA Signature Verification
ECDSA verification follows FIPS 186-5 section 6.4.2 and supports exactly P-256 with SHA-256 and P-384 with SHA-384.
Curve parameters come from NIST SP 800-186 sections 3.2.1.3–3.2.1.4, public-key encoding follows RFC 5480 sections
2.1.1–2.2, and signature identifiers follow RFC 5758 section 3.2. Signature values are one complete canonical DER
SEQUENCE containing exactly two positive INTEGER values.
Mathematically valid high-S signatures are accepted; this certificate-verification API does not impose a low-S
normalization policy.
The key must use id-ecPublicKey with a present named-curve OID for one of the two supported curves.
Implicit, explicit, missing, and unsupported curve parameters are rejected.
Public points may use the exact uncompressed form or the 0x02 /0x03 compressed forms.
Coordinates must be in the field and satisfy the curve equation.
Compressed points recover y with the fixed (p+1)/4 exponent available because both primes are 3 modulo 4, verify
the square, and select the encoded parity.
Both curves have cofactor one, so a finite point on the curve is already in the required prime-order subgroup.
Field elements and scalars use a fixed maximum of twelve 32-bit limbs.
Jacobian point operations avoid inversions during public scalar multiplication, while fixed Montgomery precomputations
bound modular arithmetic.
The verification double-scalar calculation is deliberately variable-time: the branch schedule may depend on u,
v, the public key, and signature, all of which are public verification data.
Verification creates no private scalar or other secret state, so no secret-erasure lifecycle is involved.
A future ECDHE implementation may reuse constants and field arithmetic only; its secret-scalar multiplication must use a
separately reviewed constant-schedule path and explicitly erase private intermediates.
Ed25519 Signature Verification
Ed25519 verification follows RFC 8032 sections 5.1.2–5.1.4 and 5.1.7. It supports only pure Ed25519: Ed25519ctx,
Ed25519ph, and Ed448 are distinct algorithms and are not accepted.
Public-key and signature identifiers use id-Ed25519 from RFC 8410 sections 3, 4, and 6, and their
AlgorithmIdentifier parameters must be absent.
A DER NULL parameter is rejected rather than treated as an interoperable alternative.
The public key is exactly one 32-octet encoded point, and a signature is the raw 64-octet ENC(R) || ENC(S) value
without additional ASN.1 wrapping.
Point decoding requires the canonical little-endian y representative below 2^255-19, reconstructs x with the
RFC 8032 square-root procedure, and rejects negative zero or values that are not on the curve.
The scalar S must be below the subgroup order L; this prevents the signature malleability described by RFC 8032
section 8.4. The public key must be a nonidentity point in the prime-order subgroup.
The signature point is decoded canonically, and verification uses the sufficient non-cofactored equation
[S]B = R + [k]A explicitly permitted by RFC 8032 section 5.1.7. This exact equation also rejects a signature point
with a nontrivial torsion component.
Field elements use ten alternating 26/25-bit limbs, while SHA-512 reduction uses eight 32-bit scalar limbs.
These fixed representations bound all storage and arithmetic without a general-purpose big integer or nonportable
128-bit integer.
Scalar multiplication is deliberately variable-time because S, k, the public key, and signature point are all
public verification inputs.
Verification creates no private scalar or other secret state, so no secret-erasure lifecycle is involved.
TLS 1.3 Signature Schemes
TlsSignatureScheme represents the supported two-octet
SignatureScheme values from RFC 8446 section 4.2.3. It supports ECDSA with P-256/SHA-256 or P-384/SHA-384, pure
Ed25519, RSA-PSS-RSAE and RSA-PSS-PSS with SHA-256 or SHA-384, plus certificate-only RSA-PKCS1/SHA-256 and
RSA-PKCS1/SHA-384. The raw-value factories reject every unsupported registry value rather than preserving an unknown
construction.
The certificate and TLS-message policies are intentionally separate.
PKCS#1 v1.5 schemes can describe signatures appearing in certificates but are never allowed for a TLS 1.3
CertificateVerify message.
RSA-PSS-RSAE requires a SubjectPublicKeyInfo using rsaEncryption, while RSA-PSS-PSS requires id-RSASSA-PSS.
Both PSS variants use the selected SHA-2 algorithm for the message and MGF1, set the salt length to the digest length,
and use trailer field 1 as required by RFC 8446 section 4.2.3.
PublicKey::verifyTlsCertificateVerifySignature() verifies the exact caller-supplied content
covered by the signature.
The caller remains responsible for constructing the 64 space octets, context string, zero separator, and transcript hash
specified by RFC 8446 section 4.4.3. The scheme, public key, signed content, and signature are all public verification
inputs; the mapping creates no secret state and has no secret-erasure lifecycle.
Verification Results and Policy
verifySignature() returns false for a well-formed supported signature that does not verify.
It throws a parse error for malformed, unsupported, or out-of-policy key and algorithm encodings, so callers cannot
silently treat an unsupported construction as an ordinary bad signature.
PKCS#1 v1.5 support exists for certificate-chain compatibility.
RFC 8446 section 4.2.3 permits these schemes for certificate signatures but not for TLS 1.3 CertificateVerify; the
dedicated TLS verification operation enforces this distinction before signature dispatch.
Signing and private-key loading remain separate work.
Portable explicit-anchor server authentication is described below; platform trust-store policy remains deferred.
Explicit-Anchor Server Authentication
X509ServerCertificatePolicy authenticates an
already-parsed peer certificate set for one network::Host reference identity.
The first peer certificate is the target and all remaining peer certificates are unordered issuer candidates.
Configured intermediates provide a second candidate source.
Explicit certificate trust anchors are mandatory; the policy does not consult a platform trust store.
Path construction follows RFC 4158 sections 2.4 and 5. It performs deterministic depth-first traversal, preferring peer intermediates and then configured intermediates in their source order before anchors, while trying alternate branches after a failure. Certificates are deduplicated by exact DER. Issuer linkage currently requires byte-identical canonical DER for the child’s issuer and candidate’s subject. Authority and Subject Key Identifiers eliminate a candidate only when both are present and unequal. RFC 4518 distinguished-name equivalence is intentionally not implemented in this initial portable policy.
An accepted path terminates only at an explicitly configured anchor and includes that anchor in target-to-anchor order. The anchor supplies trusted subject-name and public-key input; its self-signature, validity, extensions, Basic Constraints, and Key Usage are not checked. If the target certificate itself is explicitly anchored, its end-entity profile, validity, purpose, critical extensions, and service identity are still checked.
Path Validation and Purpose
Path validation follows RFC 5280 sections 4.1.2.5, 4.2.1.3, 4.2.1.9, 4.2.1.12, and 6.1. Every child signature covers the
retained exact TBSCertificate and must have zero unused BIT STRING bits.
Every non-anchor certificate must have no compatible-parser profile issue and must satisfy the inclusive
notBefore <= validationTime <= notAfter interval.
The caller may supply a validation time explicitly; the convenience overload uses DateTime::now().
An intermediate requires a critical Basic Constraints extension with cA=true.
If Key Usage exists it must include keyCertSign; if Extended Key Usage exists it must include serverAuth or
anyExtendedKeyUsage.
pathLenConstraint counts only non-self-issued intermediate CA certificates below the constrained CA. The target must
not assert cA=true; an existing Key Usage must include digitalSignature and an existing Extended Key Usage must
permit server authentication, as required for the TLS certificate role by RFC 8446 section 4.4.2.2.
The validator recognizes the currently decoded Subject Key Identifier, Authority Key Identifier, Subject Alternative Name, Basic Constraints, Key Usage, and Extended Key Usage extensions. Every other critical extension rejects the path; unknown noncritical extensions are retained by the certificate parser and ignored by this policy. Revocation, name constraints, policy constraints, and certificate policies are unavailable in this increment and are never reported as successfully checked.
DNS and IP Service Identities
Service-identity matching follows RFC 9525 section 6 and RFC 9549 and uses Subject Alternative Name only.
A
network::HostName selects DNS-ID matching, while a
network::IpAddress selects IP-ID matching. Common Name is never a fallback,
and DNS and IP alternatives cannot satisfy a reference of the other type.
DNS references arrive as validated network::HostName values and are converted
to their canonical strict-IDNA2008 ASCII form before matching.
Presented dNSName alternatives remain ASCII as required by X.509; each label and xn-- A-label is validated,
round-tripped, and compared label by label in canonical A-label form with ASCII case folding.
Malformed or disallowed presented identities do not prevent a later valid SAN from matching.
When no valid SAN matches, a relevant malformed identity produces InvalidPresentedIdentity with its underlying IDNA
reason; ordinary valid mismatches produce ServerIdentityMismatch.
A presented wildcard is valid only as the complete leftmost label, occurs once, and matches exactly one reference label.
IP subject alternatives compare through the canonical byte representation of IpAddress.
Results, Diagnostics, and Bounds
X509CertificateValidation deliberately has no boolean
conversion.
isAccepted() and isRejected() expose the outcome.
Acceptance carries the validated target-to-anchor path.
Rejection carries an
X509CertificateValidationFailure with a stable
category, optional affected certificate and issuer candidate, partial path, and human-readable diagnostic.
No outcome uses an empty certificate as a signal.
Attacker-controlled work is bounded to 256 aggregate unique certificates, 16 certificates in one prospective path, and 1024 signature-verification attempts. Repeated certificates are rejected as path loops and verified edges are cached. Exhausting any bound produces an explicit resource-limit failure category.
Strict and Compatible Profiles
X509CertificateProfileMode affects certificate-profile
checks, never DER safety or canonicality.
Strict mode rejects a certificate when, for example, its inner and outer signature algorithm identifiers disagree.
Compatible mode retains supported interoperability exceptions as
X509CertificateProfileIssue values so callers can
make an explicit policy decision.
Malformed ASN.1, noncanonical DER, invalid lengths, invalid primitive encodings, and resource-limit violations remain
errors in both modes.
Raw ASN.1 Views and Backends
Asn1Node is a read-only view into a successfully parsed certificate.
Each node independently retains its shared immutable DER storage and exposes its exact encoding, content octets,
children, tag, and selected primitive conversions.
There is deliberately no public factory for parsing arbitrary ASN.1 with this view API.
Certificate shared data uses a virtual backend contract. Portable certificates store parsed values directly; future Windows and macOS integrations can retain a native certificate-store reference and materialize the same immutable portable view only when an accessor or serialization operation needs it. Native handles are not exposed by the public facade.
Interface
-
class Asn1Node
An immutable node in a certificate-owned ASN.1 tree.
Node values retain their shared DER storage. No factory for arbitrary ASN.1 input is exposed; obtain a node from a successfully parsed certificate or one of its typed values.
See: X.509 Certificates
Public Functions
-
Asn1Node() = default
Create an empty node.
-
bool isEmpty() const noexcept
Test if this node is empty.
-
bool isConstructed() const noexcept
Test if this node is constructed.
-
Asn1TagClass tagClass() const noexcept
Get the encoded tag class.
-
uint32_t tagNumber() const noexcept
Get the numeric tag.
-
Asn1UniversalType universalType() const noexcept
Get the universal type, or
Nonefor a non-universal node.
-
Asn1Node child(unit::ItemIndex index) const noexcept
Get a child node or an empty node for an invalid index.
-
std::optional<bool> toBoolean() const noexcept
Decode a BOOLEAN value.
-
std::optional<Asn1ObjectIdentifier> toObjectIdentifier() const noexcept
Decode an OBJECT IDENTIFIER value.
-
Asn1Node() = default
-
class Asn1ObjectIdentifier
A canonical dotted ASN.1 object identifier.
Public Functions
-
Asn1ObjectIdentifier() = default
Create an empty object identifier.
-
inline bool isEmpty() const noexcept
Test if this object identifier is empty.
Public Static Functions
-
static std::optional<Asn1ObjectIdentifier> fromString(const text::String &value) noexcept
Parse a canonical dotted-decimal object identifier.
- Parameters:
value – The text to parse.
- Returns:
The parsed identifier, or no value for malformed text.
-
static Asn1ObjectIdentifier fromStringOrThrow(const text::String &value)
Parse a canonical dotted-decimal object identifier.
- Parameters:
value – The text to parse.
- Throws:
err::ParseError – If the value is malformed or noncanonical.
- Returns:
The parsed identifier.
-
Asn1ObjectIdentifier() = default
-
enum class erbsland::cryptology::Asn1TagClass : uint8_t
The ASN.1 tag class encoded in an identifier octet.
Values:
-
enumerator Universal
A type defined by ASN.1.
-
enumerator Application
An application-specific type.
-
enumerator Context
A context-specific type.
-
enumerator Private
A private type.
-
enumerator Universal
-
enum class erbsland::cryptology::Asn1UniversalType : uint32_t
ASN.1 universal tag numbers used by X.509 certificates.
Values:
-
enumerator None
The node does not use the universal tag class.
-
enumerator Boolean
A BOOLEAN value.
-
enumerator Integer
An INTEGER value.
-
enumerator BitString
A BIT STRING value.
-
enumerator OctetString
An OCTET STRING value.
-
enumerator Null
A NULL value.
-
enumerator ObjectIdentifier
An OBJECT IDENTIFIER value.
-
enumerator Utf8String
A UTF8String value.
-
enumerator Sequence
A SEQUENCE value.
-
enumerator Set
A SET value.
-
enumerator NumericString
A NumericString value.
-
enumerator PrintableString
A PrintableString value.
-
enumerator TeletexString
A TeletexString value.
-
enumerator Ia5String
An IA5String value.
-
enumerator UtcTime
A UTCTime value.
-
enumerator GeneralizedTime
A GeneralizedTime value.
-
enumerator UniversalString
A UniversalString value.
-
enumerator BmpString
A BMPString value.
-
enumerator None
-
class X509AlgorithmIdentifier
An X.509 AlgorithmIdentifier preserving its parameters and exact DER.
Public Functions
-
X509AlgorithmIdentifier() = default
Create an empty algorithm identifier.
-
inline bool isEmpty() const noexcept
Test if this identifier is empty.
-
inline const Asn1ObjectIdentifier &oid() const noexcept
Get the algorithm object identifier.
Public Static Functions
-
static X509AlgorithmIdentifier fromDer(const mem::ByteBlock &der) noexcept
Parse one canonical DER AlgorithmIdentifier, returning an empty value on error.
- Parameters:
der – The complete DER AlgorithmIdentifier.
- Returns:
The parsed identifier, or an empty value on error.
-
static X509AlgorithmIdentifier fromDerOrThrow(const mem::ByteBlock &der)
Parse one canonical DER AlgorithmIdentifier.
- Parameters:
der – The complete DER AlgorithmIdentifier.
- Throws:
err::ParseError – If the DER or AlgorithmIdentifier structure is malformed.
err::OutOfRangeError – If a fixed parser resource limit is exceeded.
- Returns:
The parsed identifier.
-
X509AlgorithmIdentifier() = default
-
class X509BasicConstraints
Decoded X.509 Basic Constraints.
Public Functions
-
X509BasicConstraints() = default
Create constraints for an end-entity certificate.
-
inline bool isCertificateAuthority() const noexcept
Test if the subject may act as a certificate authority.
-
inline std::optional<uint32_t> pathLength() const noexcept
Get the optional maximum subordinate CA depth.
-
X509BasicConstraints() = default
-
class X509Certificate
An immutable X.509 certificate backed by portable data or a future native certificate reference.
A default-constructed value is empty.
isEmpty()describes only this storage state and does not perform signature, trust-path, hostname, purpose, or validity-time validation.See: X.509 Certificates
Public Functions
-
X509Certificate() = default
Create an empty certificate.
-
inline bool isEmpty() const noexcept
Test if this facade contains no certificate.
-
X509Version version() const noexcept
Get the X.509 version, or
Unknownwhen empty.
-
mem::ByteBlock serialNumber() const
Get exact serial-number INTEGER content octets, or an empty block.
-
X509AlgorithmIdentifier signatureAlgorithm() const
Get the outer signature algorithm identifier.
-
text::String signatureAlgorithmId() const
Get the stable dotted signature algorithm identifier, or an empty string.
-
util::List<X509GeneralName> subjectAlternativeNames() const
Get typed subject alternative names.
-
text::StringList dnsNames() const
Get DNS subject alternative names in encoded order.
-
util::List<network::IpAddress> ipAddresses() const
Get IP-address subject alternative names in encoded order.
-
X509AlgorithmIdentifier tbsSignatureAlgorithm() const
Get the TBSCertificate signature algorithm identifier.
-
mem::ByteBlock signatureData() const
Get signature BIT STRING data without its unused-bit-count octet.
-
uint8_t signatureUnusedBitCount() const noexcept
Get the signature BIT STRING unused-bit count.
-
util::List<X509Extension> extensions() const
Get all certificate extensions in encoded order.
-
std::optional<X509BasicConstraints> basicConstraints() const
Get decoded Basic Constraints, if present and readable.
-
std::optional<X509KeyUsages> keyUsage() const
Get decoded Key Usage, if present and readable.
-
util::List<Asn1ObjectIdentifier> extendedKeyUsage() const
Get decoded Extended Key Usage object identifiers.
-
util::List<X509CertificateProfileIssue> profileIssues() const
Get retained compatible-mode profile issues.
-
text::String toPem() const
Encode this certificate using strict RFC 7468 textual form, or return an empty string when empty.
-
text::StringTree toStringTree() const
Build a complete OpenSSL-like certificate display tree.
-
void writeToFile(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic) const
Write this certificate to a file.
- Parameters:
path – The destination path.
format – The explicit format or suffix-selected
Automaticformat.
- Throws:
err::LogicError – If the certificate is empty.
err::ParameterError – If automatic output cannot select a format.
path::PathError – If writing fails.
Public Static Functions
-
static auto fromPem(const text::String &text, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) noexcept -> X509Certificate
Parse exactly one strict CERTIFICATE PEM block, returning an empty certificate on any error.
-
static auto fromPemOrThrow(const text::String &text, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) -> X509Certificate
Parse exactly one strict CERTIFICATE PEM block.
- Throws:
err::ParseError – If textual or certificate data is malformed or rejected by the selected profile mode.
err::OutOfRangeError – If a fixed resource limit is exceeded.
-
static auto fromDer(const mem::ByteBlock &data, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) noexcept -> X509Certificate
Parse exactly one complete canonical DER certificate, returning an empty certificate on any error.
-
static auto fromDerOrThrow(const mem::ByteBlock &data, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) -> X509Certificate
Parse exactly one complete canonical DER certificate.
- Throws:
err::ParseError – If DER or certificate data is malformed or rejected by the selected profile mode.
err::OutOfRangeError – If a fixed resource limit is exceeded.
-
static auto fromFile(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) noexcept -> X509Certificate
Read one certificate from a file, returning an empty certificate on any error.
-
static auto fromFileOrThrow(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) -> X509Certificate
Read one certificate from a file.
- Throws:
path::PathError – If reading fails.
err::ParseError – If certificate data is malformed.
err::OutOfRangeError – If a fixed resource limit is exceeded.
-
X509Certificate() = default
-
class X509CertificateBuilder
A profile-driven builder for web certificates and PKCS#10 requests.
See: X.509 Certificates
Public Functions
-
X509CertificateBuilder &setCommonName(text::String value)
Replace the subject common name.
-
X509CertificateBuilder &setCountry(text::String value)
Replace the two-character subject country code.
-
X509CertificateBuilder &setState(text::String value)
Replace the subject state or province.
-
X509CertificateBuilder &setLocality(text::String value)
Replace the subject locality.
-
X509CertificateBuilder &setOrganization(text::String value)
Replace the subject organization.
-
X509CertificateBuilder &setOrganizationalUnit(text::String value)
Replace the subject organizational unit.
-
X509CertificateBuilder &addDnsName(text::String value)
Add a DNS subject alternative name.
-
X509CertificateBuilder &addIpAddress(network::IpAddress value)
Add an IP-address subject alternative name.
-
X509CertificateBuilder &setValidFrom(time::DateTime value) noexcept
Set an exact not-before time.
-
X509CertificateBuilder &setValidTo(time::DateTime value) noexcept
Set an exact not-after time and clear a configured lifetime.
-
X509CertificateBuilder &setValidity(time::DateTime from, time::DateTime to) noexcept
Set an exact validity range and clear a configured lifetime.
-
X509CertificateBuilder &setLifetime(time::CalendarDelta value) noexcept
Set the lifetime relative to the configured or default not-before time.
-
X509CertificateBuilder &setCaPathLength(uint32_t value) noexcept
Set the maximum subordinate-CA depth for a CA profile.
-
X509Certificate createSelfSignedCertificate(const SigningPrivateKey &key) const
Create a self-signed CA certificate.
- Throws:
err::LogicError – If this is not a CA profile or the key is empty.
err::ParameterError – If configured identity or validity data is invalid.
-
auto createCertificate(const SigningPrivateKey &subjectKey, const X509Certificate &issuerCertificate, const SigningPrivateKey &issuerKey) const -> X509Certificate
Create a certificate signed by an authorized issuer.
- Throws:
err::LogicError – If a required value is empty.
err::ParameterError – If the profile, validity, issuer, or key relationship is invalid.
-
X509CertificateSigningRequest createSigningRequest(const SigningPrivateKey &subjectKey) const
Create a signed PKCS#10 request from the same profile and identity configuration.
- Throws:
err::LogicError – If the key is empty.
err::ParameterError – If configured profile or identity data is invalid.
Public Static Functions
-
static X509CertificateBuilder certificateAuthority(text::String commonName)
Create a CA profile builder.
- Parameters:
commonName – The required nonempty subject common name.
- Returns:
A builder with safe CA defaults.
-
static X509CertificateBuilder tlsServer(text::String commonName)
Create a TLS server profile builder.
- Parameters:
commonName – The required nonempty subject common name.
- Returns:
A builder requiring at least one DNS name or IP address before creation.
-
static X509CertificateBuilder tlsClient(text::String commonName)
Create a TLS client profile builder.
- Parameters:
commonName – The required nonempty subject common name.
- Returns:
A builder with the TLS client profile.
-
static X509CertificateBuilder tlsServerAndClient(text::String commonName)
Create a dual-use TLS server/client profile builder.
- Parameters:
commonName – The required nonempty subject common name.
- Returns:
A builder requiring at least one DNS name or IP address before creation.
-
static X509CertificateBuilder fromCertificate(const X509Certificate &certificate, X509CertificateProfile profile)
Initialize controlled reissuance from a parsed certificate.
- Parameters:
certificate – The source certificate whose supported identity information is copied.
profile – The safe profile for the new certificate or request.
- Throws:
err::LogicError – If the source is empty or has an unknown critical extension.
- Returns:
A new independent builder.
-
X509CertificateBuilder &setCommonName(text::String value)
-
class X509CertificateBundle
An ordered bundle of X.509 certificates.
PEM supports multiple certificates. DER conversion and output require exactly one certificate.
See: X.509 Certificates
Public Functions
-
X509CertificateBundle() = default
Create an empty certificate bundle.
-
explicit X509CertificateBundle(util::List<X509Certificate> certificates)
Create a bundle from ordered certificates.
- Parameters:
certificates – The certificates to store; empty certificate elements are rejected.
- Throws:
err::ParameterError – If an element is empty or the fixed count limit is exceeded.
-
inline bool isEmpty() const noexcept
Test if the bundle contains no certificates.
-
inline const util::List<X509Certificate> &certificates() const noexcept
Get certificates in source order.
-
mem::ByteBlock toDer() const
Return DER when the bundle contains exactly one certificate.
- Throws:
err::LogicError – If the bundle does not contain exactly one certificate.
-
void writeToFile(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic) const
Write this bundle to a file.
- Throws:
err::LogicError – If DER is selected for a bundle not containing exactly one certificate.
err::ParameterError – If automatic output cannot select a format.
path::PathError – If writing fails.
Public Static Functions
-
static auto fromPem(const text::String &text, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) noexcept -> X509CertificateBundle
Parse one or more strict CERTIFICATE PEM blocks, returning an empty bundle on any error.
-
static auto fromPemOrThrow(const text::String &text, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) -> X509CertificateBundle
Parse one or more strict CERTIFICATE PEM blocks.
-
static auto fromDer(const mem::ByteBlock &data, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) noexcept -> X509CertificateBundle
Parse one DER certificate as a one-element bundle, returning an empty bundle on any error.
-
static auto fromDerOrThrow(const mem::ByteBlock &data, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) -> X509CertificateBundle
Parse one DER certificate as a one-element bundle.
-
static auto fromFile(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) noexcept -> X509CertificateBundle
Read a certificate bundle from a file, returning an empty bundle on any error.
-
static auto fromFileOrThrow(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic, X509CertificateProfileMode mode = X509CertificateProfileMode::Strict) -> X509CertificateBundle
Read a certificate bundle from a file.
-
X509CertificateBundle() = default
-
enum class erbsland::cryptology::X509CertificateProfile : uint8_t
A safe web-certificate extension and validation profile.
Values:
-
enumerator CertificateAuthority
Certificate authority that may issue certificates and CRLs.
-
enumerator TlsServer
TLS server identity requiring a DNS or IP subject alternative name.
-
enumerator TlsClient
TLS client identity with an optional subject alternative name.
-
enumerator TlsServerAndClient
Dual-use TLS identity requiring a DNS or IP subject alternative name.
-
enumerator CertificateAuthority
-
class X509CertificateProfileIssue
A machine-readable X.509 profile issue retained in compatible mode.
Public Functions
-
X509CertificateProfileIssue() = default
Create an empty issue.
-
inline X509CertificateProfileIssue(X509CertificateProfileIssueCategory category, text::String field, Asn1ObjectIdentifier oid, text::String diagnostic) noexcept
Create a profile issue.
- Parameters:
category – The stable issue category.
field – The affected field name.
oid – The affected object identifier, if any.
diagnostic – A human-readable diagnostic.
-
inline X509CertificateProfileIssueCategory category() const noexcept
Get the stable issue category.
-
inline const Asn1ObjectIdentifier &oid() const noexcept
Get the affected object identifier, if any.
-
X509CertificateProfileIssue() = default
-
enum class erbsland::cryptology::X509CertificateProfileIssueCategory : uint8_t
A stable category for a retained X.509 profile issue.
Values:
-
enumerator SerialNumber
The serial number violates the RFC 5280 profile.
-
enumerator SignatureAlgorithmMismatch
Inner and outer signature algorithms differ.
-
enumerator VersionField
A field is inconsistent with the certificate version.
-
enumerator ValidityRange
The not-after time precedes the not-before time.
-
enumerator ExtensionValue
A recognized extension has a malformed inner value.
-
enumerator NameValue
A name contains an unsupported or malformed value.
-
enumerator SerialNumber
-
enum class erbsland::cryptology::X509CertificateProfileMode : uint8_t
The handling of independently detectable RFC 5280 profile violations.
Values:
-
enumerator Strict
Reject certificates with detected profile violations.
-
enumerator Compatible
Retain reviewed profile anomalies and report typed issues.
-
enumerator Strict
-
class X509CertificateSigningRequest
An immutable PKCS#10 certificate signing request.
See: X.509 Certificates
Public Functions
-
X509CertificateSigningRequest() = default
Create an empty request.
-
inline bool isEmpty() const noexcept
Test if no request is stored.
-
void writeToFile(const path::Path &path, PemDerFormat format = PemDerFormat::Automatic) const
Write the request without replacing an existing file.
-
X509CertificateSigningRequest() = default
-
class X509CertificateValidation
The explicit result of X.509 server-certificate validation.
This type deliberately has no boolean conversion. An accepted result carries the selected path in target-to-anchor order; a rejected result carries structured failure context and never uses an empty certificate as a signal.
See: X.509 Certificates
Public Functions
-
inline bool isAccepted() const noexcept
Test whether the certificate was accepted for the requested server identity.
-
inline bool isRejected() const noexcept
Test whether the certificate was rejected.
-
inline const util::List<X509Certificate> &validatedPath() const noexcept
Get the selected target-to-anchor path, or an empty list after rejection.
-
inline const std::optional<X509CertificateValidationFailure> &failure() const noexcept
Get structured failure context, or no value after acceptance.
-
inline bool isAccepted() const noexcept
-
class X509CertificateValidationFailure
Structured context for one rejected X.509 server-certificate validation.
See: X.509 Certificates
Public Functions
-
inline X509CertificateValidationFailureCategory category() const noexcept
Get the stable failure category.
-
inline const std::optional<X509Certificate> &certificate() const noexcept
Get the certificate whose processing failed, or no value for an input-wide failure.
-
inline const std::optional<X509Certificate> &issuerCandidate() const noexcept
Get the issuer candidate involved in an edge failure.
-
inline const util::List<X509Certificate> &partialPath() const noexcept
Get the partial target-to-issuer path that led to this failure.
-
inline X509CertificateValidationFailureCategory category() const noexcept
-
enum class erbsland::cryptology::X509CertificateValidationFailureCategory : uint8_t
A stable failure category for X.509 server-certificate validation.
Values:
-
enumerator EmptyPeerCertificates
The peer supplied no target certificate.
-
enumerator EmptyTrustAnchors
The policy contains no explicit trust anchor.
-
enumerator InvalidValidationTime
The requested validation time is invalid.
-
enumerator InvalidReferenceIdentity
The reference identity cannot be canonicalized for comparison.
-
enumerator InvalidPresentedIdentity
A relevant presented dNSName is malformed or violates IDNA2008.
-
enumerator CandidateLimitExceeded
The aggregate unique-certificate limit was exceeded.
-
enumerator PathDepthExceeded
Every prospective path exceeded the depth limit.
-
enumerator SignatureLimitExceeded
The signature-verification work limit was exceeded.
-
enumerator PathLoop
Every prospective path repeated a certificate.
-
enumerator IssuerNotFound
No matching issuer or trust anchor could be found.
-
enumerator SignatureInvalid
An issuer candidate did not verify the child signature.
-
enumerator SignatureUnsupported
A signature or public-key construction is unsupported or malformed.
-
enumerator CertificateProfileRejected
Compatible-parser profile issues are not accepted by this policy.
-
enumerator CertificateNotYetValid
The validation time precedes notBefore.
-
enumerator CertificateExpired
The validation time follows notAfter.
-
enumerator UnknownCriticalExtension
A non-anchor certificate has an unsupported critical extension.
-
enumerator BasicConstraintsRequired
An intermediate has no critical Basic Constraints extension.
-
enumerator NotCertificateAuthority
An intermediate is not a CA, or the target is marked as one.
-
enumerator KeyUsageRejected
Key Usage does not permit the required operation.
-
enumerator ExtendedKeyUsageRejected
Extended Key Usage does not permit TLS server authentication.
-
enumerator PathLengthExceeded
A CA pathLenConstraint is exceeded.
-
enumerator ServerIdentityMismatch
No appropriate subjectAltName matches the requested identity.
-
enumerator EmptyPeerCertificates
-
class X509Extension
One X.509 extension preserving its exact value and decoded inner node.
Public Functions
-
X509Extension() = default
Create an empty extension.
-
inline const Asn1ObjectIdentifier &oid() const noexcept
Get the extension OID.
-
inline bool isCritical() const noexcept
Test if the extension is marked critical.
-
X509Extension() = default
-
class X509GeneralName
A supported or preserved GeneralName from an X.509 extension.
Public Types
-
enum class Kind : uint8_t
The represented GeneralName alternative.
Values:
-
enumerator Unsupported
A preserved unsupported context-specific alternative.
-
enumerator Email
An rfc822Name value.
-
enumerator Dns
A dNSName value.
-
enumerator Directory
A directoryName value.
-
enumerator Uri
A uniformResourceIdentifier value.
-
enumerator IpAddress
An iPAddress value.
-
enumerator RegisteredId
A registeredID value.
-
enumerator Unsupported
Public Functions
-
X509GeneralName() = default
Create an empty unsupported name.
-
inline const Asn1ObjectIdentifier ®isteredId() const noexcept
Get a registered-ID value.
-
enum class Kind : uint8_t
-
enum class erbsland::cryptology::X509KeyUsage : uint16_t
X.509 Key Usage bits.
Values:
-
enumerator None
No decoded usage bits.
-
enumerator DigitalSignature
Digital signatures other than certificate or CRL signatures.
-
enumerator ContentCommitment
Non-repudiation or content commitment.
-
enumerator KeyEncipherment
Key transport.
-
enumerator DataEncipherment
Direct data encipherment.
-
enumerator KeyAgreement
Key agreement.
-
enumerator KeyCertificateSign
Certificate signing.
-
enumerator CrlSign
CRL signing.
-
enumerator EncipherOnly
Encipher-only key agreement.
-
enumerator DecipherOnly
Decipher-only key agreement.
-
enumerator None
-
using erbsland::cryptology::X509KeyUsages = util::EnumFlags<X509KeyUsage>
A set of X.509 Key Usage bits.
-
class X509Name
An ordered X.509 issuer or subject Name.
Public Functions
-
X509Name() = default
Create an empty name.
-
inline bool isEmpty() const noexcept
Test if the name contains no relative distinguished names.
-
inline const util::List<X509RelativeDistinguishedName> &relativeDistinguishedNames() const noexcept
Get ordered relative distinguished names.
-
text::StringList values(const Asn1ObjectIdentifier &oid) const
Get all decoded values for an attribute OID.
- Parameters:
oid – The attribute type to select.
- Returns:
Values in certificate order.
-
text::StringList commonNames() const
Get common-name values.
-
text::StringList organizations() const
Get organization values.
-
text::StringList organizationalUnits() const
Get organizational-unit values.
-
text::StringList localities() const
Get locality values.
-
text::StringList states() const
Get state or province values.
-
text::StringList countries() const
Get country values.
-
X509Name() = default
-
class X509NameAttribute
One attribute in an X.509 relative distinguished name.
Public Functions
-
X509NameAttribute() = default
Create an empty name attribute.
-
inline const Asn1ObjectIdentifier &oid() const noexcept
Get the attribute type OID.
-
X509NameAttribute() = default
-
class X509RelativeDistinguishedName
One ordered relative distinguished name in an X.509 Name.
Public Functions
-
X509RelativeDistinguishedName() = default
Create an empty relative distinguished name.
-
inline const util::List<X509NameAttribute> &attributes() const noexcept
Get the attributes in canonical DER order.
-
X509RelativeDistinguishedName() = default
-
class X509ServerCertificatePolicy
A portable explicit-anchor policy for authenticating TLS server certificates.
Path building follows RFC 4158 sections 2.4 and 5. Path validation follows RFC 5280 sections 4.1.2.5, 4.2.1.3, 4.2.1.9, 4.2.1.12, and 6.1. TLS purpose checks follow RFC 8446 section 4.4.2.2, and DNS/IP identity matching follows RFC 9525 sections 6.1—6.6. Revocation, name/policy constraints, RFC 4518 name equivalence, platform trust stores, and UTS #46 compatibility mapping are not performed. DNS references use strict IDNA2008; presented certificate dNSName values remain canonical ASCII A-labels for comparison.
See: X.509 Certificates
Public Functions
-
inline X509ServerCertificatePolicy(X509CertificateBundle trustAnchors, X509CertificateBundle intermediates = {}) noexcept
Create a server-authentication policy.
- Parameters:
trustAnchors – Explicit trusted certificates; an empty bundle causes validation to reject explicitly.
intermediates – Additional unordered issuer candidates.
-
auto validate(const X509CertificateBundle &peerCertificates, const network::Host &referenceIdentity, time::DateTime validationTime) const -> X509CertificateValidation
Validate a peer certificate set at an explicit time.
- Parameters:
peerCertificates – The target certificate first, followed by unordered peer intermediates.
referenceIdentity – The unresolved DNS name or literal IP address to authenticate.
validationTime – The time used for every non-anchor validity check.
- Returns:
An explicit accepted or rejected validation result.
-
auto validate(const X509CertificateBundle &peerCertificates, const network::Host &referenceIdentity) const -> X509CertificateValidation
Validate a peer certificate set at the current time.
- Parameters:
peerCertificates – The target certificate first, followed by unordered peer intermediates.
referenceIdentity – The unresolved DNS name or literal IP address to authenticate.
- Returns:
An explicit accepted or rejected validation result.
-
inline const X509CertificateBundle &trustAnchors() const noexcept
Get the explicit trust anchors.
-
inline const X509CertificateBundle &intermediates() const noexcept
Get the configured intermediate certificates.
Public Static Attributes
-
static constexpr auto cMaximumCandidateCertificates = std::size_t{256U}
Maximum aggregate number of unique target, intermediate, and anchor certificates.
-
static constexpr auto cMaximumPathDepth = std::size_t{16U}
Maximum number of certificates in one target-to-anchor path.
-
static constexpr auto cMaximumSignatureVerifications = std::size_t{1024U}
Maximum number of issuer-edge signature-verification attempts.
-
inline X509ServerCertificatePolicy(X509CertificateBundle trustAnchors, X509CertificateBundle intermediates = {}) noexcept