mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-04 20:24:10 +00:00
Merge branch 'release/1.2' into main
This commit is contained in:
commit
53bb1a3989
5 changed files with 121 additions and 13 deletions
20
CHANGELOG.md
20
CHANGELOG.md
|
|
@ -2,6 +2,24 @@
|
|||
|
||||
Entries are listed in reverse chronological order.
|
||||
|
||||
# 1.x Series
|
||||
|
||||
## 1.2
|
||||
|
||||
* Add module documentation for using the bytes-oriented `x25519()` API.
|
||||
* Add implementation of `zeroize::Zeroize` for `PublicKey`.
|
||||
* Move unittests to a separate directory.
|
||||
* Add cargo feature flags `"fiat_u32_backend"` and `"fiat_u64_backend"` for
|
||||
activating the Fiat crypto field element implementations.
|
||||
* Fix issue with removed `feature(external_doc)` on nightly compilers.
|
||||
* Pin `zeroize` to version 1.3 to support a wider range of MSRVs.
|
||||
* Add CI via Github actions.
|
||||
* Fix breakage in the serde unittests.
|
||||
* MSRV is now 1.41 for production and 1.48 for development.
|
||||
* Add an optional check to `SharedSecret` for contibutory behaviour.
|
||||
* Add implementation of `ReusableSecret` keys which are non-ephemeral, but which
|
||||
cannot be serialised to discourage long-term use.
|
||||
|
||||
## 1.1.1
|
||||
|
||||
* Fix a typo in the README.
|
||||
|
|
@ -23,6 +41,8 @@ Entries are listed in reverse chronological order.
|
|||
* Remove mention of deprecated `rand_os` crate from examples.
|
||||
* Clarify `EphemeralSecret`/`StaticSecret` distinction in documentation.
|
||||
|
||||
# Pre-1.0.0
|
||||
|
||||
## 0.6.0
|
||||
|
||||
* Updates `rand_core` version to `0.5`.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ edition = "2018"
|
|||
# - update html_root_url
|
||||
# - update CHANGELOG
|
||||
# - if any changes were made to README.md, mirror them in src/lib.rs docs
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
authors = [
|
||||
"Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||
"DebugSteven <debugsteven@gmail.com>",
|
||||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ To install, add the following to your project's `Cargo.toml`:
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
x25519-dalek = "1.1"
|
||||
x25519-dalek = "1"
|
||||
```
|
||||
|
||||
# MSRV
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#![cfg_attr(feature = "bench", feature(test))]
|
||||
#![cfg_attr(feature = "nightly", deny(missing_docs))]
|
||||
#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/x25519-dalek/1.1.1")]
|
||||
#![doc(html_root_url = "https://docs.rs/x25519-dalek/1.2.0")]
|
||||
|
||||
//! # x25519-dalek [](https://crates.io/crates/x25519-dalek) [](https://docs.rs/x25519-dalek) [](https://travis-ci.org/dalek-cryptography/x25519-dalek)
|
||||
//!
|
||||
|
|
@ -124,7 +124,7 @@
|
|||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! x25519-dalek = "1.1"
|
||||
//! x25519-dalek = "1"
|
||||
//! ```
|
||||
//!
|
||||
//! # MSRV
|
||||
|
|
|
|||
103
src/x25519.rs
103
src/x25519.rs
|
|
@ -17,6 +17,7 @@
|
|||
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use curve25519_dalek::traits::IsIdentity;
|
||||
|
||||
use rand_core::CryptoRng;
|
||||
use rand_core::RngCore;
|
||||
|
|
@ -95,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
|
||||
|
|
@ -102,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",
|
||||
|
|
@ -177,6 +226,44 @@ impl SharedSecret {
|
|||
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
|
||||
/// Ensure in constant-time that this shared secret did not result from a
|
||||
/// key exchange with non-contributory behaviour.
|
||||
///
|
||||
/// In some more exotic protocols which need to guarantee "contributory"
|
||||
/// behaviour for both parties, that is, that each party contibuted a public
|
||||
/// value which increased the security of the resulting shared secret.
|
||||
/// To take an example protocol attack where this could lead to undesireable
|
||||
/// results [from Thái "thaidn" Dương](https://vnhacker.blogspot.com/2015/09/why-not-validating-curve25519-public.html):
|
||||
///
|
||||
/// > If Mallory replaces Alice's and Bob's public keys with zero, which is
|
||||
/// > a valid Curve25519 public key, he would be able to force the ECDH
|
||||
/// > shared value to be zero, which is the encoding of the point at infinity,
|
||||
/// > and thus get to dictate some publicly known values as the shared
|
||||
/// > keys. It still requires an active man-in-the-middle attack to pull the
|
||||
/// > trick, after which, however, not only Mallory can decode Alice's data,
|
||||
/// > but everyone too! It is also impossible for Alice and Bob to detect the
|
||||
/// > intrusion, as they still share the same keys, and can communicate with
|
||||
/// > each other as normal.
|
||||
///
|
||||
/// The original Curve25519 specification argues that checks for
|
||||
/// non-contributory behaviour are "unnecessary for Diffie-Hellman".
|
||||
/// Whether this check is necessary for any particular given protocol is
|
||||
/// often a matter of debate, which we will not re-hash here, but simply
|
||||
/// cite some of the [relevant] [public] [discussions].
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns `true` if the key exchange was contributory (good), and `false`
|
||||
/// otherwise (can be bad for some protocols).
|
||||
///
|
||||
/// [relevant]: https://tools.ietf.org/html/rfc7748#page-15
|
||||
/// [public]: https://vnhacker.blogspot.com/2015/09/why-not-validating-curve25519-public.html
|
||||
/// [discussions]: https://vnhacker.blogspot.com/2016/08/the-internet-of-broken-protocols.html
|
||||
#[must_use]
|
||||
pub fn was_contributory(&self) -> bool {
|
||||
!self.0.is_identity()
|
||||
}
|
||||
}
|
||||
|
||||
/// "Decode" a scalar from a 32-byte array.
|
||||
|
|
|
|||
Loading…
Reference in a new issue