macros.rs
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 $tvis fn public(&self) -> $PK_NAME { 113 $PK_NAME((&self.$KP_NAME).into()) 114 } 115 /// Verify the signature of a given message. 116 $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 fn try_sign( 141 &self, 142 msg: &[u8]) 143 -> 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 fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self> 177 where 178 Self: Sized 179 { 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 }