silk.tls.certificate.
Decode one X.509 certificate from DER or PEM, and read its fields.
When to use#
Use Certificate.decodePem for a .pem or .crt file with one CERTIFICATE block, and
Certificate.decodeDer for binary DER, such as a certificate from a TLS handshake. For a file
with more than one certificate, use silk.tls.certificate_bundle.
Details#
A Certificate owns a copy of its DER bytes. The accessors return slices of that DER, such as
Certificate.subjectDer or Certificate.tbsDer, and decoded values, such as
Certificate.notAfter. Nothing is normalized: names, algorithms, and extensions keep their
original bytes, and unknown or duplicate extensions stay available. DecodeLimits bound the
work for input that you do not control.
Errors#
DecodeErrorif the input is not a valid certificate or goes over a limit.reasongives the rule, andoffsetwithoffsetSpacegives the position.OutOfMemoryErrorif theAllocatorfails.
Gotchas#
Decoding checks only the structure. It does not verify the signature, the chain, the names, or
the dates. Use silk.tls.certificate_path for that. The PEM decoder is strict: text outside the
block, other labels, and non-canonical Base64 are errors.
Examples#
Report where a PEM certificate is broken#
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.tls.certificate { Certificate, DecodeError, DecodeLimits, DecodeReason }
import silk.core.effect { Effect }
import silk.core.result { Result }
pub effect fn main() -> i32
! OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let pem = b"-----BEGIN CERTIFICATE-----\n!!!!\n-----END CERTIFICATE-----\n"
let decoded = run Certificate.decodePem(pem, DecodeLimits.defaults())
|> Effect.provideMut<Allocator>(&mut allocator)
return match move decoded {
Result<Certificate, DecodeError>.Failure { error } => {
// `!` is not a Base64 character.
if error.reason != DecodeReason.Base64 {
return 1
}
return 0
}
Result<Certificate, DecodeError>.Success { value: _ } => 1
}
}Import as Certificate with import silk.tls.certificate { Certificate }.
Public declarations: 12.
DecodeLimits#
pub struct DecodeLimitsThe resource limits for one decode call. Each limit is inclusive, and 0 allows nothing.
DecodeLimits.defaults gives safe values.
Field inputBytes#
pub inputBytes: usizeThe maximum input length, with PEM whitespace.
Field certificateBytes#
pub certificateBytes: usizeThe maximum DER length of one certificate.
Field totalDerBytes#
pub totalDerBytes: usizeThe maximum DER length of all certificates together.
Field certificates#
pub certificates: usizeThe maximum number of certificates, with duplicates.
Field fieldBytes#
pub fieldBytes: usizeThe maximum content length of one field.
Field extensions#
pub extensions: usizeThe maximum number of extensions in one certificate.
Field depth#
pub depth: usizeThe maximum nesting depth of DER values. The certificate itself has depth 1.
Field nodes#
pub nodes: usizeThe maximum number of DER values in one certificate.
Implementation Copy for DecodeLimits#
impl Copy for DecodeLimitsImplementation DecodeLimits#
impl DecodeLimitsAssociated function defaults#
pub fn defaults() -> DecodeLimitsReturns the default limits: 16 MiB of input, 1 MiB for each certificate, 8 MiB of DER in total, 1024 certificates, 256 KiB for each field, 256 extensions, a depth of 32, and 65536 DER values for each certificate.
DecodeClass#
pub enum DecodeClassThe kind of a DecodeError.
Malformed#
MalformedThe input breaks a rule of PEM, DER, or the X.509 structure.
Unsupported#
UnsupportedThe input is valid, but its version or PEM label is not supported.
ResourceLimit#
ResourceLimitThe input goes over a DecodeLimits value or a size that the target can hold.
Implementation Debug for DecodeClass#
impl Debug for DecodeClassOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant, such as Malformed.
DecodeReason#
pub enum DecodeReasonThe rule that a DecodeError broke.
EmptyInput#
EmptyInputThe input has no certificate.
PemSyntax#
PemSyntaxA PEM marker or a byte between the markers is not valid.
Base64#
Base64The Base64 has a character, padding, or unused bits that are not valid.
TrailingData#
TrailingDataThere are bytes after the one certificate that the function reads.
Truncated#
TruncatedThe input ends before a value is complete.
Tag#
TagA DER tag is not valid.
Length#
LengthA DER length is not in its shortest form.
Integer#
IntegerAn INTEGER is empty or not in its shortest form.
Boolean#
BooleanA BOOLEAN is not one byte of 0x00 or 0xff.
BitString#
BitStringThe unused-bit count of a BIT STRING, or its unused bits, are not valid.
Oid#
OidAn object identifier is not valid.
SetOrder#
SetOrderThe values of a SET OF in a name are not in DER order.
DefaultValue#
DefaultValueA field that has its default value is encoded. DER does not allow it.
Time#
TimeA time or date is not valid.
Schema#
SchemaThe fields do not have the structure of an X.509 certificate.
StringEncoding#
StringEncodingA text field does not follow its string type.
Version#
VersionThe version is not v1, v2, or v3.
PemLabel#
PemLabelThe PEM label is not CERTIFICATE.
InputBytes#
InputBytesThe input is longer than inputBytes.
CertificateBytes#
CertificateBytesA certificate is longer than certificateBytes.
TotalDerBytes#
TotalDerBytesAll certificates together are longer than totalDerBytes.
Certificates#
CertificatesThere are more certificates than certificates.
FieldBytes#
FieldBytesA field is longer than fieldBytes.
Extensions#
ExtensionsA certificate has more extensions than extensions.
Depth#
DepthThe DER values nest deeper than depth.
Nodes#
NodesA certificate has more DER values than nodes.
SizeOverflow#
SizeOverflowA length, a tag number, or an allocation size does not fit in usize.
Implementation Debug for DecodeReason#
impl Debug for DecodeReasonOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant, such as EmptyInput.
DecodeOffsetSpace#
pub enum DecodeOffsetSpaceThe bytes that DecodeError.offset counts in.
Input#
InputThe offset is a position in the input that you gave.
Der#
DerThe offset is a position in the DER of the PEM block at certificateIndex, after Base64
decoding.
Implementation Debug for DecodeOffsetSpace#
impl Debug for DecodeOffsetSpaceOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant, such as Input.
CertificateVersion#
pub enum CertificateVersionThe X.509 version of a certificate.
V1#
V1Version 1. The version field is absent.
V2#
V2Version 2.
V3#
V3Version 3. Most certificates use it, because only v3 has extensions.
DecodeError#
pub struct DecodeErrorA certificate decoding error, with the rule and the position. It does not borrow the input.
Details#
reason gives the rule that the input broke. offset gives the position, and offsetSpace
tells if offset counts in the input or in the decoded DER.
Field kind#
pub kind: DecodeClassThe kind of error.
Field reason#
pub reason: DecodeReasonThe rule that the input broke.
Field certificateIndex#
pub certificateIndex: usizeThe index of the certificate that failed, from 0. Errors in the document itself use 0.
Field offsetSpace#
pub offsetSpace: DecodeOffsetSpaceTells you if offset counts in the input or in the decoded DER.
Field offset#
pub offset: usizeThe position of the byte or tag that failed, or the position where missing data must be.
Implementation Copy for DecodeError#
impl Copy for DecodeErrorImplementation Debug for DecodeError#
impl Debug for DecodeErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the fields, as DecodeError { kind: ..., reason: ..., ... }.
CertificateTime#
pub struct CertificateTimeA date and time in UTC from a certificate.
Field year#
pub year: u16The year, from 1 to 9999.
Field month#
pub month: u8The month, from 1 to 12.
Field day#
pub day: u8The day of the month.
Field hour#
pub hour: u8The hour, from 0 to 23.
Field minute#
pub minute: u8The minute, from 0 to 59.
Field second#
pub second: u8The second, from 0 to 59.
Implementation Copy for CertificateTime#
impl Copy for CertificateTimeBitStringView#
pub struct BitStringView<'a>The content of a BIT STRING, such as a public key or a signature. It borrows the certificate.
Field bytes#
pub bytes: &'a [u8]The bits, without the first byte that counts the unused bits.
Field unusedBits#
pub unusedBits: u8The number of unused bits at the end of the last byte. Keys and signatures use 0.
AlgorithmView#
pub struct AlgorithmView<'a>An algorithm identifier, such as the signature algorithm. It borrows the certificate.
Field der#
pub der: &'a [u8]The full DER of the AlgorithmIdentifier.
Field oid#
pub oid: &'a [u8]The bytes of the object identifier, without the tag and the length.
Field parametersDer#
pub parametersDer: Option<&'a [u8]>The full DER of the parameters, or None if they are absent. Absent parameters and an
explicit NULL are different.
CertificateOffsets#
pub struct CertificateOffsetsThe positions of the main fields in the DER of a certificate. Use them to point at a field in an error message.
Field tbs#
pub tbs: usizeThe position of the TBSCertificate, the part that the issuer signs.
Field version#
pub version: usizeThe position of the version field, or the first TBSCertificate field if the version is absent.
Field serial#
pub serial: usizeThe position of the serial number.
Field tbsSignatureAlgorithm#
pub tbsSignatureAlgorithm: usizeThe position of the signature algorithm inside the TBSCertificate.
Field issuer#
pub issuer: usizeThe position of the issuer name.
Field subject#
pub subject: usizeThe position of the subject name.
Field spki#
pub spki: usizeThe position of the SubjectPublicKeyInfo.
Field publicKey#
pub publicKey: usizeThe position of the public key BIT STRING.
Field signatureAlgorithm#
pub signatureAlgorithm: usizeThe position of the outer signature algorithm.
Field signature#
pub signature: usizeThe position of the signature BIT STRING.
Field issuerUniqueId#
pub issuerUniqueId: usizeThe position of the issuer unique ID, or the TBSCertificate if it is absent.
Field subjectUniqueId#
pub subjectUniqueId: usizeThe position of the subject unique ID, or the TBSCertificate if it is absent.
ExtensionView#
pub struct ExtensionView<'a>One extension of a certificate, as it is in the DER. It borrows the certificate.
Field offset#
pub offset: usizeThe position of the extension in the DER of the certificate.
Field valueOffset#
pub valueOffset: usizeThe position of the extension value in the DER of the certificate.
Field der#
pub der: &'a [u8]The full DER of the extension.
Field oid#
pub oid: &'a [u8]The bytes of the extension object identifier, without the tag and the length.
Field critical#
pub critical: booltrue if the extension is marked critical. An absent flag is false.
Field value#
pub value: &'a [u8]The bytes inside the extension OCTET STRING. They are not decoded.
Certificate#
pub struct CertificateA decoded X.509 certificate that owns its DER bytes.
When to use#
Make one with Certificate.decodePem for a .pem or .crt file with one CERTIFICATE
block, or with Certificate.decodeDer for binary DER, such as a certificate from a TLS
handshake. For a file with more than one certificate, use silk.tls.certificate_bundle.
Details#
The accessors return slices of the DER, such as Certificate.subjectDer, and decoded values,
such as Certificate.notAfter. Nothing is normalized: names, algorithms, and extensions keep
their original bytes.
The accessors borrow the certificate. Unknown algorithms, duplicate extensions, and other values
that a validator can reject stay available, so that silk.tls.certificate_profile can check them.
Gotchas#
Decoding checks only the structure. It does not verify the signature, the chain, the names, or
the dates. Use silk.tls.certificate_path for that.
Implementation Certificate#
impl CertificateMethod copy#
pub effect fn copy(self: &Self) -> Certificate ! OutOfMemoryError ? &mut AllocatorReturns a copy of the certificate. It does not decode again.
Errors#
OutOfMemoryErrorif theAllocatorfails.
Associated function decodeDer#
pub effect fn decodeDer(input: &[u8], limits: DecodeLimits) -> Result<Certificate, DecodeError>
! OutOfMemoryError
? &mut AllocatorDecodes one DER certificate from input, and copies it.
All of input must be the certificate. Bytes after it, also whitespace, are an error. The
limits in limits bound the work for input that you do not control.
Errors#
Failurewith aDecodeErrorifinputis not one valid certificate or goes over a limit.OutOfMemoryErrorif theAllocatorfails.
Gotchas#
Decoding checks only the structure. It does not verify the signature, the chain, the names,
or the dates. Use silk.tls.certificate_path for that.
Associated function decodePem#
pub effect fn decodePem(input: &[u8], limits: DecodeLimits) -> Result<Certificate, DecodeError>
! OutOfMemoryError
? &mut AllocatorDecodes one PEM CERTIFICATE block from input.
Spaces, tabs, CR, and LF are allowed around the Base64 lines. The Base64 must be canonical.
Errors#
Failurewith aDecodeErrorif there is text outside the block, a second block, another label, or a certificate that is not valid.OutOfMemoryErrorif theAllocatorfails.
Gotchas#
Some PEM readers ignore text outside the block. This one does not. Use
CertificateBundle.decodeAnnotatedPem for a CA file with comments.
Decoding checks only the structure. It does not verify the signature, the chain, the names,
or the dates. Use silk.tls.certificate_path for that.
Method tbsDer#
pub fn tbsDer(self: &Self) -> &[u8]Returns the DER of the TBSCertificate, the part that the issuer signs.
Method issuerDer#
pub fn issuerDer(self: &Self) -> &[u8]Returns the DER of the issuer name, as it is. It is not normalized.
Method subjectDer#
pub fn subjectDer(self: &Self) -> &[u8]Returns the DER of the subject name, as it is. It is not normalized.
Method validityDer#
pub fn validityDer(self: &Self) -> &[u8]Returns the DER of the validity period.
Method spkiDer#
pub fn spkiDer(self: &Self) -> &[u8]Returns the DER of the SubjectPublicKeyInfo: the key algorithm and the public key.
Method der#
pub fn der(self: &Self) -> &[u8]Returns the full DER of the certificate.
Method version#
pub fn version(self: &Self) -> CertificateVersionReturns the X.509 version.
Method offsets#
pub fn offsets(self: &Self) -> CertificateOffsetsReturns the positions of the main fields in Certificate.der.
Method serial#
pub fn serial(self: &Self) -> &[u8]Returns the bytes of the serial number, as a big-endian signed integer. A leading zero byte is kept when the high bit is set.
Method notBefore#
pub fn notBefore(self: &Self) -> CertificateTimeReturns the start of the validity period. It does not read a clock.
Method notAfter#
pub fn notAfter(self: &Self) -> CertificateTimeReturns the end of the validity period. It does not check that it is after
Certificate.notBefore.
Method publicKey#
pub fn publicKey<'a>(self: &'a Self) -> BitStringView<'a>Returns the subject public key bits.
Method signature#
pub fn signature<'a>(self: &'a Self) -> BitStringView<'a>Returns the signature bits.
Method publicKeyAlgorithm#
pub fn publicKeyAlgorithm<'a>(self: &'a Self) -> AlgorithmView<'a>Returns the algorithm of the subject public key.
Method tbsSignatureAlgorithm#
pub fn tbsSignatureAlgorithm<'a>(self: &'a Self) -> AlgorithmView<'a>Returns the signature algorithm inside the TBSCertificate. It must be the same as
Certificate.signatureAlgorithm, but this function does not check it.
Method signatureAlgorithm#
pub fn signatureAlgorithm<'a>(self: &'a Self) -> AlgorithmView<'a>Returns the outer signature algorithm, which the issuer used to sign.
Method issuerUniqueId#
pub fn issuerUniqueId<'a>(self: &'a Self) -> Option<BitStringView<'a>>Returns the issuer unique ID, or None if it is absent. Modern certificates do not use it.
Method subjectUniqueId#
pub fn subjectUniqueId<'a>(self: &'a Self) -> Option<BitStringView<'a>>Returns the subject unique ID, or None if it is absent. Modern certificates do not use it.
Method extensionCount#
pub fn extensionCount(self: &Self) -> usizeReturns the number of extensions, with unknown and duplicate ones.
Method extension#
pub fn extension<'a>(self: &'a Self, index: usize) -> Option<ExtensionView<'a>>Returns the extension at index in source order, or None if index is out of range. The
value is not decoded.
Category: TLS and certificates.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.