1
//! Re-exporting Ed25519 implementations, and related utilities.
2
//!
3
//! Here we re-export types from [`ed25519_dalek`] that implement the
4
//! Ed25519 signature algorithm.  (TODO: Eventually, this module
5
//! should probably be replaced with a wrapper that uses the ed25519
6
//! trait and the Signature trait.)
7
//!
8
//! We additionally provide an `Ed25519Identity` type to represent the
9
//! unvalidated Ed25519 "identity keys" that we use throughout the Tor
10
//! protocol to uniquely identify a relay.
11

            
12
use base64ct::{Base64Unpadded, Encoding as _};
13
use curve25519_dalek::Scalar;
14
use sha2::Sha512;
15
use std::fmt::{self, Debug, Display, Formatter};
16
use subtle::{Choice, ConstantTimeEq};
17

            
18
use ed25519_dalek::hazmat::ExpandedSecretKey;
19
// NOTE: We are renaming a few types here to maintain consistency with
20
// our variable names, and with the nomenclature we use elsewhere for public
21
// keys.
22
pub use ed25519_dalek::{
23
    Signature, Signer, SigningKey as Keypair, Verifier, VerifyingKey as PublicKey,
24
};
25

            
26
use crate::util::ct::CtByteArray;
27

            
28
/// The length of an ED25519 identity, in bytes.
29
pub const ED25519_ID_LEN: usize = 32;
30

            
31
/// The length of an ED25519 signature, in bytes.
32
pub const ED25519_SIGNATURE_LEN: usize = 64;
33

            
34
/// A variant of [`Keypair`] containing an [`ExpandedSecretKey`].
35
///
36
/// In the Tor protocol, we use this type for blinded onion service identity keys
37
/// (KS_hs_blind_id).  Since their scalar values are computed, rather than taken
38
/// directly from a
39
/// SHA-512 transformation of a SecretKey, we cannot use the regular `Keypair`
40
/// type.
41
#[allow(clippy::exhaustive_structs)]
42
pub struct ExpandedKeypair {
43
    /// The secret part of the key.
44
    pub(crate) secret: ExpandedSecretKey,
45
    /// The public part of this key.
46
    ///
47
    /// NOTE: As with [`ed25519_dalek::SigningKey`], this public key _must_ be
48
    /// the public key matching `secret`.  Putting a different public key in
49
    /// here would enable a class of attacks against ed25519 and enable secret
50
    /// key recovery.
51
    pub(crate) public: PublicKey,
52
}
53

            
54
impl ExpandedKeypair {
55
    /// Return the public part of this expanded keypair.
56
    pub fn public(&self) -> &PublicKey {
57
        &self.public
58
    }
59

            
60
    // NOTE: There is deliberately no secret() function.  If we had one, we
61
    // would be exposing an unescorted secret key, which is part of
62
    // ed25519::hazmat.
63

            
64
    /// Compute a signature over a message using this keypair.
65
    pub fn sign(&self, message: &[u8]) -> Signature {
66
        // See notes on ExpandedKeypair about why this hazmat is okay to use.
67
        ed25519_dalek::hazmat::raw_sign::<Sha512>(&self.secret, message, &self.public)
68
    }
69

            
70
    /// Return a representation of the secret key in this keypair.
71
    ///
72
    /// (Since it is an expanded secret key, we represent it as its scalar part
73
    /// followed by its hash_prefix.)
74
    pub fn to_secret_key_bytes(&self) -> [u8; 64] {
75
        let mut output = [0_u8; 64];
76
        output[0..32].copy_from_slice(&self.secret.scalar.to_bytes());
77
        output[32..64].copy_from_slice(&self.secret.hash_prefix);
78
        output
79
    }
80

            
81
    /// Reconstruct a key from its byte representation as returned by
82
    /// `to_secret_key_bytes()`.
83
    ///
84
    /// Return None if the input cannot be the output of `to_secret_key_bytes()`.
85
    //
86
    // NOTE: Returning None is a bit silly, but that's what Dalek does.
87
    pub fn from_secret_key_bytes(bytes: [u8; 64]) -> Option<Self> {
88
        let scalar = Option::from(Scalar::from_bytes_mod_order(
89
            bytes[0..32].try_into().expect("wrong length on slice"),
90
        ))?;
91
        let hash_prefix = bytes[32..64].try_into().expect("wrong length on slice");
92
        let secret = ExpandedSecretKey {
93
            scalar,
94
            hash_prefix,
95
        };
96
        let public = PublicKey::from(&secret);
97
        Some(Self { secret, public })
98
    }
99

            
100
    // NOTE: There is deliberately no constructor here that takes a (secret,
101
    // public) pair.  If there were, you could construct a pair with a
102
    // mismatched public key.
103
}
104

            
105
impl<'a> From<&'a Keypair> for ExpandedKeypair {
106
    fn from(kp: &'a Keypair) -> ExpandedKeypair {
107
        ExpandedKeypair {
108
            secret: kp.as_bytes().into(),
109
            public: kp.into(),
110
        }
111
    }
112
}
113

            
114
/// An unchecked, unvalidated Ed25519 key.
115
///
116
/// This key is an "identity" in the sense that it identifies (up to) one
117
/// Ed25519 key.  It may also represent the identity for a particular entity,
118
/// such as a relay or an onion service.
119
///
120
/// This type is distinct from an Ed25519 [`PublicKey`] for several reasons:
121
///  * We're storing it in a compact format, whereas the public key
122
///    implementation might want an expanded form for more efficient key
123
///    validation.
124
///  * This type hasn't checked whether the bytes here actually _are_ a valid
125
///    Ed25519 public key.
126
21927
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)]
127
pub struct Ed25519Identity {
128
    /// A raw unchecked Ed25519 public key.
129
    id: CtByteArray<ED25519_ID_LEN>,
130
}
131

            
132
impl Ed25519Identity {
133
    /// Construct a new Ed25519 identity from a 32-byte sequence.
134
    ///
135
    /// This might or might not actually be a valid Ed25519 public key.
136
    ///
137
    /// ```
138
    /// use tor_llcrypto::pk::ed25519::{Ed25519Identity, PublicKey};
139
    ///
140
    /// let bytes = b"klsadjfkladsfjklsdafkljasdfsdsd!";
141
    /// let id = Ed25519Identity::new(*bytes);
142
    /// let pk: Result<PublicKey,_> = (&id).try_into();
143
    /// assert!(pk.is_ok());
144
    ///
145
    /// let bytes = b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
146
    /// let id = Ed25519Identity::new(*bytes);
147
    /// let pk: Result<PublicKey,_> = (&id).try_into();
148
    /// assert!(pk.is_err());
149
    /// ```
150
4557
    pub fn new(id: [u8; 32]) -> Self {
151
4557
        Ed25519Identity { id: id.into() }
152
4557
    }
153
    /// If `id` is of the correct length, wrap it in an Ed25519Identity.
154
4473
    pub fn from_bytes(id: &[u8]) -> Option<Self> {
155
4473
        Some(Ed25519Identity::new(id.try_into().ok()?))
156
4473
    }
157
    /// Return a reference to the bytes in this key.
158
882
    pub fn as_bytes(&self) -> &[u8] {
159
882
        &self.id.as_ref()[..]
160
882
    }
161
}
162

            
163
impl From<[u8; ED25519_ID_LEN]> for Ed25519Identity {
164
    fn from(id: [u8; ED25519_ID_LEN]) -> Self {
165
        Ed25519Identity::new(id)
166
    }
167
}
168

            
169
impl From<Ed25519Identity> for [u8; ED25519_ID_LEN] {
170
    fn from(value: Ed25519Identity) -> Self {
171
        value.id.into()
172
    }
173
}
174

            
175
impl From<PublicKey> for Ed25519Identity {
176
    fn from(pk: PublicKey) -> Self {
177
        (&pk).into()
178
    }
179
}
180

            
181
impl From<&PublicKey> for Ed25519Identity {
182
    fn from(pk: &PublicKey) -> Self {
183
        // This unwrap is safe because the public key is always 32 bytes
184
        // long.
185
        Ed25519Identity::from_bytes(pk.as_bytes()).expect("Ed25519 public key had wrong length?")
186
    }
187
}
188

            
189
impl TryFrom<&Ed25519Identity> for PublicKey {
190
    type Error = ed25519_dalek::SignatureError;
191
84
    fn try_from(id: &Ed25519Identity) -> Result<PublicKey, Self::Error> {
192
84
        PublicKey::from_bytes(id.id.as_ref())
193
84
    }
194
}
195

            
196
impl TryFrom<Ed25519Identity> for PublicKey {
197
    type Error = ed25519_dalek::SignatureError;
198
84
    fn try_from(id: Ed25519Identity) -> Result<PublicKey, Self::Error> {
199
84
        (&id).try_into()
200
84
    }
201
}
202

            
203
impl ConstantTimeEq for Ed25519Identity {
204
    fn ct_eq(&self, other: &Self) -> Choice {
205
        self.id.ct_eq(&other.id)
206
    }
207
}
208

            
209
impl Display for Ed25519Identity {
210
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
211
        write!(f, "{}", Base64Unpadded::encode_string(self.id.as_ref()))
212
    }
213
}
214

            
215
impl Debug for Ed25519Identity {
216
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
217
        write!(f, "Ed25519Identity {{ {} }}", self)
218
    }
219
}
220

            
221
impl safelog::Redactable for Ed25519Identity {
222
    /// Warning: This displays 12 bits of the ed25519 identity, which is
223
    /// enough to narrow down a public relay by a great deal.
224
    fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225
        write!(
226
            f,
227
            "{}…",
228
            &Base64Unpadded::encode_string(self.id.as_ref())[..2]
229
        )
230
    }
231

            
232
    fn debug_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233
        write!(f, "Ed25519Identity {{ {} }}", self.redacted())
234
    }
235
}
236

            
237
impl serde::Serialize for Ed25519Identity {
238
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
239
    where
240
        S: serde::Serializer,
241
    {
242
        if serializer.is_human_readable() {
243
            serializer.serialize_str(&Base64Unpadded::encode_string(self.id.as_ref()))
244
        } else {
245
            serializer.serialize_bytes(&self.id.as_ref()[..])
246
        }
247
    }
248
}
249

            
250
impl<'de> serde::Deserialize<'de> for Ed25519Identity {
251
21
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
252
21
    where
253
21
        D: serde::Deserializer<'de>,
254
21
    {
255
21
        if deserializer.is_human_readable() {
256
            /// Helper for deserialization
257
            struct EdIdentityVisitor;
258
            impl<'de> serde::de::Visitor<'de> for EdIdentityVisitor {
259
                type Value = Ed25519Identity;
260
                fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> fmt::Result {
261
                    fmt.write_str("base64-encoded Ed25519 public key")
262
                }
263
21
                fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
264
21
                where
265
21
                    E: serde::de::Error,
266
21
                {
267
21
                    let bytes = Base64Unpadded::decode_vec(s).map_err(E::custom)?;
268
21
                    Ed25519Identity::from_bytes(&bytes)
269
21
                        .ok_or_else(|| E::custom("wrong length for Ed25519 public key"))
270
21
                }
271
            }
272

            
273
21
            deserializer.deserialize_str(EdIdentityVisitor)
274
        } else {
275
            /// Helper for deserialization
276
            struct EdIdentityVisitor;
277
            impl<'de> serde::de::Visitor<'de> for EdIdentityVisitor {
278
                type Value = Ed25519Identity;
279
                fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> fmt::Result {
280
                    fmt.write_str("ed25519 public key")
281
                }
282
                fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
283
                where
284
                    E: serde::de::Error,
285
                {
286
                    Ed25519Identity::from_bytes(bytes)
287
                        .ok_or_else(|| E::custom("wrong length for ed25519 public key"))
288
                }
289
            }
290
            deserializer.deserialize_bytes(EdIdentityVisitor)
291
        }
292
21
    }
293
}
294

            
295
/// An ed25519 signature, plus the document that it signs and its
296
/// public key.
297
#[derive(Clone, Debug)]
298
pub struct ValidatableEd25519Signature {
299
    /// The key that allegedly produced the signature
300
    key: PublicKey,
301
    /// The alleged signature
302
    sig: Signature,
303
    /// The entire body of text that is allegedly signed here.
304
    ///
305
    /// TODO: It's not so good to have this included here; it
306
    /// would be better to have a patch to ed25519_dalek to allow
307
    /// us to pre-hash the signed thing, and just store a digest.
308
    /// We can't use that with the 'prehash' variant of ed25519,
309
    /// since that has different constants.
310
    entire_text_of_signed_thing: Vec<u8>,
311
}
312

            
313
impl ValidatableEd25519Signature {
314
    /// Create a new ValidatableEd25519Signature
315
84
    pub fn new(key: PublicKey, sig: Signature, text: &[u8]) -> Self {
316
84
        ValidatableEd25519Signature {
317
84
            key,
318
84
            sig,
319
84
            entire_text_of_signed_thing: text.into(),
320
84
        }
321
84
    }
322

            
323
    /// View the interior of this signature object.
324
84
    pub(crate) fn as_parts(&self) -> (&PublicKey, &Signature, &[u8]) {
325
84
        (&self.key, &self.sig, &self.entire_text_of_signed_thing[..])
326
84
    }
327

            
328
    /// Return a reference to the underlying Signature.
329
    pub fn signature(&self) -> &Signature {
330
        &self.sig
331
    }
332
}
333

            
334
impl super::ValidatableSignature for ValidatableEd25519Signature {
335
    fn is_valid(&self) -> bool {
336
        self.key
337
            .verify(&self.entire_text_of_signed_thing[..], &self.sig)
338
            .is_ok()
339
    }
340

            
341
    fn as_ed25519(&self) -> Option<&ValidatableEd25519Signature> {
342
        Some(self)
343
    }
344
}
345

            
346
/// Perform a batch verification operation on the provided signatures
347
///
348
/// Return `true` if _every_ signature is valid; otherwise return `false`.
349
///
350
/// Note that the mathematics for batch validation are slightly
351
/// different than those for normal one-signature validation.  Because
352
/// of this, it is possible for an ostensible signature that passes
353
/// one validation algorithm might fail the other.  (Well-formed
354
/// signatures generated by a correct Ed25519 implementation will
355
/// always pass both kinds of validation, and an attacker should not
356
/// be able to forge a signature that passes either kind.)
357
105
pub fn validate_batch(sigs: &[&ValidatableEd25519Signature]) -> bool {
358
105
    use crate::pk::ValidatableSignature;
359
105
    if sigs.is_empty() {
360
        // ed25519_dalek has nonzero cost for a batch-verification of
361
        // zero sigs.
362
63
        true
363
42
    } else if sigs.len() == 1 {
364
        // Validating one signature in the traditional way is faster.
365
        sigs[0].is_valid()
366
    } else {
367
42
        let mut ed_msgs = Vec::new();
368
42
        let mut ed_sigs = Vec::new();
369
42
        let mut ed_pks = Vec::new();
370
126
        for ed_sig in sigs {
371
84
            let (pk, sig, msg) = ed_sig.as_parts();
372
84
            ed_sigs.push(*sig);
373
84
            ed_pks.push(*pk);
374
84
            ed_msgs.push(msg);
375
84
        }
376
42
        ed25519_dalek::verify_batch(&ed_msgs[..], &ed_sigs[..], &ed_pks[..]).is_ok()
377
    }
378
105
}
379

            
380
/// An object that has an Ed25519 [`PublicKey`].
381
pub trait Ed25519PublicKey {
382
    /// Get the Ed25519 [`PublicKey`].
383
    fn public_key(&self) -> &PublicKey;
384
}
385

            
386
impl Ed25519PublicKey for Keypair {
387
    fn public_key(&self) -> &PublicKey {
388
        self.as_ref()
389
    }
390
}