tor_netdoc/doc/authcert/
build.rs1#![allow(deprecated)]
6
7use super::{AuthCert, AuthCertVersion, CrossCert, CrossCertObject};
8
9use crate::{BuildError as Error, BuildResult};
10use std::net::SocketAddrV4;
11use std::ops::Range;
12use std::time::SystemTime;
13use tor_llcrypto::pk::rsa;
14
15#[deprecated = "use AuthCertConstructor instead"]
22#[cfg_attr(docsrs, doc(cfg(feature = "build_docs")))]
23pub struct AuthCertBuilder {
24 address: Option<SocketAddrV4>,
26 identity_key: Option<rsa::PublicKey>,
28 signing_key: Option<rsa::PublicKey>,
30 published: Option<SystemTime>,
32 expires: Option<SystemTime>,
34}
35
36impl AuthCertBuilder {
37 pub(crate) fn new() -> Self {
39 AuthCertBuilder {
40 address: None,
41 identity_key: None,
42 signing_key: None,
43 published: None,
44 expires: None,
45 }
46 }
47
48 pub fn address(&mut self, address: SocketAddrV4) -> &mut Self {
52 self.address = Some(address);
53 self
54 }
55
56 pub fn identity_key(&mut self, key: rsa::PublicKey) -> &mut Self {
60 self.identity_key = Some(key);
61 self
62 }
63
64 pub fn signing_key(&mut self, key: rsa::PublicKey) -> &mut Self {
68 self.signing_key = Some(key);
69 self
70 }
71
72 pub fn lifespan(&mut self, lifespan: Range<SystemTime>) -> &mut Self {
76 self.published = Some(lifespan.start);
77 self.expires = Some(lifespan.end);
78 self
79 }
80
81 pub fn dangerous_testing_cert(&self) -> BuildResult<AuthCert> {
94 let dir_key_published = self
95 .published
96 .ok_or(Error::CannotBuild("Missing published time"))?
97 .into();
98 let dir_key_expires = self
99 .expires
100 .ok_or(Error::CannotBuild("Missing expiration time"))?
101 .into();
102 if dir_key_expires < dir_key_published {
103 return Err(Error::CannotBuild("Expires before published time."));
104 }
105 let dir_identity_key = self
106 .identity_key
107 .as_ref()
108 .ok_or(Error::CannotBuild("Missing identity key."))?
109 .clone();
110 let dir_signing_key = self
111 .signing_key
112 .as_ref()
113 .ok_or(Error::CannotBuild("Missing signing key."))?
114 .clone();
115
116 let id_fingerprint = dir_identity_key.to_rsa_identity();
117
118 let dir_key_crosscert = CrossCert {
120 signature: CrossCertObject(vec![]),
121 };
122
123 Ok(AuthCert {
124 dir_address: self.address,
125 dir_identity_key,
126 dir_signing_key,
127 dir_key_published,
128 dir_key_expires,
129 fingerprint: crate::types::Fingerprint(id_fingerprint),
130 dir_key_certificate_version: AuthCertVersion::V3,
131 dir_key_crosscert,
132 __non_exhaustive: (),
133 })
134 }
135}
136
137#[cfg(test)]
138mod test {
139 #![allow(clippy::bool_assert_comparison)]
141 #![allow(clippy::clone_on_copy)]
142 #![allow(clippy::dbg_macro)]
143 #![allow(clippy::mixed_attributes_style)]
144 #![allow(clippy::print_stderr)]
145 #![allow(clippy::print_stdout)]
146 #![allow(clippy::single_char_pattern)]
147 #![allow(clippy::unwrap_used)]
148 #![allow(clippy::unchecked_time_subtraction)]
149 #![allow(clippy::useless_vec)]
150 #![allow(clippy::needless_pass_by_value)]
151 use super::*;
153 use hex_literal::hex;
154 use std::time::Duration;
155 use web_time_compat::SystemTimeExt;
156
157 fn rsa1() -> rsa::PublicKey {
158 let der = hex!(
159 "30818902818100d527b6c63d6e81d39c328a94ce157dccdc044eb1ad8c210c9c9e22487b4cfade6d4041bd10469a657e3d82bc00cf62ac3b6a99247e573b54c10c47f5dc849b0accda031eca6f6e5dc85677f76dec49ff24d2fcb2b5887fb125aa204744119bb6417f45ee696f8dfc1c2fc21b2bae8e9e37a19dc2518a2c24e7d8fd7fac0f46950203010001"
160 );
161 rsa::PublicKey::from_der(&der).unwrap()
162 }
163
164 fn rsa2() -> rsa::PublicKey {
165 let der = hex!(
166 "3082010a0282010100d4e420607eddac8264d888cf89a7af78e619db21db5a4671497797614826316f13e2136fd65ed12bbebb724aa6c214d9ceb30a28053778c3da25b87cdb24a246ba427726e17c60b507ed26d8c6377aa14f611dc12f7a7e67ada07fd04e42225a0b84331e347373590f41410c11853e42ee9a34e95a7715edddb651b063e12bf3a58b8c5dce5efd2681d1d4a6ba02def665eb2ba64520577f4d659849858a10f9303fbd934be8a1a461dbe5d7bf0c12c2a3281c63dcdd28f77f5516046253cf7f7a907c15ed2f7baf0aac4c9be3092ec173e15881aebc5d53b5c73dbc545684165510926d8ca202f2e06faaf0da35950c162bf36a2868006837b8b39b61c5b2b10203010001"
167 );
168 rsa::PublicKey::from_der(&der).unwrap()
169 }
170
171 #[test]
172 fn simple_cert() {
173 let now = SystemTime::get();
174 let one_hour = Duration::new(3600, 0);
175 let later = now + one_hour * 2;
176 let addr = "192.0.0.1:9090".parse().unwrap();
177 let cert = AuthCert::builder()
178 .identity_key(rsa2())
179 .signing_key(rsa1())
180 .address(addr)
181 .lifespan(now..later)
182 .dangerous_testing_cert()
183 .unwrap();
184
185 assert_eq!(cert.key_ids().id_fingerprint, rsa2().to_rsa_identity());
186 assert_eq!(cert.key_ids().sk_fingerprint, rsa1().to_rsa_identity());
187 assert_eq!(cert.published(), now);
188 assert_eq!(cert.expires(), later);
189 }
190
191 #[test]
192 fn failing_cert() {
193 let now = SystemTime::get();
194 let one_hour = Duration::new(3600, 0);
195 let later = now + one_hour * 2;
196
197 {
198 let c = AuthCert::builder()
199 .identity_key(rsa1())
200 .lifespan(now..later)
201 .dangerous_testing_cert();
202 assert!(c.is_err()); }
204
205 {
206 let c = AuthCert::builder()
207 .signing_key(rsa1())
208 .lifespan(now..later)
209 .dangerous_testing_cert();
210 assert!(c.is_err()); }
212
213 {
214 let c = AuthCert::builder()
215 .signing_key(rsa1())
216 .identity_key(rsa2())
217 .dangerous_testing_cert();
218 assert!(c.is_err()); }
220
221 {
222 let c = AuthCert::builder()
223 .signing_key(rsa1())
224 .identity_key(rsa2())
225 .lifespan(later..now)
226 .dangerous_testing_cert();
227 assert!(c.is_err()); }
229 }
230}