mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-07 20:50:39 +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.
|
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
|
## 1.1.1
|
||||||
|
|
||||||
* Fix a typo in the README.
|
* 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.
|
* Remove mention of deprecated `rand_os` crate from examples.
|
||||||
* Clarify `EphemeralSecret`/`StaticSecret` distinction in documentation.
|
* Clarify `EphemeralSecret`/`StaticSecret` distinction in documentation.
|
||||||
|
|
||||||
|
# Pre-1.0.0
|
||||||
|
|
||||||
## 0.6.0
|
## 0.6.0
|
||||||
|
|
||||||
* Updates `rand_core` version to `0.5`.
|
* Updates `rand_core` version to `0.5`.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||||
# - update html_root_url
|
# - update html_root_url
|
||||||
# - update CHANGELOG
|
# - update CHANGELOG
|
||||||
# - if any changes were made to README.md, mirror them in src/lib.rs docs
|
# - if any changes were made to README.md, mirror them in src/lib.rs docs
|
||||||
version = "1.1.1"
|
version = "1.2.0"
|
||||||
authors = [
|
authors = [
|
||||||
"Isis Lovecruft <isis@patternsinthevoid.net>",
|
"Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||||
"DebugSteven <debugsteven@gmail.com>",
|
"DebugSteven <debugsteven@gmail.com>",
|
||||||
|
|
@ -31,7 +31,7 @@ travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[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"]
|
#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]
|
[dependencies]
|
||||||
curve25519-dalek = { version = "3", default-features = false }
|
curve25519-dalek = { version = "3", default-features = false }
|
||||||
|
|
@ -54,6 +54,7 @@ default = ["std", "u64_backend"]
|
||||||
serde = ["our_serde", "curve25519-dalek/serde"]
|
serde = ["our_serde", "curve25519-dalek/serde"]
|
||||||
std = ["curve25519-dalek/std"]
|
std = ["curve25519-dalek/std"]
|
||||||
nightly = ["curve25519-dalek/nightly"]
|
nightly = ["curve25519-dalek/nightly"]
|
||||||
|
reusable_secrets = []
|
||||||
u64_backend = ["curve25519-dalek/u64_backend"]
|
u64_backend = ["curve25519-dalek/u64_backend"]
|
||||||
u32_backend = ["curve25519-dalek/u32_backend"]
|
u32_backend = ["curve25519-dalek/u32_backend"]
|
||||||
fiat_u64_backend = ["curve25519-dalek/fiat_u64_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
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
x25519-dalek = "1.1"
|
x25519-dalek = "1"
|
||||||
```
|
```
|
||||||
|
|
||||||
# MSRV
|
# MSRV
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
#![cfg_attr(feature = "bench", feature(test))]
|
#![cfg_attr(feature = "bench", feature(test))]
|
||||||
#![cfg_attr(feature = "nightly", deny(missing_docs))]
|
#![cfg_attr(feature = "nightly", deny(missing_docs))]
|
||||||
#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")]
|
#![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)
|
//! # 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
|
//! ```toml
|
||||||
//! [dependencies]
|
//! [dependencies]
|
||||||
//! x25519-dalek = "1.1"
|
//! x25519-dalek = "1"
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # MSRV
|
//! # MSRV
|
||||||
|
|
|
||||||
103
src/x25519.rs
103
src/x25519.rs
|
|
@ -17,6 +17,7 @@
|
||||||
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
|
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
|
||||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use curve25519_dalek::traits::IsIdentity;
|
||||||
|
|
||||||
use rand_core::CryptoRng;
|
use rand_core::CryptoRng;
|
||||||
use rand_core::RngCore;
|
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.
|
/// 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
|
||||||
|
|
@ -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
|
/// serialization methods to save and load key material. This means that the secret may be used
|
||||||
/// multiple times (but does not *have to be*).
|
/// multiple times (but does not *have to be*).
|
||||||
///
|
///
|
||||||
/// Some protocols, such as Noise, already handle the static/ephemeral distinction, so the
|
/// # Warning
|
||||||
/// additional guarantees provided by [`EphemeralSecret`] are not helpful or would cause duplicate
|
///
|
||||||
/// code paths. In this case, it may be useful to
|
/// If you're uncertain about whether you should use this, then you likely
|
||||||
/// ```rust,ignore
|
/// should not be using this. Our strongly recommended advice is to use
|
||||||
/// use x25519_dalek::StaticSecret as SecretKey;
|
/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that
|
||||||
/// ```
|
/// secret keys are never reused, which can have very serious security
|
||||||
/// since the only difference between the two is that [`StaticSecret`] does not enforce at
|
/// implications for many protocols.
|
||||||
/// compile-time that the key is only used once.
|
|
||||||
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
|
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde",
|
feature = "serde",
|
||||||
|
|
@ -177,6 +226,44 @@ impl SharedSecret {
|
||||||
pub fn as_bytes(&self) -> &[u8; 32] {
|
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||||
self.0.as_bytes()
|
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.
|
/// "Decode" a scalar from a 32-byte array.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue