mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-03 20:13:48 +00:00
Merge pull request #71 from isislovecruft/feature/noise-secrets
Implement reused secret keys for Noise/X3DH/etc protocols
This commit is contained in:
commit
b6f7de1e4c
2 changed files with 58 additions and 9 deletions
|
|
@ -31,7 +31,7 @@ travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
|
|||
|
||||
[package.metadata.docs.rs]
|
||||
#rustdoc-args = ["--html-in-header", ".cargo/registry/src/github.com-1ecc6299db9ec823/curve25519-dalek-1.0.1/docs/assets/rustdoc-include-katex-header.html"]
|
||||
features = ["nightly"]
|
||||
features = ["nightly", "reusable_secrets", "serde"]
|
||||
|
||||
[dependencies]
|
||||
curve25519-dalek = { version = "3", default-features = false }
|
||||
|
|
@ -54,6 +54,7 @@ default = ["std", "u64_backend"]
|
|||
serde = ["our_serde", "curve25519-dalek/serde"]
|
||||
std = ["curve25519-dalek/std"]
|
||||
nightly = ["curve25519-dalek/nightly"]
|
||||
reusable_secrets = []
|
||||
u64_backend = ["curve25519-dalek/u64_backend"]
|
||||
u32_backend = ["curve25519-dalek/u32_backend"]
|
||||
fiat_u64_backend = ["curve25519-dalek/fiat_u64_backend"]
|
||||
|
|
|
|||
|
|
@ -96,6 +96,55 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// implemented to facilitate protocols such as Noise (e.g. Noise IK key usage,
|
||||
/// etc.) and X3DH which require an "ephemeral" key to conduct the
|
||||
/// Diffie-Hellman operation multiple times throughout the protocol, while the
|
||||
/// protocol run at a higher level is only conducted once per key.
|
||||
///
|
||||
/// Similarly to [`EphemeralSecret`], this type does _not_ have serialisation
|
||||
/// methods, in order to discourage long-term usage of secret key material. (For
|
||||
/// long-term secret keys, see [`StaticSecret`].)
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// If you're uncertain about whether you should use this, then you likely
|
||||
/// should not be using this. Our strongly recommended advice is to use
|
||||
/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that
|
||||
/// secret keys are never reused, which can have very serious security
|
||||
/// implications for many protocols.
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
#[derive(Clone, Zeroize)]
|
||||
#[zeroize(drop)]
|
||||
pub struct ReusableSecret(pub(crate) Scalar);
|
||||
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
impl ReusableSecret {
|
||||
/// Perform a Diffie-Hellman key agreement between `self` and
|
||||
/// `their_public` key to produce a [`SharedSecret`].
|
||||
pub fn diffie_hellman(&self, their_public: &PublicKey) -> SharedSecret {
|
||||
SharedSecret(&self.0 * their_public.0)
|
||||
}
|
||||
|
||||
/// Generate a non-serializeable x25519 [`ReuseableSecret`] key.
|
||||
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
let mut bytes = [0u8; 32];
|
||||
|
||||
csprng.fill_bytes(&mut bytes);
|
||||
|
||||
ReusableSecret(clamp_scalar(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "reusable_secrets")]
|
||||
impl<'a> From<&'a ReusableSecret> for PublicKey {
|
||||
/// Given an x25519 [`ReusableSecret`] key, compute its corresponding [`PublicKey`].
|
||||
fn from(secret: &'a ReusableSecret) -> PublicKey {
|
||||
PublicKey((&ED25519_BASEPOINT_TABLE * &secret.0).to_montgomery())
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
|
@ -103,14 +152,13 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey {
|
|||
/// serialization methods to save and load key material. This means that the secret may be used
|
||||
/// multiple times (but does not *have to be*).
|
||||
///
|
||||
/// Some protocols, such as Noise, already handle the static/ephemeral distinction, so the
|
||||
/// additional guarantees provided by [`EphemeralSecret`] are not helpful or would cause duplicate
|
||||
/// code paths. In this case, it may be useful to
|
||||
/// ```rust,ignore
|
||||
/// use x25519_dalek::StaticSecret as SecretKey;
|
||||
/// ```
|
||||
/// since the only difference between the two is that [`StaticSecret`] does not enforce at
|
||||
/// compile-time that the key is only used once.
|
||||
/// # Warning
|
||||
///
|
||||
/// If you're uncertain about whether you should use this, then you likely
|
||||
/// should not be using this. Our strongly recommended advice is to use
|
||||
/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that
|
||||
/// secret keys are never reused, which can have very serious security
|
||||
/// implications for many protocols.
|
||||
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
|
|
|
|||
Loading…
Reference in a new issue