Merge branch 'release/1.2' into main

This commit is contained in:
Isis Lovecruft 2021-09-14 23:53:15 +00:00
commit 53bb1a3989
No known key found for this signature in database
GPG key ID: AB41313533E8E812
5 changed files with 121 additions and 13 deletions

View file

@ -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`.

View file

@ -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"]

View file

@ -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

View file

@ -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://img.shields.io/crates/v/x25519-dalek.svg)](https://crates.io/crates/x25519-dalek) [![](https://docs.rs/x25519-dalek/badge.svg)](https://docs.rs/x25519-dalek) [![](https://travis-ci.org/dalek-cryptography/x25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/x25519-dalek)
//!
@ -124,7 +124,7 @@
//!
//! ```toml
//! [dependencies]
//! x25519-dalek = "1.1"
//! x25519-dalek = "1"
//! ```
//!
//! # MSRV

View file

@ -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.