1use crate::{internal_prelude::*, list_expired_keys_for_service};
13
14pub(crate) trait HsTimePeriodKeySpecifier: Debug {
21 fn nickname(&self) -> &HsNickname;
23 fn period(&self) -> &TimePeriod;
25}
26
27define_derive_deftly! {
28 HsTimePeriodKeySpecifier:
30
31 impl HsTimePeriodKeySpecifier for $ttype {
32 $(
33 ${when any(approx_equal($fname, nickname), approx_equal($fname, period))}
34 fn $fname(&self) -> &$ftype {
35 &self.$fname
36 }
37 )
38 }
39}
40
41#[derive(Deftly, PartialEq, Debug, Constructor)]
42#[derive_deftly(KeySpecifier)]
43#[deftly(prefix = "hss")]
44#[deftly(role = "KP_hs_id")]
45#[deftly(summary = "Public part of the identity key")]
46#[deftly(keypair_specifier = "HsIdKeypairSpecifier")]
47#[deftly(ctor_path = "HsIdPublicKey")]
48pub struct HsIdPublicKeySpecifier {
50 nickname: HsNickname,
52}
53
54#[derive(Deftly, PartialEq, Debug, Constructor)]
55#[derive_deftly(KeySpecifier)]
56#[deftly(prefix = "hss")]
57#[deftly(role = "KS_hs_id")]
58#[deftly(summary = "Long-term identity keypair")]
59#[deftly(ctor_path = "HsIdKeypair")]
60pub struct HsIdKeypairSpecifier {
62 pub(crate) nickname: HsNickname,
64}
65
66impl From<&HsIdPublicKeySpecifier> for HsIdKeypairSpecifier {
67 fn from(hs_id_public_key_specifier: &HsIdPublicKeySpecifier) -> HsIdKeypairSpecifier {
68 HsIdKeypairSpecifier::new(hs_id_public_key_specifier.nickname.clone())
69 }
70}
71
72#[derive(Deftly, PartialEq, Debug, Constructor)]
73#[derive_deftly(KeySpecifier, HsTimePeriodKeySpecifier)]
74#[deftly(prefix = "hss")]
75#[deftly(role = "KS_hs_blind_id")]
76#[deftly(summary = "Blinded signing keypair")]
77pub struct BlindIdKeypairSpecifier {
79 pub(crate) nickname: HsNickname,
81 #[deftly(denotator)]
82 pub(crate) period: TimePeriod,
84}
85
86#[derive(Deftly, PartialEq, Debug, Constructor)]
87#[derive_deftly(KeySpecifier, HsTimePeriodKeySpecifier)]
88#[deftly(prefix = "hss")]
89#[deftly(role = "KP_hs_blind_id")]
90#[deftly(keypair_specifier = "BlindIdKeypairSpecifier")]
91#[deftly(summary = "Blinded public key")]
92pub struct BlindIdPublicKeySpecifier {
94 pub(crate) nickname: HsNickname,
96 #[deftly(denotator)]
97 pub(crate) period: TimePeriod,
99}
100
101impl From<&BlindIdPublicKeySpecifier> for BlindIdKeypairSpecifier {
102 fn from(
103 hs_blind_id_public_key_specifier: &BlindIdPublicKeySpecifier,
104 ) -> BlindIdKeypairSpecifier {
105 BlindIdKeypairSpecifier::new(
106 hs_blind_id_public_key_specifier.nickname.clone(),
107 hs_blind_id_public_key_specifier.period,
108 )
109 }
110}
111
112#[derive(Deftly, PartialEq, Debug, Constructor)]
113#[derive_deftly(KeySpecifier, HsTimePeriodKeySpecifier)]
114#[deftly(prefix = "hss")]
115#[deftly(role = "KS_hs_desc_sign")]
116#[deftly(summary = "Descriptor signing key")]
117pub struct DescSigningKeypairSpecifier {
119 pub(crate) nickname: HsNickname,
121 #[deftly(denotator)]
122 pub(crate) period: TimePeriod,
124}
125
126#[derive(Debug, Deftly, Eq, PartialEq, strum::Display, strum::EnumString)]
128#[strum(serialize_all = "snake_case")]
129pub(crate) enum IptKeyRole {
130 KHssNtor,
132 KSid,
134}
135
136impl KeySpecifierComponentViaDisplayFromStr for IptKeyRole {}
137
138#[derive(Debug, Deftly, Eq, PartialEq)]
140#[derive_deftly(KeySpecifier)]
141#[deftly(prefix = "hss")]
142#[deftly(summary = "introduction point key")]
143pub(crate) struct IptKeySpecifier {
144 pub(crate) nick: HsNickname,
146 #[deftly(fixed_path_component = "ipts")]
148 #[deftly(role)]
149 pub(crate) role: IptKeyRole,
150 #[deftly(denotator)]
152 pub(crate) lid: IptLocalId,
153}
154
155pub(crate) fn expire_publisher_keys(
157 keymgr: &KeyMgr,
158 nickname: &HsNickname,
159 relevant_periods: &[HsDirParams],
160) -> tor_keymgr::Result<()> {
161 let keys_to_remove = list_expired_keys_for_service(relevant_periods, nickname, keymgr)?;
164 for entry in keys_to_remove {
165 keymgr.remove_entry(&entry)?;
166 }
167
168 Ok(())
169}
170
171#[cfg(test)]
172mod test {
173 #![allow(clippy::bool_assert_comparison)]
175 #![allow(clippy::clone_on_copy)]
176 #![allow(clippy::dbg_macro)]
177 #![allow(clippy::mixed_attributes_style)]
178 #![allow(clippy::print_stderr)]
179 #![allow(clippy::print_stdout)]
180 #![allow(clippy::single_char_pattern)]
181 #![allow(clippy::unwrap_used)]
182 #![allow(clippy::unchecked_time_subtraction)]
183 #![allow(clippy::useless_vec)]
184 #![allow(clippy::needless_pass_by_value)]
185 use super::*;
187 use tor_keymgr::KeySpecifier;
188 use tor_keymgr::test_utils::check_key_specifier;
189
190 #[test]
191 fn hsid_key_specifiers() {
192 let nickname = HsNickname::try_from("shallot".to_string()).unwrap();
193 let key_spec = HsIdPublicKeySpecifier::new(nickname.clone());
194 assert_eq!(
195 key_spec.arti_path().unwrap().as_str(),
196 "hss/shallot/kp_hs_id"
197 );
198
199 let key_spec = HsIdKeypairSpecifier::new(nickname);
200 check_key_specifier(&key_spec, "hss/shallot/ks_hs_id");
201 }
202
203 #[test]
204 fn blind_id_key_specifiers() {
205 let nickname = HsNickname::try_from("shallot".to_string()).unwrap();
206 let period = TimePeriod::from_parts(1, 2, 3);
207 let key_spec = BlindIdPublicKeySpecifier::new(nickname.clone(), period);
208 assert_eq!(
209 key_spec.arti_path().unwrap().as_str(),
210 "hss/shallot/kp_hs_blind_id+2_1_3"
211 );
212
213 let key_spec = BlindIdKeypairSpecifier::new(nickname, period);
214 check_key_specifier(&key_spec, "hss/shallot/ks_hs_blind_id+2_1_3");
215 }
216
217 #[test]
218 fn desc_signing_key_specifiers() {
219 let nickname = HsNickname::try_from("shallot".to_string()).unwrap();
220 let period = TimePeriod::from_parts(1, 2, 3);
221 let key_spec = DescSigningKeypairSpecifier::new(nickname, period);
222 check_key_specifier(&key_spec, "hss/shallot/ks_hs_desc_sign+2_1_3");
223 }
224
225 #[test]
226 fn ipt_key_specifiers() {
227 let nick = HsNickname::try_from("shallot".to_string()).unwrap();
228 let lid = IptLocalId::dummy(1);
229 let spec = |role| IptKeySpecifier {
230 nick: nick.clone(),
231 lid,
232 role,
233 };
234 let lid_s = "0101010101010101010101010101010101010101010101010101010101010101";
235 check_key_specifier(
236 &spec(IptKeyRole::KHssNtor),
237 &format!("hss/shallot/ipts/k_hss_ntor+{lid_s}"),
238 );
239 check_key_specifier(
240 &spec(IptKeyRole::KSid),
241 &format!("hss/shallot/ipts/k_sid+{lid_s}"),
242 );
243 }
244}