Skip to content

Commit

Permalink
Merge pull request dalek-cryptography#71 from isislovecruft/feature/n…
Browse files Browse the repository at this point in the history
…oise-secrets

Implement reused secret keys for Noise/X3DH/etc protocols
  • Loading branch information
isislovecruft authored Sep 14, 2021
2 parents 254e43d + eef4de4 commit b6f7de1
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 9 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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"]
Expand Down
64 changes: 56 additions & 8 deletions src/x25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,69 @@ 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
/// [`StaticSecret::diffie_hellman`] method does not consume the secret key, and the type provides
/// 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",
Expand Down

0 comments on commit b6f7de1

Please sign in to comment.