1
//! Macros that can be used to improve your life with regards to crypto.
2

            
3
use derive_deftly::define_derive_deftly;
4

            
5
// NOTE: We will require a define_rsa_keypair for the future so the relay legacy RSA keys can be
6
// declared.
7

            
8
/// Create an ed25519 keypair wrapper given a visibility and a struct name.
9
///
10
/// # Syntax:
11
/// ```rust,ignore
12
/// define_ed25519_keypair(<visibility> <prefix>)
13
/// ```
14
///
15
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
16
/// cryptographic keypair for an ed25519 keypair. It derives the deftly Ed25519Keypair template
17
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
18
///
19
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
20
///
21
/// # Example:
22
///
23
/// ```rust
24
/// use tor_key_forge::define_ed25519_keypair;
25
///
26
/// define_ed25519_keypair!(NonPublicSigning);
27
/// define_ed25519_keypair!(pub PublicSigning);
28
/// define_ed25519_keypair!(pub(crate) CratePublicSigning);
29
/// ```
30
///
31
/// The above results in `NonPublicSigningKeypair` and `NonPublicSigningPublicKey` struct being
32
/// created and usable with a series of useful methods. Same for the other defines.
33
///
34
/// You can then use these objects like so:
35
///
36
/// ```rust
37
/// use rand::Rng;
38
/// use tor_key_forge::Keygen;
39
/// use tor_key_forge::define_ed25519_keypair;
40
/// use tor_llcrypto::pk::ValidatableSignature;
41
/// use tor_llcrypto::pk::ed25519::Signer;
42
///
43
/// define_ed25519_keypair!(
44
///     /// Our signing key.
45
///     MySigning
46
/// );
47
///
48
/// let mut rng = rand::thread_rng();
49
/// let signing_kp = MySigningKeypair::generate(&mut rng).expect("Invalid keygen");
50
/// let signing_pubkey = signing_kp.public();
51
/// // Lets sign this wonderful message.
52
/// let message = "Workers want rights, not your opinion".as_bytes();
53
/// let sig = signing_kp.sign(&message);
54
///
55
/// // You can then verify either directly with the keypair or the public key.
56
/// assert!(signing_kp.verify(sig, &message));
57
/// assert!(signing_pubkey.verify(sig, &message));
58
/// ```
59
#[macro_export]
60
macro_rules! define_ed25519_keypair {
61
    ($(#[ $docs_and_attrs:meta ])*
62
     $vis:vis $base_name:ident) => {
63
        $crate::macro_deps::paste! {
64
            #[derive($crate::derive_deftly::Deftly)]
65
            #[derive_deftly($crate::macro_deps::Ed25519Keypair)]
66
            #[deftly(kp(pubkey = $base_name "PublicKey"))]
67
            #[non_exhaustive]
68
            $(#[ $docs_and_attrs ])*
69
            $vis struct [<$base_name "Keypair">]($crate::macro_deps::ed25519::Keypair);
70
        }
71
    };
72
}
73

            
74
define_derive_deftly! {
75
    /// Implement set of helper functions around a type wrapping an ed25519::Keypair.
76
    export Ed25519Keypair for struct:
77

            
78
    // Enforce that the object has a single field. We want to avoid the implementer to start
79
    // storing metadata or other things in this object that is meant specifically to be
80
    // a semantic wrapper around an Ed25519 keypair.
81
    ${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
82

            
83
    ${define KP_NAME $( $fname )}
84
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
85

            
86
    /// Public key component of this keypair. Useful if we move the public key around,
87
    /// it then keeps it semantic with the name and less prone to errors.
88
    #[derive(Clone, Debug, PartialEq, Eq)]
89
    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
90
    #[non_exhaustive]
91
    $tvis struct $PK_NAME ($tvis $crate::macro_deps::ed25519::PublicKey);
92

            
93
    impl $PK_NAME {
94
        /// Verify the signature of a given message.
95
        #[allow(unused)]
96
        $tvis fn verify(&self, sig: $crate::macro_deps::ed25519::Signature, text: &[u8]) -> bool {
97
            use $crate::macro_deps::ValidatableSignature;
98
            $crate::macro_deps::ed25519::ValidatableEd25519Signature::new(self.0, sig, text).is_valid()
99
        }
100
    }
101

            
102
    impl $crate::macro_deps::ed25519::Ed25519PublicKey for $PK_NAME {
103
        fn public_key(&self) -> &$crate::macro_deps::ed25519::PublicKey {
104
            &self.0
105
        }
106
    }
107

            
108
    // We don't expect all implementations to use all code.
109
    #[allow(unused)]
110
    impl $ttype {
111
        /// Build the raw inner public key into the wrapper public key object.
112
2
        $tvis fn public(&self) -> $PK_NAME {
113
            $PK_NAME((&self.$KP_NAME).into())
114
        }
115
        /// Verify the signature of a given message.
116
4
        $tvis fn verify(&self, sig: $crate::macro_deps::ed25519::Signature, text: &[u8]) -> bool {
117
            use $crate::macro_deps::ValidatableSignature;
118
            $crate::macro_deps::ed25519::ValidatableEd25519Signature::new(
119
                self.0.verifying_key(), sig, text
120
            ).is_valid()
121
        }
122
        /// Return a Ed25519Identity built from this keypair.
123
        $tvis fn to_ed25519_id(&self) -> $crate::macro_deps::ed25519::Ed25519Identity {
124
            $crate::macro_deps::ed25519::Ed25519Identity::from(&self.public().0)
125
        }
126
    }
127

            
128
    impl From<$crate::macro_deps::ed25519::Keypair> for $ttype {
129
        fn from(kp: $crate::macro_deps::ed25519::Keypair) -> Self {
130
            Self(kp)
131
        }
132
    }
133
    impl $crate::macro_deps::ed25519::Ed25519PublicKey for $ttype {
134
        fn public_key(&self) -> &$crate::macro_deps::ed25519::PublicKey {
135
            self.0.as_ref()
136
        }
137
    }
138

            
139
    impl $crate::macro_deps::ed25519::Signer<$crate::macro_deps::ed25519::Signature> for $ttype {
140
2
        fn try_sign(
141
2
            &self,
142
2
            msg: &[u8])
143
2
        -> Result<$crate::macro_deps::ed25519::Signature, $crate::macro_deps::signature::Error> {
144
            self.0.try_sign(msg)
145
        }
146
    }
147

            
148
    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
149
    /// in a keystore.
150

            
151
    impl $crate::ItemType for $ttype {
152
        fn item_type() -> $crate::KeystoreItemType {
153
            $crate::KeyType::Ed25519Keypair.into()
154
        }
155
    }
156

            
157
    impl $crate::EncodableItem for $ttype {
158
        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
159
            self.$KP_NAME.as_keystore_item()
160
        }
161
    }
162

            
163
    impl $crate::ToEncodableKey for $ttype {
164
        type Key = $crate::macro_deps::ed25519::Keypair;
165
        type KeyPair = $ttype;
166

            
167
        fn to_encodable_key(self) -> Self::Key {
168
            self.$KP_NAME
169
        }
170
        fn from_encodable_key(key: Self::Key) -> Self {
171
            Self(key)
172
        }
173
    }
174

            
175
    impl $crate::Keygen for $ttype {
176
2
        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
177
2
        where
178
2
            Self: Sized
179
2
        {
180
            Ok(Self { $KP_NAME: $crate::macro_deps::ed25519::Keypair::generate(&mut rng) })
181
        }
182
    }
183
}
184

            
185
/// Create a curve25519 keypair wrapper given a visibility and a struct name.
186
///
187
/// # Syntax:
188
/// ```rust,ignore
189
/// define_curve25519_keypair(<visibility> <prefix>)
190
/// ```
191
///
192
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
193
/// cryptographic keypair for a curve25519 keypair. It derives the deftly Curve25519Keypair template
194
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
195
///
196
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
197
///
198
/// # Example:
199
///
200
/// ```rust
201
/// use tor_key_forge::define_curve25519_keypair;
202
///
203
/// define_curve25519_keypair!(NonPublicEnc);
204
/// define_curve25519_keypair!(pub PublicEnc);
205
/// define_curve25519_keypair!(pub(crate) CratePublicEnc);
206
/// ```
207
///
208
/// The above results in `NonPublicEncKeypair` and `NonPublicEncPublicKey` struct being created and
209
/// usable with a series of useful methods.
210
///
211
/// You can then use these objects like so:
212
///
213
/// ```rust
214
/// use rand::Rng;
215
/// use tor_key_forge::define_curve25519_keypair;
216
/// use tor_key_forge::Keygen;
217
///
218
/// define_curve25519_keypair!(
219
///     // This is Alice's keypair.
220
///     AliceEnc
221
/// );
222
/// define_curve25519_keypair!(BobEnc);
223
///
224
/// let mut rng = rand::thread_rng();
225
/// let alice_kp = AliceEncKeypair::generate(&mut rng).expect("Failed alice keygen");
226
/// let bob_kp = BobEncKeypair::generate(&mut rng).expect("Failed bob keygen");
227
///
228
/// // Using the public key wrapper
229
/// let alice_shared_secret = alice_kp.diffie_hellman(bob_kp.public());
230
/// // Using the direct curve25519::PublicKey.
231
/// let bob_shared_secret = bob_kp.diffie_hellman(&alice_kp.public().0);
232
///
233
/// assert_eq!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes());
234
/// ```
235
#[macro_export]
236
macro_rules! define_curve25519_keypair {
237
    ($(#[ $docs_and_attrs:meta ])*
238
    $vis:vis $base_name:ident) => {
239
        $crate::macro_deps::paste! {
240
            #[derive($crate::derive_deftly::Deftly)]
241
            #[derive_deftly($crate::macro_deps::Curve25519Keypair)]
242
            #[deftly(kp(pubkey = $base_name "PublicKey"))]
243
            #[non_exhaustive]
244
            $(#[ $docs_and_attrs ])*
245
            $vis struct [<$base_name "Keypair">]($crate::macro_deps::curve25519::StaticKeypair);
246
        }
247
    };
248
}
249

            
250
define_derive_deftly! {
251
    /// Implement set of helper functions around a type wrapping an ed25519::Keypair.
252
    export Curve25519Keypair for struct:
253

            
254
    // Enforce that the object has a single field. We want to avoid the implementer to start
255
    // storing metadata or other things in this object that is meant specifically to be
256
    // a semantic wrapper around an Curve25519 keypair.
257
    ${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
258

            
259
    ${define KP_NAME $( $fname )}
260
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
261

            
262
    /// Public key component of this keypair. Useful if we move the public key around,
263
    /// it then keeps it semantic with the name and less prone to errors.
264
    #[derive(Clone, Debug, PartialEq, Eq)]
265
    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
266
    #[non_exhaustive]
267
    $tvis struct $PK_NAME ($crate::macro_deps::curve25519::PublicKey);
268

            
269
    impl std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey> for $PK_NAME {
270
        #[inline]
271
        fn borrow(&self) -> &$crate::macro_deps::curve25519::PublicKey {
272
            &self.0
273
        }
274
    }
275

            
276
    impl $ttype {
277
        /// Build the raw inner public key into the wrapper public key object.
278
        $tvis fn public(&self) -> $PK_NAME {
279
            $PK_NAME(self.$KP_NAME.public.clone())
280
        }
281

            
282
        /// Wrapper around the diffie_hellman() function of the underlying type. This is pretty fun
283
        /// because it accepts both the PK_NAME wrapper or the raw inner curve25519::PublicKey.
284
        $tvis fn diffie_hellman<T>(&self, pk: T) -> $crate::macro_deps::curve25519::SharedSecret
285
        where
286
            T: std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey>
287
        {
288
            self.$KP_NAME.secret.diffie_hellman(pk.borrow())
289
        }
290
    }
291

            
292
    impl From<$crate::macro_deps::curve25519::StaticKeypair> for $ttype {
293
        fn from(kp: $crate::macro_deps::curve25519::StaticKeypair) -> Self {
294
            Self(kp)
295
        }
296
    }
297

            
298
    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
299
    /// in a keystore.
300

            
301
    impl $crate::ItemType for $ttype {
302
        fn item_type() -> $crate::KeystoreItemType {
303
            $crate::KeyType::X25519StaticKeypair.into()
304
        }
305
    }
306

            
307
    impl $crate::EncodableItem for $ttype {
308
        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
309
            self.$KP_NAME.as_keystore_item()
310
        }
311
    }
312

            
313
    impl $crate::ToEncodableKey for $ttype {
314
        type Key = $crate::macro_deps::curve25519::StaticKeypair;
315
        type KeyPair = $ttype;
316

            
317
        fn to_encodable_key(self) -> Self::Key {
318
            self.$KP_NAME
319
        }
320
        fn from_encodable_key(key: Self::Key) -> Self {
321
            Self(key)
322
        }
323
    }
324

            
325
    impl $crate::Keygen for $ttype {
326
        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
327
        where
328
            Self: Sized
329
        {
330
            let secret = $crate::macro_deps::curve25519::StaticSecret::random_from_rng(rng);
331
            let public: $crate::macro_deps::curve25519::PublicKey = (&secret).into();
332
            let kp = $crate::macro_deps::curve25519::StaticKeypair {
333
                secret: secret.into(),
334
                public: public.into(),
335
            };
336
            Ok(kp.into())
337
        }
338
    }
339
}
340

            
341
// Re-export dependencies as `tor_key_forge::macro_deps` that we use to make this macro work.
342
#[doc(hidden)]
343
pub mod deps {
344
    pub use derive_deftly_template_Curve25519Keypair;
345
    pub use derive_deftly_template_Ed25519Keypair;
346
    pub use derive_more;
347
    pub use paste::paste;
348
    pub use signature;
349
    pub use tor_llcrypto::pk::{curve25519, ed25519, ValidatableSignature};
350
}
351

            
352
#[cfg(test)]
353
mod test {
354
    use crate::Keygen;
355
    use tor_basic_utils::test_rng::testing_rng;
356
    use tor_llcrypto::pk::ed25519::Signer;
357

            
358
    #[test]
359
    fn deftly_ed25519_keypair() {
360
        define_ed25519_keypair!(SomeEd25519);
361

            
362
        let mut rng = testing_rng();
363
        let kp = SomeEd25519Keypair::generate(&mut rng).expect("Failed to gen key");
364

            
365
        // Make sure the generated public key from our wrapper is the same as the
366
        // underlying keypair.
367
        let pubkey = kp.public();
368
        assert_eq!(pubkey.0, kp.0.verifying_key());
369

            
370
        // Message to sign and verify.
371
        let msg: [u8; 4] = [2, 3, 4, 5];
372
        let msg_bad: [u8; 4] = [2, 3, 4, 6];
373

            
374
        let sig = kp.sign(msg.as_slice());
375
        assert!(kp.verify(sig, msg.as_slice()));
376
        // Lets make sure we don't validate another message.
377
        assert!(!kp.verify(sig, msg_bad.as_slice()));
378
    }
379
}