KeyCertificate

Struct KeyCertificate 

Source
pub struct KeyCertificate {
    pub version: Option<u32>,
    pub address: Option<IpAddr>,
    pub dir_port: Option<u16>,
    pub fingerprint: Option<String>,
    pub identity_key: Option<String>,
    pub published: Option<DateTime<Utc>>,
    pub expires: Option<DateTime<Utc>>,
    pub signing_key: Option<String>,
    pub crosscert: Option<String>,
    pub certification: Option<String>,
    /* private fields */
}
Expand description

A directory authority key certificate.

Key certificates are used in Tor’s v3 directory protocol to bind a directory authority’s long-term identity key to a medium-term signing key. This allows authorities to rotate their signing keys without changing their identity.

§Structure

A key certificate contains:

  • Version information (currently version 3)
  • Authority network address and port
  • Authority fingerprint (SHA-1 hash of identity key)
  • Validity period (published and expiration times)
  • The identity key (long-term, kept offline)
  • The signing key (medium-term, used for votes/consensus)
  • Cross-certification signatures proving key binding

§Mandatory Fields

The following fields are required for a valid certificate:

  • version
  • fingerprint
  • published
  • expires
  • identity_key
  • signing_key
  • certification

§Example

use stem_rs::descriptor::KeyCertificate;

let cert_content = r#"dir-key-certificate-version 3
fingerprint BCB380A633592C218757BEE11E630511A485658A
dir-key-published 2024-01-01 00:00:00
dir-key-expires 2025-01-01 00:00:00
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-key-certification
-----BEGIN SIGNATURE-----
AAAA
-----END SIGNATURE-----
"#;

let cert = KeyCertificate::parse(cert_content)?;
println!("Authority fingerprint: {:?}", cert.fingerprint);
println!("Certificate expired: {}", cert.is_expired());

§Security

  • Check is_expired() before trusting a certificate
  • Certificates should be obtained from trusted sources
  • The signatures should be cryptographically verified (not done by this parser)

Fields§

§version: Option<u32>

Certificate format version (currently 3).

Version 3 is the only version currently in use. This field indicates the format of the certificate and which fields are expected.

§address: Option<IpAddr>

IP address where the authority’s directory service is available.

This is the address clients can use to fetch directory information directly from this authority. May be IPv4 or IPv6.

§dir_port: Option<u16>

Port number for the authority’s directory service.

Combined with address, this forms the complete endpoint for directory requests.

§fingerprint: Option<String>

SHA-1 fingerprint of the authority’s identity key.

This is a 40-character hexadecimal string representing the SHA-1 hash of the authority’s long-term identity key. It uniquely identifies the authority across the Tor network.

§identity_key: Option<String>

The authority’s long-term identity key in PEM format.

This RSA public key is the authority’s permanent identifier. It is kept offline and used only to sign key certificates. The key is encoded as a PEM block with type “RSA PUBLIC KEY”.

§published: Option<DateTime<Utc>>

Time when this certificate was generated.

Certificates should not be used before their published time. This timestamp is in UTC.

§expires: Option<DateTime<Utc>>

Time after which this certificate is no longer valid.

Certificates should not be trusted after their expiration time. Use is_expired() to check validity. This timestamp is in UTC.

§signing_key: Option<String>

The authority’s medium-term signing key in PEM format.

This RSA public key is used to sign votes and consensus documents. It is rotated periodically (typically every few months) and a new key certificate is issued for each rotation.

§crosscert: Option<String>

Cross-certification signature from the signing key.

This signature, made with the signing key, proves that the signing key holder authorized the binding to the identity key. Encoded as a PEM block with type “ID SIGNATURE”.

§certification: Option<String>

Certification signature from the identity key.

This signature, made with the identity key, proves that the identity key holder authorized the signing key. This is the primary authentication of the certificate. Encoded as a PEM block with type “SIGNATURE”.

Implementations§

Source§

impl KeyCertificate

Source

pub fn parse(content: &str) -> Result<Self, Error>

Parses a key certificate from its string representation.

This method parses the certificate with full validation enabled, ensuring all mandatory fields are present and correctly formatted.

§Arguments
  • content - The certificate content as a string
§Returns

A parsed KeyCertificate on success.

§Errors

Returns Error::Parse if:

  • The certificate doesn’t start with dir-key-certificate-version
  • The certificate doesn’t end with dir-key-certification
  • Any mandatory field is missing
  • Any field has an invalid format (e.g., invalid fingerprint, datetime)
  • Key blocks are malformed or incomplete
§Example
use stem_rs::descriptor::KeyCertificate;

let content = r#"dir-key-certificate-version 3
fingerprint BCB380A633592C218757BEE11E630511A485658A
dir-key-published 2024-01-01 00:00:00
dir-key-expires 2025-01-01 00:00:00
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-key-certification
-----BEGIN SIGNATURE-----
AAAA
-----END SIGNATURE-----
"#;

let cert = KeyCertificate::parse(content)?;
assert_eq!(cert.version, Some(3));
Source

pub fn parse_with_validation( content: &str, validate: bool, ) -> Result<Self, Error>

Parses a key certificate with optional validation.

This method allows parsing certificates that may be incomplete or malformed by disabling validation. This is useful for:

  • Parsing partial certificates for debugging
  • Handling certificates from untrusted sources gracefully
  • Testing and development
§Arguments
  • content - The certificate content as a string
  • validate - If true, validates all fields and structure; if false, parses what it can without errors
§Returns

A parsed KeyCertificate on success. With validation disabled, many fields may be None even if they would normally be required.

§Errors

With validate = true, returns the same errors as parse(). With validate = false, only returns errors for fundamental parsing failures (e.g., completely unparseable content).

§Example
use stem_rs::descriptor::KeyCertificate;

// Parse incomplete certificate without validation
let partial = "dir-key-certificate-version 3\nfingerprint BCB380A633592C218757BEE11E630511A485658A\n";
let cert = KeyCertificate::parse_with_validation(partial, false)?;
assert_eq!(cert.version, Some(3));
assert!(cert.identity_key.is_none()); // Missing but no error
Source

pub fn raw_content(&self) -> &[u8]

Returns the raw bytes of the original certificate content.

This provides access to the exact bytes that were parsed, which is useful for:

  • Computing digests for signature verification
  • Storing certificates in their original format
  • Debugging parsing issues
§Returns

A byte slice containing the original certificate content.

Source

pub fn unrecognized_lines(&self) -> &[String]

Returns lines that were not recognized during parsing.

Unrecognized lines are preserved for forward compatibility with future certificate extensions. This allows newer certificate formats to be partially parsed by older code.

§Returns

A slice of strings, each representing an unrecognized line. Empty if all lines were recognized.

Source

pub fn is_expired(&self) -> bool

Checks if this certificate has expired.

A certificate is considered expired if the current time is past the certificate’s expiration time. Expired certificates should not be trusted for signature verification.

§Returns
  • true if the certificate has expired
  • false if the certificate is still valid or has no expiration time
§Example
use stem_rs::descriptor::KeyCertificate;

// Certificate with past expiration date
let old_cert_content = r#"dir-key-certificate-version 3
fingerprint BCB380A633592C218757BEE11E630511A485658A
dir-key-published 2017-01-01 00:00:00
dir-key-expires 2018-01-01 00:00:00
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-key-certification
-----BEGIN SIGNATURE-----
AAAA
-----END SIGNATURE-----
"#;

let cert = KeyCertificate::parse(old_cert_content)?;
assert!(cert.is_expired());
Source

pub fn to_descriptor_string(&self) -> String

Converts the certificate back to its string representation.

This produces a string in the standard key certificate format that can be parsed again or written to a file. The output follows the same format as the original certificate.

§Returns

A string containing the certificate in standard format.

§Note

The output may not be byte-for-byte identical to the original input due to whitespace normalization, but it will be semantically equivalent.

§Example
use stem_rs::descriptor::KeyCertificate;

let content = r#"dir-key-certificate-version 3
fingerprint BCB380A633592C218757BEE11E630511A485658A
dir-key-published 2024-01-01 00:00:00
dir-key-expires 2025-01-01 00:00:00
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA
-----END RSA PUBLIC KEY-----
dir-key-certification
-----BEGIN SIGNATURE-----
AAAA
-----END SIGNATURE-----
"#;

let cert = KeyCertificate::parse(content)?;
let output = cert.to_descriptor_string();
assert!(output.contains("dir-key-certificate-version 3"));
assert!(output.contains("fingerprint BCB380A633592C218757BEE11E630511A485658A"));

Trait Implementations§

Source§

impl Clone for KeyCertificate

Source§

fn clone(&self) -> KeyCertificate

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for KeyCertificate

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for KeyCertificate

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromStr for KeyCertificate

Source§

type Err = Error

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a string s to return a value of this type. Read more
Source§

impl PartialEq for KeyCertificate

Source§

fn eq(&self, other: &KeyCertificate) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for KeyCertificate

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.