silk.tls.certificate_text.
Text forms of certificate fields as OpenSSL prints them: object names, distinguished names, validity times, and serial numbers.
When to use#
Use it to show a certificate the way OpenSSL and Node.js do, such as X509Certificate.subject,
issuer, validFrom, serialNumber, and signatureAlgorithm in Node.js, or the DirName
entries of subjectAltName.
Details#
CertificateText.objectName looks up the short and long names of an object identifier in
the object table of OpenSSL 3.0, and CertificateText.writeObjectIdentifier writes the
dotted form, such as 1.2.840.113549.1.1.11.
CertificateText.writeName writes a DER Name, such as Certificate.subjectDer, in one
of the NameTextFormat layouts. It decodes BMPString, UniversalString, and the 8-bit string
types to UTF-8 and escapes as RFC 2253 does. It checks the strings as OpenSSL does when it
reads a name, so a name that OpenSSL rejects is an error here too.
CertificateText.writeTime writes a CertificateTime as Jan 2 03:04:05 2025 GMT, and
CertificateText.writeSerial writes a serial number in upper-case hexadecimal.
Errors#
CertificateTextErrorfor DER that is not valid, or an output that is too short.
Gotchas#
The text is for display and logs. Compare names by their DER, not by this text: two different names can print the same. The object table is the one of OpenSSL 3.0, so a newer identifier prints in dotted form.
Examples#
Print a subject#
import silk.core.result { Result }
import silk.collections.slice { Slice }
import silk.tls.certificate_text { CertificateText, CertificateTextError, NameTextFormat }
pub fn main() -> i32 {
// SEQUENCE { SET { SEQUENCE { commonName, UTF8String "a,b" } } }
let name = b"\x30\x0e\x31\x0c\x30\x0a\x06\x03\x55\x04\x03\x0c\x03\x61\x2c\x62"
let mut text: [u8; 16] = [0; 16]
let length = match CertificateText.writeName(name, NameTextFormat.Multiline, &mut text) {
Result<usize, CertificateTextError>.Success { value } => value
Result<usize, CertificateTextError>.Failure { error: _ } => {
return 1
}
}
// The comma is escaped: CN=a\,b
if length != 7 || text[4] != 92 {
return 2
}
return 42
}Import as CertificateText with import silk.tls.certificate_text { CertificateText }.
Public declarations: 4.
CertificateTextError#
pub enum CertificateTextErrorThe reason that a certificate field could not be written as text.
InvalidEncoding#
InvalidEncodingThe DER is not valid, not minimal, has bytes after it, or holds a string that OpenSSL rejects, such as a UTF8String that is not UTF-8.
OutputTooSmall#
OutputTooSmallThe output is shorter than the text. Its first bytes may have been written.
NameTextFormat#
pub enum NameTextFormatHow CertificateText.writeName lays out a distinguished name.
Multiline#
MultilineOne attribute per line in the order of the DER, such as C=US\nO=Example\nCN=example.com,
with + between the attributes of one RDN. Control characters are escaped as \XX.
Node.js uses it for X509Certificate.subject and issuer (OpenSSL's
XN_FLAG_SEP_MULTILINE with ASN1_STRFLGS_ESC_2253, ESC_CTRL, and UTF8_CONVERT).
Rfc2253#
Rfc2253RFC 2253: the RDNs in reverse order, separated by ,, with + inside an RDN, such as
CN=example.com,O=Example,C=US. An attribute with an unknown type, or a value that is not
a string, is written as # and the hexadecimal DER of the value. Control characters are
not escaped. Node.js uses it for the DirName entries of subjectAltName (OpenSSL's
XN_FLAG_RFC2253 without ESC_CTRL and ESC_MSB).
ObjectName#
pub struct ObjectNameThe names of an object identifier in the object table of OpenSSL.
Field identifier#
pub identifier: &'static [u8]The DER content of the object identifier, such as \x55\x04\x03 for 2.5.4.3.
Field shortName#
pub shortName: &'static [u8]The short name, such as CN or RSA-SHA256.
Field longName#
pub longName: &'static [u8]The long name, such as commonName or sha256WithRSAEncryption.
Implementation Copy for ObjectName#
impl Copy for ObjectNameCertificateText#
pub struct CertificateTextFunctions that write certificate fields as text.
Implementation CertificateText#
impl CertificateTextAssociated function objectName#
pub fn objectName(identifier: &[u8]) -> Option<ObjectName>Returns the names of the object identifier whose DER content is identifier, or None
when the object table of OpenSSL has no entry for it.
Associated function namedObject#
pub fn namedObject(name: &[u8]) -> Option<ObjectName>Returns the object whose short name or long name is name, as OpenSSL's OBJ_txt2nid
finds it: short names first, then long names. The match is exact and case-sensitive.
Associated function objectIdentifierLength#
pub fn objectIdentifierLength(identifier: &[u8]) -> Result<usize, CertificateTextError>Returns the length in bytes of CertificateText.writeObjectIdentifier.
Errors#
InvalidEncodingas withCertificateText.writeObjectIdentifier.
Associated function writeObjectIdentifier#
pub fn writeObjectIdentifier(identifier: &[u8], output: &mut [u8]) -> Result<
usize,
CertificateTextError,
>Writes the dotted form of the object identifier whose DER content is identifier, such as
2.5.4.3, to the start of output and returns its length, as OpenSSL's OBJ_obj2txt
does with numeric output.
Errors#
InvalidEncodingifidentifieris empty, a sub-identifier has a leading0x80byte or is not finished, or an arc has more than 1024 decimal digits.OutputTooSmallifoutputis shorter than the text.
Associated function nameLength#
pub fn nameLength(name: &[u8], format: NameTextFormat) -> Result<usize, CertificateTextError>Returns the length in bytes of CertificateText.writeName.
Errors#
InvalidEncodingas withCertificateText.writeName.
Associated function writeName#
pub fn writeName(name: &[u8], format: NameTextFormat, output: &mut [u8]) -> Result<
usize,
CertificateTextError,
>Writes the DER Name name as text in format to the start of output and returns its
length. An empty name is empty text.
Details#
Each attribute is its short name from the object table, or its dotted identifier, then =
and the value. A UTF8String is written as it is, the 8-bit string types as Latin-1, and
BMPString and UniversalString as UTF-8. ", +, ,, ;, <, >, and \ are escaped
with \, and so are a leading space or # and a trailing space.
Errors#
InvalidEncodingif the DER is not valid or not minimal, or a value is a type or string that OpenSSL rejects in a name: a UTF8String that is not UTF-8, a BMPString or UniversalString with a surrogate or a bad length, or a tag such as INTEGER.OutputTooSmallifoutputis shorter than the text.
Associated function writeTime#
pub fn writeTime(time: CertificateTime, output: &mut [u8; 24]) -> usizeWrites time as OpenSSL's ASN1_TIME_print does, such as Jan 2 03:04:05 2025 GMT, to
the start of output and returns its length. The day is padded to two places with a
space and the year is not padded.
Associated function serialLength#
pub fn serialLength(serial: &[u8]) -> Result<usize, CertificateTextError>Returns the length in bytes of CertificateText.writeSerial.
Errors#
InvalidEncodingifserialis empty.
Associated function writeSerial#
pub fn writeSerial(serial: &[u8], output: &mut [u8]) -> Result<usize, CertificateTextError>Writes the big-endian signed integer serial, such as Certificate.serial, in
upper-case hexadecimal to the start of output and returns its length, as OpenSSL's
BN_bn2hex does: whole bytes without leading zero bytes, such as 0A1B, 0 for zero,
and - before the magnitude of a negative number.
Errors#
InvalidEncodingifserialis empty.OutputTooSmallifoutputis shorter than the text.
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, x86_64-pc-windows-msvc, wasm64-unknown-unknown.