tor_relay_crypto/
certs.rs1use tor_cert::{CertEncodeError, CertType, CertifiedKey, Ed25519Cert, EncodedEd25519Cert};
4use tor_checkable::{SelfSigned, Timebound};
5use tor_key_forge::{InvalidCertError, ParsedEd25519Cert, ToEncodableCert};
6use tor_llcrypto::pk::ed25519::{self, Ed25519Identity};
7use web_time_compat::{SystemTime, SystemTimeExt};
8
9use crate::pk::{RelayIdentityKeypair, RelayLinkSigningKeypair, RelaySigningKeypair};
10
11pub fn gen_signing_cert(
20 kp_relay_id: &RelayIdentityKeypair,
21 kp_relaysign_id: &RelaySigningKeypair,
22 expiry: SystemTime,
23) -> Result<RelaySigningKeyCert, CertEncodeError> {
24 Ed25519Cert::builder()
25 .cert_type(RelaySigningKeyCert::cert_type())
26 .expiration(expiry)
27 .signing_key(kp_relay_id.to_ed25519_id())
28 .cert_key(CertifiedKey::Ed25519(kp_relaysign_id.to_ed25519_id()))
29 .encode_and_sign(kp_relay_id)
30 .map(RelaySigningKeyCert::from)
31}
32
33pub fn gen_link_cert(
36 kp_relaysign_id: &RelaySigningKeypair,
37 kp_link_id: &RelayLinkSigningKeypair,
38 expiry: SystemTime,
39) -> Result<RelayLinkSigningKeyCert, CertEncodeError> {
40 Ed25519Cert::builder()
41 .cert_type(RelayLinkSigningKeyCert::cert_type())
42 .expiration(expiry)
43 .signing_key(kp_relaysign_id.to_ed25519_id())
44 .cert_key(CertifiedKey::Ed25519(kp_link_id.to_ed25519_id()))
45 .encode_and_sign(kp_relaysign_id)
46 .map(RelayLinkSigningKeyCert::from)
47}
48
49pub fn gen_tls_cert(
52 kp_relaysign_id: &RelaySigningKeypair,
53 tls_digest: [u8; 32],
54 expiry: SystemTime,
55) -> Result<EncodedEd25519Cert, CertEncodeError> {
56 Ed25519Cert::builder()
57 .cert_type(CertType::SIGNING_V_TLS_CERT)
58 .expiration(expiry)
59 .signing_key(kp_relaysign_id.to_ed25519_id())
60 .cert_key(CertifiedKey::X509Sha256Digest(tls_digest))
61 .encode_and_sign(kp_relaysign_id)
62}
63
64#[derive(Debug, Clone, PartialEq, derive_more::From)]
75pub struct RelaySigningKeyCert(EncodedEd25519Cert);
76
77impl RelaySigningKeyCert {
78 fn cert_type() -> CertType {
80 CertType::IDENTITY_V_SIGNING
81 }
82}
83
84#[derive(Debug, Clone, PartialEq, derive_more::From)]
95pub struct RelayLinkSigningKeyCert(EncodedEd25519Cert);
96
97impl RelayLinkSigningKeyCert {
98 fn cert_type() -> CertType {
100 CertType::SIGNING_V_LINK_AUTH
101 }
102}
103
104impl ToEncodableCert<RelaySigningKeypair> for RelaySigningKeyCert {
105 type ParsedCert = ParsedEd25519Cert;
106 type EncodableCert = EncodedEd25519Cert;
107 type SigningKey = RelayIdentityKeypair;
108
109 fn validate(
110 cert: Self::ParsedCert,
111 subject: &RelaySigningKeypair,
112 signed_with: &Self::SigningKey,
113 ) -> Result<Self, InvalidCertError> {
114 let now = SystemTime::get();
116 validate_ed25519_cert(
117 cert,
118 &subject.public().into(),
119 &signed_with.public().into(),
120 Self::cert_type(),
121 &now,
122 )
123 .map(RelaySigningKeyCert::from)
124 }
125
126 fn to_encodable_cert(self) -> Self::EncodableCert {
127 self.0
128 }
129}
130
131impl ToEncodableCert<RelayLinkSigningKeypair> for RelayLinkSigningKeyCert {
132 type ParsedCert = ParsedEd25519Cert;
133 type EncodableCert = EncodedEd25519Cert;
134 type SigningKey = RelaySigningKeypair;
135
136 fn validate(
137 cert: Self::ParsedCert,
138 subject: &RelayLinkSigningKeypair,
139 signed_with: &Self::SigningKey,
140 ) -> Result<Self, InvalidCertError> {
141 let now = SystemTime::get();
143 validate_ed25519_cert(
144 cert,
145 &subject.public().into(),
146 &signed_with.public().into(),
147 Self::cert_type(),
148 &now,
149 )
150 .map(RelayLinkSigningKeyCert::from)
151 }
152
153 fn to_encodable_cert(self) -> Self::EncodableCert {
154 self.0
155 }
156}
157
158fn validate_ed25519_cert(
164 cert: ParsedEd25519Cert,
165 subject: &ed25519::PublicKey,
166 signed_with: &ed25519::PublicKey,
167 cert_type: CertType,
168 ts: &SystemTime,
169) -> Result<EncodedEd25519Cert, InvalidCertError> {
170 let cert = cert
171 .should_be_signed_with(&Ed25519Identity::from(signed_with))?
172 .check_signature()?;
173
174 let cert = cert.check_valid_at(ts)?;
175 let subject = Ed25519Identity::from(subject);
176
177 if subject != *cert.subject_key()? {
178 return Err(InvalidCertError::SubjectKeyMismatch);
179 }
180
181 let actual_cert_type = cert.as_ref().cert_type();
182 if actual_cert_type != cert_type {
183 return Err(InvalidCertError::CertType(actual_cert_type));
184 }
185
186 Ok(cert.into_encoded())
187}