Lines
52.63 %
Functions
5.43 %
Branches
100 %
//! Macros that can be used to improve your life with regards to crypto.
use derive_deftly::define_derive_deftly;
// NOTE: We will require a define_rsa_keypair for the future so the relay legacy RSA keys can be
// declared.
/// Create an ed25519 keypair wrapper given a visibility and a struct name.
///
/// # Syntax:
/// ```rust,ignore
/// define_ed25519_keypair(<visibility> <prefix>)
/// ```
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
/// cryptographic keypair for an ed25519 keypair. It derives the deftly Ed25519Keypair template
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
/// # Example:
/// ```rust
/// use tor_key_forge::define_ed25519_keypair;
/// define_ed25519_keypair!(NonPublicSigning);
/// define_ed25519_keypair!(pub PublicSigning);
/// define_ed25519_keypair!(pub(crate) CratePublicSigning);
/// The above results in `NonPublicSigningKeypair` and `NonPublicSigningPublicKey` struct being
/// created and usable with a series of useful methods. Same for the other defines.
/// You can then use these objects like so:
/// use rand::Rng;
/// use tor_key_forge::Keygen;
/// use tor_llcrypto::pk::ValidatableSignature;
/// use tor_llcrypto::pk::ed25519::Signer;
/// define_ed25519_keypair!(
/// /// Our signing key.
/// MySigning
/// );
/// let mut rng = rand::thread_rng();
/// let signing_kp = MySigningKeypair::generate(&mut rng).expect("Invalid keygen");
/// let signing_pubkey = signing_kp.public();
/// // Lets sign this wonderful message.
/// let message = "Workers want rights, not your opinion".as_bytes();
/// let sig = signing_kp.sign(&message);
/// // You can then verify either directly with the keypair or the public key.
/// assert!(signing_kp.verify(sig, &message));
/// assert!(signing_pubkey.verify(sig, &message));
#[macro_export]
macro_rules! define_ed25519_keypair {
($(#[ $docs_and_attrs:meta ])*
$vis:vis $base_name:ident) => {
$crate::macro_deps::paste! {
#[derive($crate::derive_deftly::Deftly)]
#[derive_deftly($crate::macro_deps::Ed25519Keypair)]
#[deftly(kp(pubkey = $base_name "PublicKey"))]
#[non_exhaustive]
$(#[ $docs_and_attrs ])*
$vis struct [<$base_name "Keypair">]($crate::macro_deps::ed25519::Keypair);
}
};
define_derive_deftly! {
/// Implement set of helper functions around a type wrapping an ed25519::Keypair.
export Ed25519Keypair for struct:
// Enforce that the object has a single field. We want to avoid the implementer to start
// storing metadata or other things in this object that is meant specifically to be
// a semantic wrapper around an Ed25519 keypair.
${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
${define KP_NAME $( $fname )}
${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
/// Public key component of this keypair. Useful if we move the public key around,
/// it then keeps it semantic with the name and less prone to errors.
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
$tvis struct $PK_NAME ($tvis $crate::macro_deps::ed25519::PublicKey);
impl $PK_NAME {
/// Verify the signature of a given message.
#[allow(unused)]
$tvis fn verify(&self, sig: $crate::macro_deps::ed25519::Signature, text: &[u8]) -> bool {
use $crate::macro_deps::ValidatableSignature;
$crate::macro_deps::ed25519::ValidatableEd25519Signature::new(self.0, sig, text).is_valid()
impl $crate::macro_deps::ed25519::Ed25519PublicKey for $PK_NAME {
fn public_key(&self) -> &$crate::macro_deps::ed25519::PublicKey {
&self.0
// We don't expect all implementations to use all code.
impl $ttype {
/// Build the raw inner public key into the wrapper public key object.
$tvis fn public(&self) -> $PK_NAME {
$PK_NAME((&self.$KP_NAME).into())
$crate::macro_deps::ed25519::ValidatableEd25519Signature::new(
self.0.verifying_key(), sig, text
).is_valid()
/// Return a Ed25519Identity built from this keypair.
$tvis fn to_ed25519_id(&self) -> $crate::macro_deps::ed25519::Ed25519Identity {
$crate::macro_deps::ed25519::Ed25519Identity::from(&self.public().0)
impl From<$crate::macro_deps::ed25519::Keypair> for $ttype {
fn from(kp: $crate::macro_deps::ed25519::Keypair) -> Self {
Self(kp)
impl $crate::macro_deps::ed25519::Ed25519PublicKey for $ttype {
self.0.as_ref()
impl $crate::macro_deps::ed25519::Signer<$crate::macro_deps::ed25519::Signature> for $ttype {
fn try_sign(
&self,
msg: &[u8])
-> Result<$crate::macro_deps::ed25519::Signature, $crate::macro_deps::signature::Error> {
self.0.try_sign(msg)
/// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
/// in a keystore.
impl $crate::ItemType for $ttype {
fn item_type() -> $crate::KeystoreItemType {
$crate::KeyType::Ed25519Keypair.into()
impl $crate::EncodableItem for $ttype {
fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
self.$KP_NAME.as_keystore_item()
impl $crate::ToEncodableKey for $ttype {
type Key = $crate::macro_deps::ed25519::Keypair;
type KeyPair = $ttype;
fn to_encodable_key(self) -> Self::Key {
self.$KP_NAME
fn from_encodable_key(key: Self::Key) -> Self {
Self(key)
impl $crate::Keygen for $ttype {
fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
where
Self: Sized
{
Ok(Self { $KP_NAME: $crate::macro_deps::ed25519::Keypair::generate(&mut rng) })
/// Create a curve25519 keypair wrapper given a visibility and a struct name.
/// define_curve25519_keypair(<visibility> <prefix>)
/// cryptographic keypair for a curve25519 keypair. It derives the deftly Curve25519Keypair template
/// use tor_key_forge::define_curve25519_keypair;
/// define_curve25519_keypair!(NonPublicEnc);
/// define_curve25519_keypair!(pub PublicEnc);
/// define_curve25519_keypair!(pub(crate) CratePublicEnc);
/// The above results in `NonPublicEncKeypair` and `NonPublicEncPublicKey` struct being created and
/// usable with a series of useful methods.
/// define_curve25519_keypair!(
/// // This is Alice's keypair.
/// AliceEnc
/// define_curve25519_keypair!(BobEnc);
/// let alice_kp = AliceEncKeypair::generate(&mut rng).expect("Failed alice keygen");
/// let bob_kp = BobEncKeypair::generate(&mut rng).expect("Failed bob keygen");
/// // Using the public key wrapper
/// let alice_shared_secret = alice_kp.diffie_hellman(bob_kp.public());
/// // Using the direct curve25519::PublicKey.
/// let bob_shared_secret = bob_kp.diffie_hellman(&alice_kp.public().0);
/// assert_eq!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes());
macro_rules! define_curve25519_keypair {
#[derive_deftly($crate::macro_deps::Curve25519Keypair)]
$vis struct [<$base_name "Keypair">]($crate::macro_deps::curve25519::StaticKeypair);
export Curve25519Keypair for struct:
// a semantic wrapper around an Curve25519 keypair.
$tvis struct $PK_NAME ($crate::macro_deps::curve25519::PublicKey);
impl std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey> for $PK_NAME {
#[inline]
fn borrow(&self) -> &$crate::macro_deps::curve25519::PublicKey {
$PK_NAME(self.$KP_NAME.public.clone())
/// Wrapper around the diffie_hellman() function of the underlying type. This is pretty fun
/// because it accepts both the PK_NAME wrapper or the raw inner curve25519::PublicKey.
$tvis fn diffie_hellman<T>(&self, pk: T) -> $crate::macro_deps::curve25519::SharedSecret
T: std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey>
self.$KP_NAME.secret.diffie_hellman(pk.borrow())
impl From<$crate::macro_deps::curve25519::StaticKeypair> for $ttype {
fn from(kp: $crate::macro_deps::curve25519::StaticKeypair) -> Self {
$crate::KeyType::X25519StaticKeypair.into()
type Key = $crate::macro_deps::curve25519::StaticKeypair;
let secret = $crate::macro_deps::curve25519::StaticSecret::random_from_rng(rng);
let public: $crate::macro_deps::curve25519::PublicKey = (&secret).into();
let kp = $crate::macro_deps::curve25519::StaticKeypair {
secret: secret.into(),
public: public.into(),
Ok(kp.into())
// Re-export dependencies as `tor_key_forge::macro_deps` that we use to make this macro work.
#[doc(hidden)]
pub mod deps {
pub use derive_deftly_template_Curve25519Keypair;
pub use derive_deftly_template_Ed25519Keypair;
pub use derive_more;
pub use paste::paste;
pub use signature;
pub use tor_llcrypto::pk::{curve25519, ed25519, ValidatableSignature};
#[cfg(test)]
mod test {
use crate::Keygen;
use tor_basic_utils::test_rng::testing_rng;
use tor_llcrypto::pk::ed25519::Signer;
#[test]
fn deftly_ed25519_keypair() {
define_ed25519_keypair!(SomeEd25519);
let mut rng = testing_rng();
let kp = SomeEd25519Keypair::generate(&mut rng).expect("Failed to gen key");
// Make sure the generated public key from our wrapper is the same as the
// underlying keypair.
let pubkey = kp.public();
assert_eq!(pubkey.0, kp.0.verifying_key());
// Message to sign and verify.
let msg: [u8; 4] = [2, 3, 4, 5];
let msg_bad: [u8; 4] = [2, 3, 4, 6];
let sig = kp.sign(msg.as_slice());
assert!(kp.verify(sig, msg.as_slice()));
// Lets make sure we don't validate another message.
assert!(!kp.verify(sig, msg_bad.as_slice()));