1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
//! This module is where all relay related keys are declared along their key specifier for the
//! KeyMgr so some of them can be stored on disk.
use std::fmt;
use std::time::SystemTime;
use derive_deftly::Deftly;
use derive_more::derive::{From, Into};
use derive_more::Constructor;
use tor_error::Bug;
use tor_key_forge::define_ed25519_keypair;
use tor_keymgr::{
derive_deftly_template_KeySpecifier, InvalidKeyPathComponentValue, KeySpecifier,
KeySpecifierComponent,
};
use tor_persist::slug::{timestamp::Iso8601TimeSlug, Slug};
// TODO: The legacy RSA key is needed. Require support in tor-key-forge and keystore.
// See https://gitlab.torproject.org/tpo/core/arti/-/work_items/1598
define_ed25519_keypair!(
/// [KP_relayid_ed] Long-term identity keypair. Never rotates.
pub RelayIdentity
);
#[non_exhaustive]
#[derive(Deftly, PartialEq, Debug, Constructor)]
#[derive_deftly(KeySpecifier)]
#[deftly(prefix = "relay")]
#[deftly(role = "KS_relayid_ed")]
#[deftly(summary = "Relay long-term identity keypair")]
/// The key specifier of the relay long-term identity key (RelayIdentityKeypair)
pub struct RelayIdentityKeypairSpecifier;
#[non_exhaustive]
#[derive(Deftly, PartialEq, Debug, Constructor)]
#[derive_deftly(KeySpecifier)]
#[deftly(prefix = "relay")]
#[deftly(role = "KP_relayid_ed")]
#[deftly(summary = "Public part of the relay long-term identity keypair")]
/// The public part of the long-term identity key of the relay.
pub struct RelayIdentityPublicKeySpecifier;
define_ed25519_keypair!(
/// [KP_relaysign_ed] Medium-term signing keypair. Rotated periodically.
pub RelaySigning
);
#[derive(Deftly, PartialEq, Debug, Constructor)]
#[derive_deftly(KeySpecifier)]
#[deftly(prefix = "relay")]
#[deftly(role = "KS_relaysign_ed")]
#[deftly(summary = "Relay medium-term signing keypair")]
/// The key specifier of the relay medium-term signing key.
pub struct RelaySigningKeypairSpecifier {
/// The expiration time of this key.
///
/// This **must** be the same as the expiration timestamp from the
/// `K_relaysign_ed` certificate of this key.
///
/// This serves as a unique identifier for this key instance,
/// and is used for deciding which `K_relaysign_ed` key to use
/// (we use the newest key that is not yet expired according to
/// the `valid_until` timestamp from its specifier).
///
/// **Important**: this timestamp should not be used for anything other than
/// distinguishing between different signing keypair instances.
/// In particular, it should **not** be used for validating the keypair,
/// or for checking its timeliness.
#[deftly(denotator)]
pub(crate) valid_until: Timestamp,
}
/// The approximate time when a [`RelaySigningKeypairSpecifier`] was generated.
///
/// Used as a denotator to distinguish between the different signing keypair instances
/// that might be stored in the keystore.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] //
#[derive(Into, From)]
pub struct Timestamp(Iso8601TimeSlug);
impl From<SystemTime> for Timestamp {
fn from(t: SystemTime) -> Self {
Self(t.into())
}
}
impl KeySpecifierComponent for Timestamp {
fn to_slug(&self) -> Result<Slug, Bug> {
self.0.try_into()
}
fn from_slug(s: &Slug) -> Result<Self, InvalidKeyPathComponentValue>
where
Self: Sized,
{
use std::str::FromStr as _;
let timestamp = Iso8601TimeSlug::from_str(s.as_ref())
.map_err(|e| InvalidKeyPathComponentValue::Slug(e.to_string()))?;
Ok(Self(timestamp))
}
fn fmt_pretty(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
define_ed25519_keypair!(
/// [KP_link_ed] Short-term signing keypair for link authentication. Rotated frequently.
pub RelayLinkSigning
);
#[cfg(test)]
mod test {
// @@ begin test lint list maintained by maint/add_warning @@
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_duration_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
//! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
use super::*;
use tor_keymgr::test_utils::check_key_specifier;
#[test]
fn relay_signing_key_specifiers() {
let ts = SystemTime::UNIX_EPOCH;
let key_spec = RelaySigningKeypairSpecifier::new(ts.into());
assert_eq!(
key_spec.arti_path().unwrap().as_str(),
"relay/ks_relaysign_ed+19700101000000"
);
check_key_specifier(&key_spec, "relay/ks_relaysign_ed+19700101000000");
}
#[test]
fn relay_identity_key_specifiers() {
let key_spec = RelayIdentityKeypairSpecifier::new();
assert_eq!(
key_spec.arti_path().unwrap().as_str(),
"relay/ks_relayid_ed"
);
check_key_specifier(&key_spec, "relay/ks_relayid_ed");
let key_spec = RelayIdentityPublicKeySpecifier::new();
assert_eq!(
key_spec.arti_path().unwrap().as_str(),
"relay/kp_relayid_ed"
);
check_key_specifier(&key_spec, "relay/kp_relayid_ed");
}
}
|