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

6
use crate::{Error, Result};
7
use serde::Deserialize;
8
use tor_llcrypto::pk::rsa::RsaIdentity;
9
10
11
use tor_netdoc::doc::authcert::{AuthCert, AuthCertKeyIds};

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

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

47
48
49
50
51
    /// Return true if this authority matches a given key ID.
    pub fn matches_keyid(&self, id: &AuthCertKeyIds) -> bool {
        self.v3ident == id.id_fingerprint
    }
}
52
53
54

/// Return a vector of the default directory authorities.
pub(crate) fn default_authorities() -> Vec<Authority> {
55
    /// Build an authority; panic if input is bad.
56
57
58
59
    fn auth(name: &str, key: &str) -> Authority {
        let v3ident = hex::decode(key).expect("Built-in authority identity had bad hex!?");
        let v3ident = RsaIdentity::from_bytes(&v3ident)
            .expect("Built-in authority identity had wrong length!?");
60
61
62
63
64
        AuthorityBuilder::new()
            .name(name)
            .v3ident(v3ident)
            .build()
            .expect("unable to construct built-in authority!?")
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    }

    // (List generated August 2020.)
    vec![
        auth("bastet", "27102BC123E7AF1D4741AE047E160C91ADC76B21"),
        auth("dannenberg", "0232AF901C31A04EE9848595AF9BB7620D4C5B2E"),
        auth("dizum", "E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58"),
        auth("Faravahar", "EFCBE720AB3A82B99F9E953CD5BF50F7EEFC7B97"),
        auth("gabelmoo", "ED03BB616EB2F60BEC80151114BB25CEF515B226"),
        auth("longclaw", "23D15D965BC35114467363C165C4F724B64B4F66"),
        auth("maatuska", "49015F787433103580E3B66A1707A00E60F2D15B"),
        auth("moria1", "D586D18309DED4CD6D57C18FDB97EFA96D330566"),
        auth("tor26", "14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4"),
    ]
}
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
/// A Builder object for constructing an [`Authority`] entry.
#[derive(Debug, Clone, Default)]
pub struct AuthorityBuilder {
    /// See [`Authority::name`]
    name: Option<String>,
    /// See [`Authority::v3ident`]
    v3ident: Option<RsaIdentity>,
}

impl AuthorityBuilder {
    /// Make a new AuthorityBuilder with no fields set.
    pub fn new() -> Self {
        Self::default()
    }
    /// Set the name on this AuthorityBuilder.
    ///
    /// This field is required.
    pub fn name(&mut self, name: &str) -> &mut Self {
        self.name = Some(name.to_owned());
        self
    }
    /// Set the v3 RSA identity of this AuthorityBuilder.
    ///
    /// This field is required.
    pub fn v3ident(&mut self, key: RsaIdentity) -> &mut Self {
        self.v3ident = Some(key);
        self
    }
    /// Try to build an [`Authority`].
    pub fn build(&self) -> Result<Authority> {
        let name = self
            .name
            .as_ref()
            .ok_or(Error::BadNetworkConfig("Missing authority name"))?
            .clone();
        let v3ident = self
            .v3ident
            .ok_or(Error::BadNetworkConfig("Missing v3 identity key."))?;
        Ok(Authority { name, v3ident })
    }
}

123
124
#[cfg(test)]
mod test {
125
    #![allow(clippy::unwrap_used)]
126
127
128
129
130
    use super::*;
    #[test]
    fn authority() {
        let key1: RsaIdentity = [9_u8; 20].into();
        let key2: RsaIdentity = [10_u8; 20].into();
131
132
133
134
135
        let auth = Authority::builder()
            .name("example")
            .v3ident(key1)
            .build()
            .unwrap();
136
137
138
139

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

        let keyids1 = AuthCertKeyIds {
140
141
            id_fingerprint: key1,
            sk_fingerprint: key2,
142
143
144
145
        };
        assert!(auth.matches_keyid(&keyids1));

        let keyids2 = AuthCertKeyIds {
146
147
            id_fingerprint: key2,
            sk_fingerprint: key2,
148
149
150
151
152
153
154
155
156
157
158
159
160
161
        };
        assert!(!auth.matches_keyid(&keyids2));
    }

    #[test]
    fn auth() {
        let dflt = default_authorities();
        assert_eq!(&dflt[0].name[..], "bastet");
        assert_eq!(
            &dflt[0].v3ident.to_string()[..],
            "$27102bc123e7af1d4741ae047e160c91adc76b21"
        );
    }
}