mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-10 21:21:13 +00:00
x25519: use manual impls instead of zeroize_derive (#776)
The types involved are all simple 1-tuple newtypes where zeroization only involves calling `zeroize` on the inner type, making all of the involved impls relatively trivial. Avoiding custom derive arguably improves auditability as you don't need to expand a proc macro to see the resulting code. It decreases the number of required dependencies in order for the `zeroize` feature to work, where some of those dependencies are incredibly heavy (particularly `syn`).
This commit is contained in:
parent
25a9dbb811
commit
37d3ae99d3
2 changed files with 78 additions and 6 deletions
|
|
@ -41,7 +41,7 @@ features = ["getrandom", "reusable_secrets", "serde", "static_secrets"]
|
||||||
curve25519-dalek = { version = "4", path = "../curve25519-dalek", default-features = false }
|
curve25519-dalek = { version = "4", path = "../curve25519-dalek", default-features = false }
|
||||||
rand_core = { version = "0.6", default-features = false }
|
rand_core = { version = "0.6", default-features = false }
|
||||||
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
|
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
|
||||||
zeroize = { version = "1", default-features = false, optional = true, features = ["zeroize_derive"] }
|
zeroize = { version = "1", default-features = false, optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
/// (in this crate) does *not* automatically happen, but either must be derived
|
/// (in this crate) does *not* automatically happen, but either must be derived
|
||||||
/// for Drop or explicitly called.
|
/// for Drop or explicitly called.
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
|
||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
||||||
pub struct PublicKey(pub(crate) MontgomeryPoint);
|
pub struct PublicKey(pub(crate) MontgomeryPoint);
|
||||||
|
|
||||||
|
|
@ -62,6 +61,13 @@ impl AsRef<[u8]> for PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
impl Zeroize for PublicKey {
|
||||||
|
fn zeroize(&mut self) {
|
||||||
|
self.0.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A short-lived Diffie-Hellman secret key that can only be used to compute a single
|
/// A short-lived Diffie-Hellman secret key that can only be used to compute a single
|
||||||
/// [`SharedSecret`].
|
/// [`SharedSecret`].
|
||||||
///
|
///
|
||||||
|
|
@ -70,7 +76,6 @@ impl AsRef<[u8]> for PublicKey {
|
||||||
/// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be
|
/// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be
|
||||||
/// generated from fresh randomness where the compiler statically checks that the resulting
|
/// generated from fresh randomness where the compiler statically checks that the resulting
|
||||||
/// secret is used at most once.
|
/// secret is used at most once.
|
||||||
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
|
|
||||||
pub struct EphemeralSecret(pub(crate) [u8; 32]);
|
pub struct EphemeralSecret(pub(crate) [u8; 32]);
|
||||||
|
|
||||||
impl EphemeralSecret {
|
impl EphemeralSecret {
|
||||||
|
|
@ -111,6 +116,23 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for EphemeralSecret {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
self.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
impl Zeroize for EphemeralSecret {
|
||||||
|
fn zeroize(&mut self) {
|
||||||
|
self.0.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
impl ZeroizeOnDrop for EphemeralSecret {}
|
||||||
|
|
||||||
/// A Diffie-Hellman secret key which may be used more than once, but is
|
/// A Diffie-Hellman secret key which may be used more than once, but is
|
||||||
/// purposefully not serialiseable in order to discourage key-reuse. This is
|
/// purposefully not serialiseable in order to discourage key-reuse. This is
|
||||||
/// implemented to facilitate protocols such as Noise (e.g. Noise IK key usage,
|
/// implemented to facilitate protocols such as Noise (e.g. Noise IK key usage,
|
||||||
|
|
@ -130,7 +152,6 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey {
|
||||||
/// secret keys are never reused, which can have very serious security
|
/// secret keys are never reused, which can have very serious security
|
||||||
/// implications for many protocols.
|
/// implications for many protocols.
|
||||||
#[cfg(feature = "reusable_secrets")]
|
#[cfg(feature = "reusable_secrets")]
|
||||||
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ReusableSecret(pub(crate) [u8; 32]);
|
pub struct ReusableSecret(pub(crate) [u8; 32]);
|
||||||
|
|
||||||
|
|
@ -174,6 +195,24 @@ impl<'a> From<&'a ReusableSecret> for PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "reusable_secrets")]
|
||||||
|
impl Drop for ReusableSecret {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
self.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "reusable_secrets", feature = "zeroize"))]
|
||||||
|
impl Zeroize for ReusableSecret {
|
||||||
|
fn zeroize(&mut self) {
|
||||||
|
self.0.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "reusable_secrets", feature = "zeroize"))]
|
||||||
|
impl ZeroizeOnDrop for ReusableSecret {}
|
||||||
|
|
||||||
/// A Diffie-Hellman secret key that can be used to compute multiple [`SharedSecret`]s.
|
/// A Diffie-Hellman secret key that can be used to compute multiple [`SharedSecret`]s.
|
||||||
///
|
///
|
||||||
/// This type is identical to the [`EphemeralSecret`] type, except that the
|
/// This type is identical to the [`EphemeralSecret`] type, except that the
|
||||||
|
|
@ -190,7 +229,6 @@ impl<'a> From<&'a ReusableSecret> for PublicKey {
|
||||||
/// implications for many protocols.
|
/// implications for many protocols.
|
||||||
#[cfg(feature = "static_secrets")]
|
#[cfg(feature = "static_secrets")]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct StaticSecret([u8; 32]);
|
pub struct StaticSecret([u8; 32]);
|
||||||
|
|
||||||
|
|
@ -263,11 +301,28 @@ impl AsRef<[u8]> for StaticSecret {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "static_secrets")]
|
||||||
|
impl Drop for StaticSecret {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
self.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "static_secrets", feature = "zeroize"))]
|
||||||
|
impl Zeroize for StaticSecret {
|
||||||
|
fn zeroize(&mut self) {
|
||||||
|
self.0.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "static_secrets", feature = "zeroize"))]
|
||||||
|
impl ZeroizeOnDrop for StaticSecret {}
|
||||||
|
|
||||||
/// The result of a Diffie-Hellman key exchange.
|
/// The result of a Diffie-Hellman key exchange.
|
||||||
///
|
///
|
||||||
/// Each party computes this using their [`EphemeralSecret`] or [`StaticSecret`] and their
|
/// Each party computes this using their [`EphemeralSecret`] or [`StaticSecret`] and their
|
||||||
/// counterparty's [`PublicKey`].
|
/// counterparty's [`PublicKey`].
|
||||||
#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
|
|
||||||
pub struct SharedSecret(pub(crate) MontgomeryPoint);
|
pub struct SharedSecret(pub(crate) MontgomeryPoint);
|
||||||
|
|
||||||
impl SharedSecret {
|
impl SharedSecret {
|
||||||
|
|
@ -330,6 +385,23 @@ impl AsRef<[u8]> for SharedSecret {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for SharedSecret {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
self.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
impl Zeroize for SharedSecret {
|
||||||
|
fn zeroize(&mut self) {
|
||||||
|
self.0.zeroize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
|
impl ZeroizeOnDrop for SharedSecret {}
|
||||||
|
|
||||||
/// The bare, byte-oriented x25519 function, exactly as specified in RFC7748.
|
/// The bare, byte-oriented x25519 function, exactly as specified in RFC7748.
|
||||||
///
|
///
|
||||||
/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who
|
/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue