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:
versionfingerprintpublishedexpiresidentity_keysigning_keycertification
§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
impl KeyCertificate
Sourcepub fn parse(content: &str) -> Result<Self, Error>
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));Sourcepub fn parse_with_validation(
content: &str,
validate: bool,
) -> Result<Self, Error>
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 stringvalidate- Iftrue, validates all fields and structure; iffalse, 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 errorSourcepub fn raw_content(&self) -> &[u8] ⓘ
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.
Sourcepub fn unrecognized_lines(&self) -> &[String]
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.
Sourcepub fn is_expired(&self) -> bool
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
trueif the certificate has expiredfalseif 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());Sourcepub fn to_descriptor_string(&self) -> String
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
impl Clone for KeyCertificate
Source§fn clone(&self) -> KeyCertificate
fn clone(&self) -> KeyCertificate
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more