1
//! Information about directory authorities
2
//!
3
//! From a client's point of view, an authority's role is to to sign the
4
//! consensus directory.
5

            
6
use derive_builder::Builder;
7
use serde::Deserialize;
8
use tor_llcrypto::pk::rsa::RsaIdentity;
9
use tor_netdoc::doc::authcert::{AuthCert, AuthCertKeyIds};
10

            
11
/// A single authority that signs a consensus directory.
12
//
13
// Note that we do *not* set serde(deny_unknown_fields)] on this structure:
14
// we want our authorities format to be future-proof against adding new info
15
// about each authority.
16
1143
#[derive(Deserialize, Debug, Clone, Builder, Eq, PartialEq)]
17
#[builder(derive(Deserialize))]
18
pub struct Authority {
19
    /// A memorable nickname for this authority.
20
    #[builder(setter(into))]
21
    name: String,
22
    /// A SHA1 digest of the DER-encoded long-term v3 RSA identity key for
23
    /// this authority.
24
    // TODO: It would be lovely to use a better hash for these identities.
25
    v3ident: RsaIdentity,
26
}
27

            
28
impl Authority {
29
    /// Return a new builder for constructing an [`Authority`].
30
    ///
31
    /// You only need this if you're using a non-default Tor network
32
    /// with its own set of directory authorities.
33
35
    pub fn builder() -> AuthorityBuilder {
34
35
        AuthorityBuilder::default()
35
35
    }
36
    /// Return the (human-readable) name for this authority.
37
    pub fn name(&self) -> &str {
38
        self.name.as_ref()
39
    }
40
    /// Return the v3 identity key of this certificate.
41
    ///
42
    /// This is the identity of the >=2048-bit RSA key that the
43
    /// authority uses to sign documents; it is distinct from its
44
    /// identity keys that it uses when operating as a relay.
45
22
    pub fn v3ident(&self) -> &RsaIdentity {
46
22
        &self.v3ident
47
22
    }
48
    /// Return true if this authority matches a given certificate.
49
    pub fn matches_cert(&self, cert: &AuthCert) -> bool {
50
        &self.v3ident == cert.id_fingerprint()
51
    }
52

            
53
    /// Return true if this authority matches a given key ID.
54
2
    pub fn matches_keyid(&self, id: &AuthCertKeyIds) -> bool {
55
2
        self.v3ident == id.id_fingerprint
56
2
    }
57
}
58

            
59
/// Return a vector of the default directory authorities.
60
123
pub(crate) fn default_authorities() -> Vec<Authority> {
61
123
    /// Build an authority; panic if input is bad.
62
1106
    fn auth(name: &str, key: &str) -> Authority {
63
1106
        let v3ident =
64
1106
            RsaIdentity::from_hex(key).expect("Built-in authority identity had bad hex!?");
65
1106
        AuthorityBuilder::new()
66
1106
            .name(name)
67
1106
            .v3ident(v3ident)
68
1106
            .build()
69
1106
            .expect("unable to construct built-in authority!?")
70
1106
    }
71
123

            
72
123
    // (List generated August 2020.)
73
123
    vec![
74
123
        auth("bastet", "27102BC123E7AF1D4741AE047E160C91ADC76B21"),
75
123
        auth("dannenberg", "0232AF901C31A04EE9848595AF9BB7620D4C5B2E"),
76
123
        auth("dizum", "E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58"),
77
123
        auth("Faravahar", "EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97"),
78
123
        auth("gabelmoo", "ED03BB616EB2F60BEC80151114BB25CEF515B226"),
79
123
        auth("longclaw", "23D15D965BC35114467363C165C4F724B64B4F66"),
80
123
        auth("maatuska", "49015F787433103580E3B66A1707A00E60F2D15B"),
81
123
        auth("moria1", "D586D18309DED4CD6D57C18FDB97EFA96D330566"),
82
123
        auth("tor26", "14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4"),
83
123
    ]
84
123
}
85

            
86
impl AuthorityBuilder {
87
    /// Make a new AuthorityBuilder with no fields set.
88
1107
    pub fn new() -> Self {
89
1107
        Self::default()
90
1107
    }
91
}
92

            
93
#[cfg(test)]
94
mod test {
95
    #![allow(clippy::unwrap_used)]
96
    use super::*;
97
    #[test]
98
    fn authority() {
99
        let key1: RsaIdentity = [9_u8; 20].into();
100
        let key2: RsaIdentity = [10_u8; 20].into();
101
        let auth = Authority::builder()
102
            .name("example")
103
            .v3ident(key1)
104
            .build()
105
            .unwrap();
106

            
107
        assert_eq!(auth.v3ident(), &key1);
108

            
109
        let keyids1 = AuthCertKeyIds {
110
            id_fingerprint: key1,
111
            sk_fingerprint: key2,
112
        };
113
        assert!(auth.matches_keyid(&keyids1));
114

            
115
        let keyids2 = AuthCertKeyIds {
116
            id_fingerprint: key2,
117
            sk_fingerprint: key2,
118
        };
119
        assert!(!auth.matches_keyid(&keyids2));
120
    }
121

            
122
    #[test]
123
    fn auth() {
124
        let dflt = default_authorities();
125
        assert_eq!(&dflt[0].name[..], "bastet");
126
        assert_eq!(
127
            &dflt[0].v3ident.to_string()[..],
128
            "$27102bc123e7af1d4741ae047e160c91adc76b21"
129
        );
130
    }
131
}