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

            
3
use derive_deftly::define_derive_deftly;
4

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

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

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

            
81
    ${define KP_NAME $( $fname )}
82
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
83

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

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

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

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

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

            
137
    impl $crate::macro_deps::ed25519::Ed25519SigningKey for $ttype {
138
2
        fn sign(
139
2
            &self,
140
2
            msg: &[u8])
141
2
        -> $crate::macro_deps::ed25519::Signature {
142
            self.0.sign(msg)
143
        }
144
    }
145

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
340
/// Create an RSA keypair wrapper given a visibility and a struct name.
341
///
342
/// # Syntax:
343
/// ```rust,ignore
344
/// define_rsa_keypair(<visibility> <prefix>)
345
/// ```
346
///
347
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
348
/// cryptographic keypair for an RSA keypair. It derives the deftly RsaKeypair template
349
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
350
///
351
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
352
///
353
/// # Example:
354
///
355
/// ```rust
356
/// use tor_key_forge::define_rsa_keypair;
357
///
358
/// define_rsa_keypair!(NonPublicSigning);
359
/// define_rsa_keypair!(pub PublicSigning);
360
/// define_rsa_keypair!(pub(crate) CratePublicSigning);
361
/// ```
362
///
363
/// The above results in `NonPublicSigningKeypair` and `NonPublicSigningPublicKey` struct being
364
/// created and usable with a series of useful methods. Same for the other defines.
365
///
366
/// You can then use these objects like so:
367
///
368
/// ```rust
369
/// # use tor_llcrypto::rng::FakeEntropicRng;
370
/// # let mut rng = FakeEntropicRng(rand::rng());
371
/// use rand::Rng;
372
/// use tor_key_forge::Keygen;
373
/// use tor_key_forge::define_rsa_keypair;
374
/// use tor_llcrypto::pk::ValidatableSignature;
375
/// use tor_llcrypto::pk::rsa::KeyPair;
376
///
377
/// define_rsa_keypair!(
378
///     /// Our signing key.
379
///     MyRsa
380
/// );
381
///
382
/// let signing_kp = MyRsaKeypair::generate(&mut rng).expect("Invalid keygen");
383
/// let signing_pubkey = signing_kp.public();
384
/// // Lets sign this wonderful message.
385
/// let message = "Workers want rights, not your opinion".as_bytes();
386
/// let sig = signing_kp.sign(&message).expect("Error signing message");
387
///
388
/// // You can then verify either directly with the keypair or the public key.
389
/// assert!(signing_kp.verify(&sig, &message));
390
/// assert!(signing_pubkey.verify(&sig, &message));
391
/// ```
392
#[macro_export]
393
macro_rules! define_rsa_keypair {
394
    ($(#[ $docs_and_attrs:meta ])*
395
     $vis:vis $base_name:ident) => {
396
        $crate::macro_deps::paste! {
397
            #[derive($crate::derive_deftly::Deftly)]
398
            #[derive_deftly($crate::macro_deps::RsaKeypair)]
399
            #[deftly(kp(pubkey = $base_name "PublicKey"))]
400
            #[non_exhaustive]
401
            $(#[ $docs_and_attrs ])*
402
            $vis struct [<$base_name "Keypair">]($crate::macro_deps::rsa::KeyPair);
403
        }
404
    };
405
}
406

            
407
define_derive_deftly! {
408
    /// Implement set of helper functions around a type wrapping a rsa::KeyPair.
409
    export RsaKeypair for struct:
410

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

            
416
    ${define KP_NAME $( $fname )}
417
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
418

            
419
    /// Public key component of this keypair. Useful if we move the public key around,
420
    /// it then keeps it semantic with the name and less prone to errors.
421
    #[derive(Clone, Debug, PartialEq, Eq)]
422
    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
423
    #[non_exhaustive]
424
    $tvis struct $PK_NAME ($tvis $crate::macro_deps::rsa::PublicKey);
425

            
426
    impl $PK_NAME {
427
        /// Verify the signature of a given message.
428
        #[allow(unused)]
429
        $tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
430
            use $crate::macro_deps::ValidatableSignature;
431
            $crate::macro_deps::rsa::ValidatableRsaSignature::new(&self.0, sig, text).is_valid()
432
        }
433
    }
434

            
435
    // We don't expect all implementations to use all code.
436
    #[allow(unused)]
437
    impl $ttype {
438
        /// Build the raw inner public key into the wrapper public key object.
439
2
        $tvis fn public(&self) -> $PK_NAME {
440
            $PK_NAME((&self.$KP_NAME).into())
441
        }
442

            
443
        /// Reference to the internal keypair.
444
        $tvis fn keypair(&self) -> &$crate::macro_deps::rsa::KeyPair {
445
            &self.0
446
        }
447

            
448
        /// Sign the given message.
449
2
        $tvis fn sign(&self, message: &[u8]) -> Result<Vec<u8>, $crate::macro_deps::rsa::Error> {
450
            self.0.sign(message)
451
        }
452

            
453
        /// Verify the signature of a given message.
454
4
        $tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
455
            use $crate::macro_deps::ValidatableSignature;
456
            $crate::macro_deps::rsa::ValidatableRsaSignature::new(
457
                &self.0.to_public_key(), sig, text
458
            ).is_valid()
459
        }
460

            
461
        /// Return a RsaIdentity built from this keypair.
462
        $tvis fn to_rsa_identity(&self) -> $crate::macro_deps::rsa::RsaIdentity {
463
            self.public().0.to_rsa_identity()
464
        }
465
    }
466

            
467
    impl From<$crate::macro_deps::rsa::KeyPair> for $ttype {
468
        fn from(kp: $crate::macro_deps::rsa::KeyPair) -> Self {
469
            Self(kp)
470
        }
471
    }
472

            
473
    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
474
    /// in a keystore.
475

            
476
    impl $crate::ItemType for $ttype {
477
        fn item_type() -> $crate::KeystoreItemType {
478
            $crate::KeyType::RsaKeypair.into()
479
        }
480
    }
481

            
482
    impl $crate::EncodableItem for $ttype {
483
        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
484
            self.$KP_NAME.as_keystore_item()
485
        }
486
    }
487

            
488
    impl $crate::ToEncodableKey for $ttype {
489
        type Key = $crate::macro_deps::rsa::KeyPair;
490
        type KeyPair = $ttype;
491

            
492
        fn to_encodable_key(self) -> Self::Key {
493
            self.$KP_NAME
494
        }
495
        fn from_encodable_key(key: Self::Key) -> Self {
496
            Self(key)
497
        }
498
    }
499

            
500
    impl $crate::Keygen for $ttype {
501
2
        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
502
2
        where
503
2
            Self: Sized
504
        {
505
            Ok(Self { $KP_NAME: $crate::macro_deps::rsa::KeyPair::generate(&mut rng)? })
506
        }
507
    }
508
}
509

            
510
// Re-export dependencies as `tor_key_forge::macro_deps` that we use to make this macro work.
511
#[doc(hidden)]
512
pub mod deps {
513
    pub use derive_deftly_template_Curve25519Keypair;
514
    pub use derive_deftly_template_Ed25519Keypair;
515
    pub use derive_deftly_template_RsaKeypair;
516
    pub use derive_more;
517
    pub use paste::paste;
518
    pub use signature;
519
    pub use tor_llcrypto::pk::{ValidatableSignature, curve25519, ed25519, rsa};
520
}
521

            
522
#[cfg(test)]
523
mod test {
524
    use crate::Keygen;
525
    use tor_basic_utils::test_rng::testing_rng;
526
    use tor_llcrypto::{pk::ed25519::Ed25519SigningKey, rng::FakeEntropicRng};
527

            
528
    #[test]
529
    fn deftly_ed25519_keypair() {
530
        define_ed25519_keypair!(SomeEd25519);
531

            
532
        let mut rng = FakeEntropicRng(testing_rng());
533
        let kp = SomeEd25519Keypair::generate(&mut rng).expect("Failed to gen key");
534

            
535
        // Make sure the generated public key from our wrapper is the same as the
536
        // underlying keypair.
537
        let pubkey = kp.public();
538
        assert_eq!(pubkey.0, kp.0.verifying_key());
539

            
540
        // Message to sign and verify.
541
        let msg: [u8; 4] = [2, 3, 4, 5];
542
        let msg_bad: [u8; 4] = [2, 3, 4, 6];
543

            
544
        let sig = kp.sign(msg.as_slice());
545
        assert!(kp.verify(sig, msg.as_slice()));
546
        // Lets make sure we don't validate another message.
547
        assert!(!kp.verify(sig, msg_bad.as_slice()));
548
    }
549

            
550
    #[test]
551
    fn deftly_rsa_keypair() {
552
        define_rsa_keypair!(SomeRsa);
553

            
554
        let mut rng = FakeEntropicRng(testing_rng());
555
        let kp = SomeRsaKeypair::generate(&mut rng).expect("Failed to gen key");
556

            
557
        // Make sure the generated public key from our wrapper is the same as the
558
        // underlying keypair.
559
        let pubkey = kp.public();
560
        assert_eq!(pubkey.0, kp.0.to_public_key());
561

            
562
        // Message to sign and verify.
563
        let msg: [u8; 4] = [2, 3, 4, 5];
564
        let msg_bad: [u8; 4] = [2, 3, 4, 6];
565

            
566
        let sig = kp.sign(msg.as_slice()).expect("Failed to sign message.");
567
        assert!(kp.verify(&sig, msg.as_slice()));
568
        // Lets make sure we don't validate another message.
569
        assert!(!kp.verify(&sig, msg_bad.as_slice()));
570
    }
571
}