Merge pull request #95 from dignifiedquire/update-deps

Updates curve25519-dalek dep to use 4.0.0-rc.0
This includes several feature flag updates and some
minor API changes.
This commit is contained in:
Michael Rosenberg 2023-01-29 04:35:12 -05:00 committed by GitHub
commit e9fe4145fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 125 deletions

View file

@ -2,9 +2,9 @@ name: Rust
on:
push:
branches: [ '*' ]
branches: [ '**' ]
pull_request:
branches: [ main, develop, release ]
branches: [ '**' ]
env:
CARGO_TERM_COLOR: always

View file

@ -4,6 +4,8 @@ Entries are listed in reverse chronological order.
# 2.x Series
* Update MSRV to 1.60.
## 2.0.0-pre.1
* Loosen restriction on zeroize dependency version from =1.3 to 1.

View file

@ -1,6 +1,6 @@
[package]
name = "x25519-dalek"
edition = "2018"
edition = "2021"
# Before changing this:
# - update version in README.md
# - update html_root_url
@ -25,6 +25,7 @@ exclude = [
".travis.yml",
"CONTRIBUTING.md",
]
rust-version = "1.60"
[badges]
travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
@ -34,12 +35,10 @@ travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
features = ["nightly", "reusable_secrets", "serde"]
[dependencies]
curve25519-dalek = { version = "3", default-features = false }
rand_core = { version = "0.6", default-features = false }
# `serde` is renamed to `our_serde` in order to avoid a name collision between
# importing the serde dependency and enabling the curve25519-dalek/serde feature
our_serde = { package = "serde", version = "1", default-features = false, optional = true, features = ["derive"] }
zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] }
curve25519-dalek = { version = "4.0.0-rc.0", default-features = false }
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
zeroize = { version = "1", default-features = false, optional = true, features = ["zeroize_derive"] }
[dev-dependencies]
bincode = "1"
@ -50,12 +49,9 @@ name = "x25519"
harness = false
[features]
default = ["std", "u64_backend"]
serde = ["our_serde", "curve25519-dalek/serde"]
std = ["curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly"]
default = ["alloc", "precomputed-tables", "zeroize"]
zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"]
serde = ["dep:serde", "curve25519-dalek/serde"]
alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"]
precomputed-tables = ["curve25519-dalek/precomputed-tables"]
reusable_secrets = []
u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]
fiat_u64_backend = ["curve25519-dalek/fiat_u64_backend"]
fiat_u32_backend = ["curve25519-dalek/fiat_u32_backend"]

View file

@ -107,7 +107,7 @@ x25519-dalek = "2.0.0-pre.0"
# MSRV
Current MSRV is 1.51.
Current MSRV is 1.60.
# Documentation

View file

@ -11,13 +11,7 @@
//! Benchmark the Diffie-Hellman operation.
#[macro_use]
extern crate criterion;
extern crate curve25519_dalek;
extern crate rand_core;
extern crate x25519_dalek;
use criterion::Criterion;
use criterion::{criterion_group, criterion_main, Criterion};
use rand_core::OsRng;
@ -25,12 +19,12 @@ use x25519_dalek::EphemeralSecret;
use x25519_dalek::PublicKey;
fn bench_diffie_hellman(c: &mut Criterion) {
let bob_secret = EphemeralSecret::new(&mut OsRng);
let bob_secret = EphemeralSecret::new(OsRng);
let bob_public = PublicKey::from(&bob_secret);
c.bench_function("diffie_hellman", move |b| {
b.iter_with_setup(
|| EphemeralSecret::new(&mut OsRng),
|| EphemeralSecret::new(OsRng),
|alice_secret| alice_secret.diffie_hellman(&bob_public),
)
});

View file

@ -129,7 +129,7 @@
//!
//! # MSRV
//!
//! Current MSRV is 1.41 for production builds, and 1.48 for running tests.
//! Current MSRV is 1.60.
//!
//! # Documentation
//!
@ -155,12 +155,6 @@
//!
//! [crypto_box]: https://github.com/RustCrypto/AEADs/tree/master/crypto_box
extern crate curve25519_dalek;
extern crate rand_core;
extern crate zeroize;
mod x25519;
pub use crate::x25519::*;

View file

@ -14,14 +14,14 @@
//! This implements x25519 key exchange as specified by Mike Hamburg
//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748).
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
use curve25519_dalek::montgomery::MontgomeryPoint;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::IsIdentity;
use curve25519_dalek::{
edwards::EdwardsPoint, montgomery::MontgomeryPoint, scalar::Scalar, traits::IsIdentity,
};
use rand_core::CryptoRng;
use rand_core::RngCore;
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
/// A Diffie-Hellman public key, corresponding to an [`EphemeralSecret`] or
@ -31,12 +31,9 @@ use zeroize::Zeroize;
/// should they wish to erase public keys from memory. Note that this erasure
/// (in this crate) does *not* automatically happen, but either must be derived
/// for Drop or explicitly called.
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
#[cfg_attr(
feature = "serde",
derive(our_serde::Serialize, our_serde::Deserialize)
)]
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, Zeroize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub struct PublicKey(pub(crate) MontgomeryPoint);
impl From<[u8; 32]> for PublicKey {
@ -68,8 +65,8 @@ impl PublicKey {
/// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be
/// generated from fresh randomness by [`EphemeralSecret::new`] and the compiler statically checks
/// that the resulting secret is used at most once.
#[derive(Zeroize)]
#[zeroize(drop)]
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
pub struct EphemeralSecret(pub(crate) Scalar);
impl EphemeralSecret {
@ -85,14 +82,14 @@ impl EphemeralSecret {
csprng.fill_bytes(&mut bytes);
EphemeralSecret(clamp_scalar(bytes))
EphemeralSecret(Scalar::from_bits_clamped(bytes))
}
}
impl<'a> From<&'a EphemeralSecret> for PublicKey {
/// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicKey`].
fn from(secret: &'a EphemeralSecret) -> PublicKey {
PublicKey((&ED25519_BASEPOINT_TABLE * &secret.0).to_montgomery())
PublicKey(EdwardsPoint::mul_base(&secret.0).to_montgomery())
}
}
@ -115,8 +112,9 @@ impl<'a> From<&'a EphemeralSecret> for PublicKey {
/// secret keys are never reused, which can have very serious security
/// implications for many protocols.
#[cfg(feature = "reusable_secrets")]
#[derive(Clone, Zeroize)]
#[zeroize(drop)]
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
#[derive(Clone)]
pub struct ReusableSecret(pub(crate) Scalar);
#[cfg(feature = "reusable_secrets")]
@ -124,7 +122,7 @@ 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)
SharedSecret(self.0 * their_public.0)
}
/// Generate a non-serializeable x25519 [`ReuseableSecret`] key.
@ -133,7 +131,7 @@ impl ReusableSecret {
csprng.fill_bytes(&mut bytes);
ReusableSecret(clamp_scalar(bytes))
ReusableSecret(Scalar::from_bits_clamped(bytes))
}
}
@ -141,7 +139,7 @@ impl ReusableSecret {
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())
PublicKey(EdwardsPoint::mul_base(&secret.0).to_montgomery())
}
}
@ -159,13 +157,10 @@ impl<'a> From<&'a ReusableSecret> for PublicKey {
/// [`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",
derive(our_serde::Serialize, our_serde::Deserialize)
)]
#[derive(Clone, Zeroize)]
#[zeroize(drop)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
#[derive(Clone)]
pub struct StaticSecret(
#[cfg_attr(feature = "serde", serde(with = "AllowUnreducedScalarBytes"))] pub(crate) Scalar,
);
@ -174,7 +169,7 @@ impl StaticSecret {
/// 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)
SharedSecret(self.0 * their_public.0)
}
/// Generate an x25519 key.
@ -183,7 +178,7 @@ impl StaticSecret {
csprng.fill_bytes(&mut bytes);
StaticSecret(clamp_scalar(bytes))
StaticSecret(Scalar::from_bits_clamped(bytes))
}
/// Extract this key's bytes for serialization.
@ -195,14 +190,14 @@ impl StaticSecret {
impl From<[u8; 32]> for StaticSecret {
/// Load a secret key from a byte array.
fn from(bytes: [u8; 32]) -> StaticSecret {
StaticSecret(clamp_scalar(bytes))
StaticSecret(Scalar::from_bits_clamped(bytes))
}
}
impl<'a> From<&'a StaticSecret> for PublicKey {
/// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicKey`].
fn from(secret: &'a StaticSecret) -> PublicKey {
PublicKey((&ED25519_BASEPOINT_TABLE * &secret.0).to_montgomery())
PublicKey(EdwardsPoint::mul_base(&secret.0).to_montgomery())
}
}
@ -210,8 +205,8 @@ impl<'a> From<&'a StaticSecret> for PublicKey {
///
/// Each party computes this using their [`EphemeralSecret`] or [`StaticSecret`] and their
/// counterparty's [`PublicKey`].
#[derive(Zeroize)]
#[zeroize(drop)]
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
pub struct SharedSecret(pub(crate) MontgomeryPoint);
impl SharedSecret {
@ -266,22 +261,6 @@ impl SharedSecret {
}
}
/// "Decode" a scalar from a 32-byte array.
///
/// By "decode" here, what is really meant is applying key clamping by twiddling
/// some bits.
///
/// # Returns
///
/// A `Scalar`.
fn clamp_scalar(mut scalar: [u8; 32]) -> Scalar {
scalar[0] &= 248;
scalar[31] &= 127;
scalar[31] |= 64;
Scalar::from_bits(scalar)
}
/// The bare, byte-oriented x25519 function, exactly as specified in RFC7748.
///
/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who
@ -289,8 +268,6 @@ fn clamp_scalar(mut scalar: [u8; 32]) -> Scalar {
///
/// # Example
/// ```
/// # extern crate rand_core;
/// #
/// use rand_core::OsRng;
/// use rand_core::RngCore;
///
@ -315,7 +292,7 @@ fn clamp_scalar(mut scalar: [u8; 32]) -> Scalar {
/// assert_eq!(alice_shared, bob_shared);
/// ```
pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] {
(clamp_scalar(k) * MontgomeryPoint(u)).to_bytes()
(Scalar::from_bits_clamped(k) * MontgomeryPoint(u)).to_bytes()
}
/// The X25519 basepoint, for use with the bare, byte-oriented x25519
@ -328,17 +305,13 @@ pub const X25519_BASEPOINT_BYTES: [u8; 32] = [
/// Derived serialization methods will not work on a StaticSecret because x25519 requires
/// non-canonical scalars which are rejected by curve25519-dalek. Thus we provide a way to convert
/// the bytes directly to a scalar using Serde's remote derive functionality.
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
#[cfg_attr(
feature = "serde",
derive(our_serde::Serialize, our_serde::Deserialize)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(remote = "Scalar"))]
struct AllowUnreducedScalarBytes(
#[cfg_attr(feature = "serde", serde(getter = "Scalar::to_bytes"))] [u8; 32],
);
impl From<AllowUnreducedScalarBytes> for Scalar {
fn from(bytes: AllowUnreducedScalarBytes) -> Scalar {
clamp_scalar(bytes.0)
Scalar::from_bits_clamped(bytes.0)
}
}

View file

@ -1,17 +1,7 @@
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::{edwards::EdwardsPoint, scalar::Scalar};
use x25519_dalek::*;
fn clamp_scalar(mut scalar: [u8; 32]) -> Scalar {
scalar[0] &= 248;
scalar[31] &= 127;
scalar[31] |= 64;
Scalar::from_bits(scalar)
}
#[test]
fn byte_basepoint_matches_edwards_scalar_mul() {
let mut scalar_bytes = [0x37; 32];
@ -21,9 +11,10 @@ fn byte_basepoint_matches_edwards_scalar_mul() {
let result = x25519(scalar_bytes, X25519_BASEPOINT_BYTES);
let expected = (&ED25519_BASEPOINT_TABLE * &clamp_scalar(scalar_bytes))
.to_montgomery()
.to_bytes();
let expected = {
let scalar = Scalar::from_bits_clamped(scalar_bytes);
EdwardsPoint::mul_base(&scalar).to_montgomery().to_bytes()
};
assert_eq!(result, expected);
}
@ -73,7 +64,7 @@ fn serde_bincode_static_secret_matches_from_bytes() {
use bincode;
let expected = StaticSecret::from([0x24; 32]);
let clamped_bytes = clamp_scalar([0x24; 32]).to_bytes();
let clamped_bytes = Scalar::from_bits_clamped([0x24; 32]).to_bytes();
let decoded: StaticSecret = bincode::deserialize(&clamped_bytes).unwrap();
assert_eq!(decoded.to_bytes(), expected.to_bytes());
@ -88,19 +79,19 @@ fn do_rfc7748_ladder_test1(input_scalar: [u8; 32], input_point: [u8; 32], expect
#[test]
fn rfc7748_ladder_test1_vectorset1() {
let input_scalar: [u8; 32] = [
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46,
0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44,
0xba, 0x44, 0x9a, 0xc4,
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e,
0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44,
0x9a, 0xc4,
];
let input_point: [u8; 32] = [
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1,
0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6,
0xd0, 0xab, 0x1c, 0x4c,
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f,
0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab,
0x1c, 0x4c,
];
let expected: [u8; 32] = [
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d,
0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55,
0x77, 0xa2, 0x85, 0x52,
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08,
0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2,
0x85, 0x52,
];
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
@ -109,19 +100,19 @@ fn rfc7748_ladder_test1_vectorset1() {
#[test]
fn rfc7748_ladder_test1_vectorset2() {
let input_scalar: [u8; 32] = [
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d,
0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e,
0x79, 0x18, 0xba, 0x0d,
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a,
0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18,
0xba, 0x0d,
];
let input_point: [u8; 32] = [
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38,
0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49,
0xc7, 0x15, 0xa4, 0x93,
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae,
0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15,
0xa4, 0x93,
];
let expected: [u8; 32] = [
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8,
0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64,
0x7a, 0xac, 0x79, 0x57,
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73,
0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac,
0x79, 0x57,
];
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
@ -189,4 +180,3 @@ fn rfc7748_ladder_test2() {
]
);
}