use derive_deftly::define_derive_deftly;
#[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! {
export Ed25519Keypair for struct:
${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
${define KP_NAME $( $fname )}
${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
#[non_exhaustive]
$tvis struct $PK_NAME ($tvis $crate::macro_deps::ed25519::PublicKey);
impl $PK_NAME {
#[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
}
}
#[allow(unused)]
impl $ttype {
$tvis fn public(&self) -> $PK_NAME {
$PK_NAME((&self.$KP_NAME).into())
}
$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.verifying_key(), sig, text
).is_valid()
}
$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 {
fn public_key(&self) -> $crate::macro_deps::ed25519::PublicKey {
self.0.public_key()
}
}
impl $crate::macro_deps::ed25519::Ed25519SigningKey for $ttype {
fn sign(
&self,
msg: &[u8])
-> $crate::macro_deps::ed25519::Signature {
self.0.sign(msg)
}
}
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) })
}
}
}
#[macro_export]
macro_rules! define_curve25519_keypair {
($(#[ $docs_and_attrs:meta ])*
$vis:vis $base_name:ident) => {
$crate::macro_deps::paste! {
#[derive($crate::derive_deftly::Deftly)]
#[derive_deftly($crate::macro_deps::Curve25519Keypair)]
#[deftly(kp(pubkey = $base_name "PublicKey"))]
#[non_exhaustive]
$(#[ $docs_and_attrs ])*
$vis struct [<$base_name "Keypair">]($crate::macro_deps::curve25519::StaticKeypair);
}
};
}
define_derive_deftly! {
export Curve25519Keypair for struct:
${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
${define KP_NAME $( $fname )}
${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
#[non_exhaustive]
$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 {
&self.0
}
}
impl $ttype {
$tvis fn public(&self) -> $PK_NAME {
$PK_NAME(self.$KP_NAME.public.clone())
}
$tvis fn diffie_hellman<T>(&self, pk: T) -> $crate::macro_deps::curve25519::SharedSecret
where
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 {
Self(kp)
}
}
impl $crate::ItemType for $ttype {
fn item_type() -> $crate::KeystoreItemType {
$crate::KeyType::X25519StaticKeypair.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::curve25519::StaticKeypair;
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
{
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())
}
}
}
#[macro_export]
macro_rules! define_rsa_keypair {
($(#[ $docs_and_attrs:meta ])*
$vis:vis $base_name:ident) => {
$crate::macro_deps::paste! {
#[derive($crate::derive_deftly::Deftly)]
#[derive_deftly($crate::macro_deps::RsaKeypair)]
#[deftly(kp(pubkey = $base_name "PublicKey"))]
#[non_exhaustive]
$(#[ $docs_and_attrs ])*
$vis struct [<$base_name "Keypair">]($crate::macro_deps::rsa::KeyPair);
}
};
}
define_derive_deftly! {
export RsaKeypair for struct:
${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
${define KP_NAME $( $fname )}
${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
#[non_exhaustive]
$tvis struct $PK_NAME ($tvis $crate::macro_deps::rsa::PublicKey);
impl $PK_NAME {
#[allow(unused)]
$tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
use $crate::macro_deps::ValidatableSignature;
$crate::macro_deps::rsa::ValidatableRsaSignature::new(&self.0, sig, text).is_valid()
}
}
#[allow(unused)]
impl $ttype {
$tvis fn public(&self) -> $PK_NAME {
$PK_NAME((&self.$KP_NAME).into())
}
$tvis fn keypair(&self) -> &$crate::macro_deps::rsa::KeyPair {
&self.0
}
$tvis fn sign(&self, message: &[u8]) -> Result<Vec<u8>, $crate::macro_deps::rsa::Error> {
self.0.sign(message)
}
$tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
use $crate::macro_deps::ValidatableSignature;
$crate::macro_deps::rsa::ValidatableRsaSignature::new(
&self.0.to_public_key(), sig, text
).is_valid()
}
$tvis fn to_rsa_identity(&self) -> $crate::macro_deps::rsa::RsaIdentity {
self.public().0.to_rsa_identity()
}
}
impl From<$crate::macro_deps::rsa::KeyPair> for $ttype {
fn from(kp: $crate::macro_deps::rsa::KeyPair) -> Self {
Self(kp)
}
}
impl $crate::ItemType for $ttype {
fn item_type() -> $crate::KeystoreItemType {
$crate::KeyType::RsaKeypair.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::rsa::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::rsa::KeyPair::generate(&mut rng)? })
}
}
}
#[doc(hidden)]
pub mod deps {
pub use derive_deftly_template_Curve25519Keypair;
pub use derive_deftly_template_Ed25519Keypair;
pub use derive_deftly_template_RsaKeypair;
pub use derive_more;
pub use paste::paste;
pub use signature;
pub use tor_llcrypto::pk::{ValidatableSignature, curve25519, ed25519, rsa};
}
#[cfg(test)]
mod test {
use crate::Keygen;
use tor_basic_utils::test_rng::testing_rng;
use tor_llcrypto::{pk::ed25519::Ed25519SigningKey, rng::FakeEntropicRng};
#[test]
fn deftly_ed25519_keypair() {
define_ed25519_keypair!(SomeEd25519);
let mut rng = FakeEntropicRng(testing_rng());
let kp = SomeEd25519Keypair::generate(&mut rng).expect("Failed to gen key");
let pubkey = kp.public();
assert_eq!(pubkey.0, kp.0.verifying_key());
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()));
assert!(!kp.verify(sig, msg_bad.as_slice()));
}
#[test]
fn deftly_rsa_keypair() {
define_rsa_keypair!(SomeRsa);
let mut rng = FakeEntropicRng(testing_rng());
let kp = SomeRsaKeypair::generate(&mut rng).expect("Failed to gen key");
let pubkey = kp.public();
assert_eq!(pubkey.0, kp.0.to_public_key());
let msg: [u8; 4] = [2, 3, 4, 5];
let msg_bad: [u8; 4] = [2, 3, 4, 6];
let sig = kp.sign(msg.as_slice()).expect("Failed to sign message.");
assert!(kp.verify(&sig, msg.as_slice()));
assert!(!kp.verify(&sig, msg_bad.as_slice()));
}
}