tor_netdoc/doc/authcert/
build.rs1use super::{AuthCert, AuthCertKeyIds};
7
8use crate::{BuildError as Error, BuildResult};
9use std::net::SocketAddrV4;
10use std::ops::Range;
11use std::time::SystemTime;
12use tor_llcrypto::pk::rsa;
13
14#[cfg_attr(docsrs, doc(cfg(feature = "build_docs")))]
21pub struct AuthCertBuilder {
22 address: Option<SocketAddrV4>,
24 identity_key: Option<rsa::PublicKey>,
26 signing_key: Option<rsa::PublicKey>,
28 published: Option<SystemTime>,
30 expires: Option<SystemTime>,
32}
33
34impl AuthCertBuilder {
35 pub(crate) fn new() -> Self {
37 AuthCertBuilder {
38 address: None,
39 identity_key: None,
40 signing_key: None,
41 published: None,
42 expires: None,
43 }
44 }
45
46 pub fn address(&mut self, address: SocketAddrV4) -> &mut Self {
50 self.address = Some(address);
51 self
52 }
53
54 pub fn identity_key(&mut self, key: rsa::PublicKey) -> &mut Self {
58 self.identity_key = Some(key);
59 self
60 }
61
62 pub fn signing_key(&mut self, key: rsa::PublicKey) -> &mut Self {
66 self.signing_key = Some(key);
67 self
68 }
69
70 pub fn lifespan(&mut self, lifespan: Range<SystemTime>) -> &mut Self {
74 self.published = Some(lifespan.start);
75 self.expires = Some(lifespan.end);
76 self
77 }
78
79 pub fn dangerous_testing_cert(&self) -> BuildResult<AuthCert> {
92 let published = self
93 .published
94 .ok_or(Error::CannotBuild("Missing published time"))?;
95 let expires = self
96 .expires
97 .ok_or(Error::CannotBuild("Missing expiration time"))?;
98 if expires < published {
99 return Err(Error::CannotBuild("Expires before published time."));
100 }
101 let identity_key = self
102 .identity_key
103 .as_ref()
104 .ok_or(Error::CannotBuild("Missing identity key."))?
105 .clone();
106 let signing_key = self
107 .signing_key
108 .as_ref()
109 .ok_or(Error::CannotBuild("Missing signing key."))?
110 .clone();
111
112 let id_fingerprint = identity_key.to_rsa_identity();
113 let sk_fingerprint = signing_key.to_rsa_identity();
114
115 let key_ids = AuthCertKeyIds {
116 id_fingerprint,
117 sk_fingerprint,
118 };
119
120 Ok(AuthCert {
121 address: self.address,
122 identity_key,
123 signing_key,
124 published,
125 expires,
126 key_ids,
127 })
128 }
129}
130
131#[cfg(test)]
132mod test {
133 #![allow(clippy::bool_assert_comparison)]
135 #![allow(clippy::clone_on_copy)]
136 #![allow(clippy::dbg_macro)]
137 #![allow(clippy::mixed_attributes_style)]
138 #![allow(clippy::print_stderr)]
139 #![allow(clippy::print_stdout)]
140 #![allow(clippy::single_char_pattern)]
141 #![allow(clippy::unwrap_used)]
142 #![allow(clippy::unchecked_duration_subtraction)]
143 #![allow(clippy::useless_vec)]
144 #![allow(clippy::needless_pass_by_value)]
145 use super::*;
147 use hex_literal::hex;
148 use std::time::Duration;
149
150 fn rsa1() -> rsa::PublicKey {
151 let der = hex!(
152 "30818902818100d527b6c63d6e81d39c328a94ce157dccdc044eb1ad8c210c9c9e22487b4cfade6d4041bd10469a657e3d82bc00cf62ac3b6a99247e573b54c10c47f5dc849b0accda031eca6f6e5dc85677f76dec49ff24d2fcb2b5887fb125aa204744119bb6417f45ee696f8dfc1c2fc21b2bae8e9e37a19dc2518a2c24e7d8fd7fac0f46950203010001"
153 );
154 rsa::PublicKey::from_der(&der).unwrap()
155 }
156
157 fn rsa2() -> rsa::PublicKey {
158 let der = hex!(
159 "3082010a0282010100d4e420607eddac8264d888cf89a7af78e619db21db5a4671497797614826316f13e2136fd65ed12bbebb724aa6c214d9ceb30a28053778c3da25b87cdb24a246ba427726e17c60b507ed26d8c6377aa14f611dc12f7a7e67ada07fd04e42225a0b84331e347373590f41410c11853e42ee9a34e95a7715edddb651b063e12bf3a58b8c5dce5efd2681d1d4a6ba02def665eb2ba64520577f4d659849858a10f9303fbd934be8a1a461dbe5d7bf0c12c2a3281c63dcdd28f77f5516046253cf7f7a907c15ed2f7baf0aac4c9be3092ec173e15881aebc5d53b5c73dbc545684165510926d8ca202f2e06faaf0da35950c162bf36a2868006837b8b39b61c5b2b10203010001"
160 );
161 rsa::PublicKey::from_der(&der).unwrap()
162 }
163
164 #[test]
165 fn simple_cert() {
166 let now = SystemTime::now();
167 let one_hour = Duration::new(3600, 0);
168 let later = now + one_hour * 2;
169 let addr = "192.0.0.1:9090".parse().unwrap();
170 let cert = AuthCert::builder()
171 .identity_key(rsa2())
172 .signing_key(rsa1())
173 .address(addr)
174 .lifespan(now..later)
175 .dangerous_testing_cert()
176 .unwrap();
177
178 assert_eq!(cert.key_ids().id_fingerprint, rsa2().to_rsa_identity());
179 assert_eq!(cert.key_ids().sk_fingerprint, rsa1().to_rsa_identity());
180 assert_eq!(cert.published(), now);
181 assert_eq!(cert.expires(), later);
182 }
183
184 #[test]
185 fn failing_cert() {
186 let now = SystemTime::now();
187 let one_hour = Duration::new(3600, 0);
188 let later = now + one_hour * 2;
189
190 {
191 let c = AuthCert::builder()
192 .identity_key(rsa1())
193 .lifespan(now..later)
194 .dangerous_testing_cert();
195 assert!(c.is_err()); }
197
198 {
199 let c = AuthCert::builder()
200 .signing_key(rsa1())
201 .lifespan(now..later)
202 .dangerous_testing_cert();
203 assert!(c.is_err()); }
205
206 {
207 let c = AuthCert::builder()
208 .signing_key(rsa1())
209 .identity_key(rsa2())
210 .dangerous_testing_cert();
211 assert!(c.is_err()); }
213
214 {
215 let c = AuthCert::builder()
216 .signing_key(rsa1())
217 .identity_key(rsa2())
218 .lifespan(later..now)
219 .dangerous_testing_cert();
220 assert!(c.is_err()); }
222 }
223}