Skip to main content

tor_key_forge/
macros.rs

1//! Macros that can be used to improve your life with regards to crypto.
2
3use 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]
58macro_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
72define_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        $tvis fn public(&self) -> $PK_NAME {
111            $PK_NAME((&self.$KP_NAME).into())
112        }
113        /// Verify the signature of a given message.
114        $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        fn sign(
139            &self,
140            msg: &[u8])
141        -> $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        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
175        where
176            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]
235macro_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
249define_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 $PK_NAME {
276        /// Get the inner [`PublicKey`]($crate::macro_deps::curve25519::PublicKey).
277        // This can be nicer to use than
278        // `<FooPublicKey as Borrow<curve25519::PublicKey>>::borrow(&foo)`.
279        #[inline]
280        $tvis fn inner(&self) -> &$crate::macro_deps::curve25519::PublicKey {
281            &self.0
282        }
283    }
284
285    impl $ttype {
286        /// Build the raw inner public key into the wrapper public key object.
287        $tvis fn public(&self) -> $PK_NAME {
288            $PK_NAME(self.$KP_NAME.public.clone())
289        }
290
291        /// The raw inner secret key.
292        ///
293        /// We return it directly without a wrapper type because it's expected that the secret key
294        /// will not be moved around,
295        /// and instead accessed only just before it's needed.
296        $tvis fn secret(&self) -> &$crate::macro_deps::curve25519::StaticSecret {
297            &self.$KP_NAME.secret
298        }
299
300        /// Wrapper around the diffie_hellman() function of the underlying type. This is pretty fun
301        /// because it accepts both the PK_NAME wrapper or the raw inner curve25519::PublicKey.
302        $tvis fn diffie_hellman<T>(&self, pk: T) -> $crate::macro_deps::curve25519::SharedSecret
303        where
304            T: std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey>
305        {
306            self.$KP_NAME.secret.diffie_hellman(pk.borrow())
307        }
308    }
309
310    impl From<$crate::macro_deps::curve25519::StaticKeypair> for $ttype {
311        fn from(kp: $crate::macro_deps::curve25519::StaticKeypair) -> Self {
312            Self(kp)
313        }
314    }
315
316    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
317    /// in a keystore.
318
319    impl $crate::ItemType for $ttype {
320        fn item_type() -> $crate::KeystoreItemType {
321            $crate::KeyType::X25519StaticKeypair.into()
322        }
323    }
324
325    impl $crate::EncodableItem for $ttype {
326        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
327            self.$KP_NAME.as_keystore_item()
328        }
329    }
330
331    impl $crate::ToEncodableKey for $ttype {
332        type Key = $crate::macro_deps::curve25519::StaticKeypair;
333        type KeyPair = $ttype;
334
335        fn to_encodable_key(self) -> Self::Key {
336            self.$KP_NAME
337        }
338        fn from_encodable_key(key: Self::Key) -> Self {
339            Self(key)
340        }
341    }
342
343    impl $crate::Keygen for $ttype {
344        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
345        where
346            Self: Sized
347        {
348            let secret = $crate::macro_deps::curve25519::StaticSecret::random_from_rng(rng);
349            let public: $crate::macro_deps::curve25519::PublicKey = (&secret).into();
350            let kp = $crate::macro_deps::curve25519::StaticKeypair {
351                secret: secret.into(),
352                public: public.into(),
353            };
354            Ok(kp.into())
355        }
356    }
357}
358
359/// Create an RSA keypair wrapper given a visibility and a struct name.
360///
361/// # Syntax:
362/// ```rust,ignore
363/// define_rsa_keypair(<visibility> <prefix>)
364/// ```
365///
366/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
367/// cryptographic keypair for an RSA keypair. It derives the deftly RsaKeypair template
368/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
369///
370/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
371///
372/// # Example:
373///
374/// ```rust
375/// use tor_key_forge::define_rsa_keypair;
376///
377/// define_rsa_keypair!(NonPublicSigning);
378/// define_rsa_keypair!(pub PublicSigning);
379/// define_rsa_keypair!(pub(crate) CratePublicSigning);
380/// ```
381///
382/// The above results in `NonPublicSigningKeypair` and `NonPublicSigningPublicKey` struct being
383/// created and usable with a series of useful methods. Same for the other defines.
384///
385/// You can then use these objects like so:
386///
387/// ```rust
388/// # use tor_llcrypto::rng::FakeEntropicRng;
389/// # let mut rng = FakeEntropicRng(rand::rng());
390/// use rand::Rng;
391/// use tor_key_forge::Keygen;
392/// use tor_key_forge::define_rsa_keypair;
393/// use tor_llcrypto::pk::ValidatableSignature;
394/// use tor_llcrypto::pk::rsa::KeyPair;
395///
396/// define_rsa_keypair!(
397///     /// Our signing key.
398///     MyRsa
399/// );
400///
401/// let signing_kp = MyRsaKeypair::generate(&mut rng).expect("Invalid keygen");
402/// let signing_pubkey = signing_kp.public();
403/// // Lets sign this wonderful message.
404/// let message = "Workers want rights, not your opinion".as_bytes();
405/// let sig = signing_kp.sign(&message).expect("Error signing message");
406///
407/// // You can then verify either directly with the keypair or the public key.
408/// assert!(signing_kp.verify(&sig, &message));
409/// assert!(signing_pubkey.verify(&sig, &message));
410/// ```
411#[macro_export]
412macro_rules! define_rsa_keypair {
413    ($(#[ $docs_and_attrs:meta ])*
414     $vis:vis $base_name:ident) => {
415        $crate::macro_deps::paste! {
416            #[derive($crate::derive_deftly::Deftly)]
417            #[derive_deftly($crate::macro_deps::RsaKeypair)]
418            #[deftly(kp(pubkey = $base_name "PublicKey"))]
419            #[non_exhaustive]
420            $(#[ $docs_and_attrs ])*
421            $vis struct [<$base_name "Keypair">]($crate::macro_deps::rsa::KeyPair);
422        }
423    };
424}
425
426define_derive_deftly! {
427    /// Implement set of helper functions around a type wrapping a rsa::KeyPair.
428    export RsaKeypair for struct:
429
430    // Enforce that the object has a single field. We want to avoid the implementer to start
431    // storing metadata or other things in this object that is meant specifically to be
432    // a semantic wrapper around an RSA keypair.
433    ${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
434
435    ${define KP_NAME $( $fname )}
436    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
437
438    /// Public key component of this keypair. Useful if we move the public key around,
439    /// it then keeps it semantic with the name and less prone to errors.
440    #[derive(Clone, Debug, PartialEq, Eq)]
441    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
442    #[non_exhaustive]
443    $tvis struct $PK_NAME ($tvis $crate::macro_deps::rsa::PublicKey);
444
445    impl $PK_NAME {
446        /// Verify the signature of a given message.
447        #[allow(unused)]
448        $tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
449            use $crate::macro_deps::ValidatableSignature;
450            $crate::macro_deps::rsa::ValidatableRsaSignature::new(&self.0, sig, text).is_valid()
451        }
452    }
453
454    // We don't expect all implementations to use all code.
455    #[allow(unused)]
456    impl $ttype {
457        /// Build the raw inner public key into the wrapper public key object.
458        $tvis fn public(&self) -> $PK_NAME {
459            $PK_NAME((&self.$KP_NAME).into())
460        }
461
462        /// Reference to the internal keypair.
463        $tvis fn keypair(&self) -> &$crate::macro_deps::rsa::KeyPair {
464            &self.0
465        }
466
467        /// Sign the given message.
468        $tvis fn sign(&self, message: &[u8]) -> Result<Vec<u8>, $crate::macro_deps::rsa::Error> {
469            self.0.sign(message)
470        }
471
472        /// Verify the signature of a given message.
473        $tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
474            use $crate::macro_deps::ValidatableSignature;
475            $crate::macro_deps::rsa::ValidatableRsaSignature::new(
476                &self.0.to_public_key(), sig, text
477            ).is_valid()
478        }
479
480        /// Return a RsaIdentity built from this keypair.
481        $tvis fn to_rsa_identity(&self) -> $crate::macro_deps::rsa::RsaIdentity {
482            self.public().0.to_rsa_identity()
483        }
484    }
485
486    impl From<$crate::macro_deps::rsa::KeyPair> for $ttype {
487        fn from(kp: $crate::macro_deps::rsa::KeyPair) -> Self {
488            Self(kp)
489        }
490    }
491
492    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
493    /// in a keystore.
494
495    impl $crate::ItemType for $ttype {
496        fn item_type() -> $crate::KeystoreItemType {
497            $crate::KeyType::RsaKeypair.into()
498        }
499    }
500
501    impl $crate::EncodableItem for $ttype {
502        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
503            self.$KP_NAME.as_keystore_item()
504        }
505    }
506
507    impl $crate::ToEncodableKey for $ttype {
508        type Key = $crate::macro_deps::rsa::KeyPair;
509        type KeyPair = $ttype;
510
511        fn to_encodable_key(self) -> Self::Key {
512            self.$KP_NAME
513        }
514        fn from_encodable_key(key: Self::Key) -> Self {
515            Self(key)
516        }
517    }
518
519    impl $crate::Keygen for $ttype {
520        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
521        where
522            Self: Sized
523        {
524            Ok(Self { $KP_NAME: $crate::macro_deps::rsa::KeyPair::generate(&mut rng)? })
525        }
526    }
527}
528
529// Re-export dependencies as `tor_key_forge::macro_deps` that we use to make this macro work.
530#[doc(hidden)]
531pub mod deps {
532    pub use derive_deftly_template_Curve25519Keypair;
533    pub use derive_deftly_template_Ed25519Keypair;
534    pub use derive_deftly_template_RsaKeypair;
535    pub use derive_more;
536    pub use paste::paste;
537    pub use signature;
538    pub use tor_llcrypto::pk::{ValidatableSignature, curve25519, ed25519, rsa};
539}
540
541#[cfg(test)]
542mod test {
543    use crate::Keygen;
544    use tor_basic_utils::test_rng::testing_rng;
545    use tor_llcrypto::{pk::ed25519::Ed25519SigningKey, rng::FakeEntropicRng};
546
547    #[test]
548    fn deftly_ed25519_keypair() {
549        define_ed25519_keypair!(SomeEd25519);
550
551        let mut rng = FakeEntropicRng(testing_rng());
552        let kp = SomeEd25519Keypair::generate(&mut rng).expect("Failed to gen key");
553
554        // Make sure the generated public key from our wrapper is the same as the
555        // underlying keypair.
556        let pubkey = kp.public();
557        assert_eq!(pubkey.0, kp.0.verifying_key());
558
559        // Message to sign and verify.
560        let msg: [u8; 4] = [2, 3, 4, 5];
561        let msg_bad: [u8; 4] = [2, 3, 4, 6];
562
563        let sig = kp.sign(msg.as_slice());
564        assert!(kp.verify(sig, msg.as_slice()));
565        // Lets make sure we don't validate another message.
566        assert!(!kp.verify(sig, msg_bad.as_slice()));
567    }
568
569    #[test]
570    fn deftly_rsa_keypair() {
571        define_rsa_keypair!(SomeRsa);
572
573        let mut rng = FakeEntropicRng(testing_rng());
574        let kp = SomeRsaKeypair::generate(&mut rng).expect("Failed to gen key");
575
576        // Make sure the generated public key from our wrapper is the same as the
577        // underlying keypair.
578        let pubkey = kp.public();
579        assert_eq!(pubkey.0, kp.0.to_public_key());
580
581        // Message to sign and verify.
582        let msg: [u8; 4] = [2, 3, 4, 5];
583        let msg_bad: [u8; 4] = [2, 3, 4, 6];
584
585        let sig = kp.sign(msg.as_slice()).expect("Failed to sign message.");
586        assert!(kp.verify(&sig, msg.as_slice()));
587        // Lets make sure we don't validate another message.
588        assert!(!kp.verify(&sig, msg_bad.as_slice()));
589    }
590}