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