mirror of
https://github.com/saymrwulf/risc0-curve25519-dalek-source.git
synced 2026-09-04 20:03:40 +00:00
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:
commit
e9fe4145fe
8 changed files with 74 additions and 125 deletions
4
.github/workflows/rust.yml
vendored
4
.github/workflows/rust.yml
vendored
|
|
@ -2,9 +2,9 @@ name: Rust
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ '*' ]
|
branches: [ '**' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main, develop, release ]
|
branches: [ '**' ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ Entries are listed in reverse chronological order.
|
||||||
|
|
||||||
# 2.x Series
|
# 2.x Series
|
||||||
|
|
||||||
|
* Update MSRV to 1.60.
|
||||||
|
|
||||||
## 2.0.0-pre.1
|
## 2.0.0-pre.1
|
||||||
|
|
||||||
* Loosen restriction on zeroize dependency version from =1.3 to 1.
|
* Loosen restriction on zeroize dependency version from =1.3 to 1.
|
||||||
|
|
|
||||||
26
Cargo.toml
26
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "x25519-dalek"
|
name = "x25519-dalek"
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
# Before changing this:
|
# Before changing this:
|
||||||
# - update version in README.md
|
# - update version in README.md
|
||||||
# - update html_root_url
|
# - update html_root_url
|
||||||
|
|
@ -25,6 +25,7 @@ exclude = [
|
||||||
".travis.yml",
|
".travis.yml",
|
||||||
"CONTRIBUTING.md",
|
"CONTRIBUTING.md",
|
||||||
]
|
]
|
||||||
|
rust-version = "1.60"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
|
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"]
|
features = ["nightly", "reusable_secrets", "serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
curve25519-dalek = { version = "3", default-features = false }
|
curve25519-dalek = { version = "4.0.0-rc.0", default-features = false }
|
||||||
rand_core = { version = "0.6", default-features = false }
|
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }
|
||||||
# `serde` is renamed to `our_serde` in order to avoid a name collision between
|
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
|
||||||
# importing the serde dependency and enabling the curve25519-dalek/serde feature
|
zeroize = { version = "1", default-features = false, optional = true, features = ["zeroize_derive"] }
|
||||||
our_serde = { package = "serde", version = "1", default-features = false, optional = true, features = ["derive"] }
|
|
||||||
zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bincode = "1"
|
bincode = "1"
|
||||||
|
|
@ -50,12 +49,9 @@ name = "x25519"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "u64_backend"]
|
default = ["alloc", "precomputed-tables", "zeroize"]
|
||||||
serde = ["our_serde", "curve25519-dalek/serde"]
|
zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"]
|
||||||
std = ["curve25519-dalek/std"]
|
serde = ["dep:serde", "curve25519-dalek/serde"]
|
||||||
nightly = ["curve25519-dalek/nightly"]
|
alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"]
|
||||||
|
precomputed-tables = ["curve25519-dalek/precomputed-tables"]
|
||||||
reusable_secrets = []
|
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"]
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ x25519-dalek = "2.0.0-pre.0"
|
||||||
|
|
||||||
# MSRV
|
# MSRV
|
||||||
|
|
||||||
Current MSRV is 1.51.
|
Current MSRV is 1.60.
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,7 @@
|
||||||
|
|
||||||
//! Benchmark the Diffie-Hellman operation.
|
//! Benchmark the Diffie-Hellman operation.
|
||||||
|
|
||||||
#[macro_use]
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
extern crate criterion;
|
|
||||||
extern crate curve25519_dalek;
|
|
||||||
extern crate rand_core;
|
|
||||||
extern crate x25519_dalek;
|
|
||||||
|
|
||||||
use criterion::Criterion;
|
|
||||||
|
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
|
|
||||||
|
|
@ -25,12 +19,12 @@ use x25519_dalek::EphemeralSecret;
|
||||||
use x25519_dalek::PublicKey;
|
use x25519_dalek::PublicKey;
|
||||||
|
|
||||||
fn bench_diffie_hellman(c: &mut Criterion) {
|
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);
|
let bob_public = PublicKey::from(&bob_secret);
|
||||||
|
|
||||||
c.bench_function("diffie_hellman", move |b| {
|
c.bench_function("diffie_hellman", move |b| {
|
||||||
b.iter_with_setup(
|
b.iter_with_setup(
|
||||||
|| EphemeralSecret::new(&mut OsRng),
|
|| EphemeralSecret::new(OsRng),
|
||||||
|alice_secret| alice_secret.diffie_hellman(&bob_public),
|
|alice_secret| alice_secret.diffie_hellman(&bob_public),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
//!
|
//!
|
||||||
//! # MSRV
|
//! # MSRV
|
||||||
//!
|
//!
|
||||||
//! Current MSRV is 1.41 for production builds, and 1.48 for running tests.
|
//! Current MSRV is 1.60.
|
||||||
//!
|
//!
|
||||||
//! # Documentation
|
//! # Documentation
|
||||||
//!
|
//!
|
||||||
|
|
@ -155,12 +155,6 @@
|
||||||
//!
|
//!
|
||||||
//! [crypto_box]: https://github.com/RustCrypto/AEADs/tree/master/crypto_box
|
//! [crypto_box]: https://github.com/RustCrypto/AEADs/tree/master/crypto_box
|
||||||
|
|
||||||
extern crate curve25519_dalek;
|
|
||||||
|
|
||||||
extern crate rand_core;
|
|
||||||
|
|
||||||
extern crate zeroize;
|
|
||||||
|
|
||||||
mod x25519;
|
mod x25519;
|
||||||
|
|
||||||
pub use crate::x25519::*;
|
pub use crate::x25519::*;
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,14 @@
|
||||||
//! This implements x25519 key exchange as specified by Mike Hamburg
|
//! This implements x25519 key exchange as specified by Mike Hamburg
|
||||||
//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748).
|
//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748).
|
||||||
|
|
||||||
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
|
use curve25519_dalek::{
|
||||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
edwards::EdwardsPoint, montgomery::MontgomeryPoint, scalar::Scalar, traits::IsIdentity,
|
||||||
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;
|
||||||
|
|
||||||
|
#[cfg(feature = "zeroize")]
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
/// A Diffie-Hellman public key, corresponding to an [`EphemeralSecret`] or
|
/// 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
|
/// 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
|
/// (in this crate) does *not* automatically happen, but either must be derived
|
||||||
/// for Drop or explicitly called.
|
/// for Drop or explicitly called.
|
||||||
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||||
feature = "serde",
|
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
||||||
derive(our_serde::Serialize, our_serde::Deserialize)
|
|
||||||
)]
|
|
||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, Zeroize)]
|
|
||||||
pub struct PublicKey(pub(crate) MontgomeryPoint);
|
pub struct PublicKey(pub(crate) MontgomeryPoint);
|
||||||
|
|
||||||
impl From<[u8; 32]> for PublicKey {
|
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
|
/// 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
|
/// generated from fresh randomness by [`EphemeralSecret::new`] and the compiler statically checks
|
||||||
/// that the resulting secret is used at most once.
|
/// that the resulting secret is used at most once.
|
||||||
#[derive(Zeroize)]
|
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||||
#[zeroize(drop)]
|
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||||
pub struct EphemeralSecret(pub(crate) Scalar);
|
pub struct EphemeralSecret(pub(crate) Scalar);
|
||||||
|
|
||||||
impl EphemeralSecret {
|
impl EphemeralSecret {
|
||||||
|
|
@ -85,14 +82,14 @@ impl EphemeralSecret {
|
||||||
|
|
||||||
csprng.fill_bytes(&mut bytes);
|
csprng.fill_bytes(&mut bytes);
|
||||||
|
|
||||||
EphemeralSecret(clamp_scalar(bytes))
|
EphemeralSecret(Scalar::from_bits_clamped(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a EphemeralSecret> for PublicKey {
|
impl<'a> From<&'a EphemeralSecret> for PublicKey {
|
||||||
/// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicKey`].
|
/// Given an x25519 [`EphemeralSecret`] key, compute its corresponding [`PublicKey`].
|
||||||
fn from(secret: &'a EphemeralSecret) -> 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
|
/// secret keys are never reused, which can have very serious security
|
||||||
/// implications for many protocols.
|
/// implications for many protocols.
|
||||||
#[cfg(feature = "reusable_secrets")]
|
#[cfg(feature = "reusable_secrets")]
|
||||||
#[derive(Clone, Zeroize)]
|
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||||
#[zeroize(drop)]
|
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ReusableSecret(pub(crate) Scalar);
|
pub struct ReusableSecret(pub(crate) Scalar);
|
||||||
|
|
||||||
#[cfg(feature = "reusable_secrets")]
|
#[cfg(feature = "reusable_secrets")]
|
||||||
|
|
@ -124,7 +122,7 @@ impl ReusableSecret {
|
||||||
/// Perform a Diffie-Hellman key agreement between `self` and
|
/// Perform a Diffie-Hellman key agreement between `self` and
|
||||||
/// `their_public` key to produce a [`SharedSecret`].
|
/// `their_public` key to produce a [`SharedSecret`].
|
||||||
pub fn diffie_hellman(&self, their_public: &PublicKey) -> 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.
|
/// Generate a non-serializeable x25519 [`ReuseableSecret`] key.
|
||||||
|
|
@ -133,7 +131,7 @@ impl ReusableSecret {
|
||||||
|
|
||||||
csprng.fill_bytes(&mut bytes);
|
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 {
|
impl<'a> From<&'a ReusableSecret> for PublicKey {
|
||||||
/// Given an x25519 [`ReusableSecret`] key, compute its corresponding [`PublicKey`].
|
/// Given an x25519 [`ReusableSecret`] key, compute its corresponding [`PublicKey`].
|
||||||
fn from(secret: &'a ReusableSecret) -> 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
|
/// [`EphemeralSecret`] at all times, as that type enforces at compile-time that
|
||||||
/// secret keys are never reused, which can have very serious security
|
/// secret keys are never reused, which can have very serious security
|
||||||
/// implications for many protocols.
|
/// implications for many protocols.
|
||||||
#[cfg_attr(feature = "serde", serde(crate = "our_serde"))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||||
feature = "serde",
|
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||||
derive(our_serde::Serialize, our_serde::Deserialize)
|
#[derive(Clone)]
|
||||||
)]
|
|
||||||
#[derive(Clone, Zeroize)]
|
|
||||||
#[zeroize(drop)]
|
|
||||||
pub struct StaticSecret(
|
pub struct StaticSecret(
|
||||||
#[cfg_attr(feature = "serde", serde(with = "AllowUnreducedScalarBytes"))] pub(crate) Scalar,
|
#[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
|
/// Perform a Diffie-Hellman key agreement between `self` and
|
||||||
/// `their_public` key to produce a `SharedSecret`.
|
/// `their_public` key to produce a `SharedSecret`.
|
||||||
pub fn diffie_hellman(&self, their_public: &PublicKey) -> 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.
|
/// Generate an x25519 key.
|
||||||
|
|
@ -183,7 +178,7 @@ impl StaticSecret {
|
||||||
|
|
||||||
csprng.fill_bytes(&mut bytes);
|
csprng.fill_bytes(&mut bytes);
|
||||||
|
|
||||||
StaticSecret(clamp_scalar(bytes))
|
StaticSecret(Scalar::from_bits_clamped(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract this key's bytes for serialization.
|
/// Extract this key's bytes for serialization.
|
||||||
|
|
@ -195,14 +190,14 @@ impl StaticSecret {
|
||||||
impl From<[u8; 32]> for StaticSecret {
|
impl From<[u8; 32]> for StaticSecret {
|
||||||
/// Load a secret key from a byte array.
|
/// Load a secret key from a byte array.
|
||||||
fn from(bytes: [u8; 32]) -> StaticSecret {
|
fn from(bytes: [u8; 32]) -> StaticSecret {
|
||||||
StaticSecret(clamp_scalar(bytes))
|
StaticSecret(Scalar::from_bits_clamped(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a StaticSecret> for PublicKey {
|
impl<'a> From<&'a StaticSecret> for PublicKey {
|
||||||
/// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicKey`].
|
/// Given an x25519 [`StaticSecret`] key, compute its corresponding [`PublicKey`].
|
||||||
fn from(secret: &'a StaticSecret) -> 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
|
/// Each party computes this using their [`EphemeralSecret`] or [`StaticSecret`] and their
|
||||||
/// counterparty's [`PublicKey`].
|
/// counterparty's [`PublicKey`].
|
||||||
#[derive(Zeroize)]
|
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
|
||||||
#[zeroize(drop)]
|
#[cfg_attr(feature = "zeroize", zeroize(drop))]
|
||||||
pub struct SharedSecret(pub(crate) MontgomeryPoint);
|
pub struct SharedSecret(pub(crate) MontgomeryPoint);
|
||||||
|
|
||||||
impl SharedSecret {
|
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.
|
/// The bare, byte-oriented x25519 function, exactly as specified in RFC7748.
|
||||||
///
|
///
|
||||||
/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who
|
/// This can be used with [`X25519_BASEPOINT_BYTES`] for people who
|
||||||
|
|
@ -289,8 +268,6 @@ fn clamp_scalar(mut scalar: [u8; 32]) -> Scalar {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// # extern crate rand_core;
|
|
||||||
/// #
|
|
||||||
/// use rand_core::OsRng;
|
/// use rand_core::OsRng;
|
||||||
/// use rand_core::RngCore;
|
/// use rand_core::RngCore;
|
||||||
///
|
///
|
||||||
|
|
@ -315,7 +292,7 @@ fn clamp_scalar(mut scalar: [u8; 32]) -> Scalar {
|
||||||
/// assert_eq!(alice_shared, bob_shared);
|
/// assert_eq!(alice_shared, bob_shared);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] {
|
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
|
/// 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
|
/// 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
|
/// 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.
|
/// 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(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(
|
|
||||||
feature = "serde",
|
|
||||||
derive(our_serde::Serialize, our_serde::Deserialize)
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "serde", serde(remote = "Scalar"))]
|
#[cfg_attr(feature = "serde", serde(remote = "Scalar"))]
|
||||||
struct AllowUnreducedScalarBytes(
|
struct AllowUnreducedScalarBytes(
|
||||||
#[cfg_attr(feature = "serde", serde(getter = "Scalar::to_bytes"))] [u8; 32],
|
#[cfg_attr(feature = "serde", serde(getter = "Scalar::to_bytes"))] [u8; 32],
|
||||||
);
|
);
|
||||||
impl From<AllowUnreducedScalarBytes> for Scalar {
|
impl From<AllowUnreducedScalarBytes> for Scalar {
|
||||||
fn from(bytes: AllowUnreducedScalarBytes) -> Scalar {
|
fn from(bytes: AllowUnreducedScalarBytes) -> Scalar {
|
||||||
clamp_scalar(bytes.0)
|
Scalar::from_bits_clamped(bytes.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,7 @@
|
||||||
|
use curve25519_dalek::{edwards::EdwardsPoint, scalar::Scalar};
|
||||||
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
|
|
||||||
use curve25519_dalek::scalar::Scalar;
|
|
||||||
|
|
||||||
use x25519_dalek::*;
|
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]
|
#[test]
|
||||||
fn byte_basepoint_matches_edwards_scalar_mul() {
|
fn byte_basepoint_matches_edwards_scalar_mul() {
|
||||||
let mut scalar_bytes = [0x37; 32];
|
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 result = x25519(scalar_bytes, X25519_BASEPOINT_BYTES);
|
||||||
|
|
||||||
let expected = (&ED25519_BASEPOINT_TABLE * &clamp_scalar(scalar_bytes))
|
let expected = {
|
||||||
.to_montgomery()
|
let scalar = Scalar::from_bits_clamped(scalar_bytes);
|
||||||
.to_bytes();
|
EdwardsPoint::mul_base(&scalar).to_montgomery().to_bytes()
|
||||||
|
};
|
||||||
|
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +64,7 @@ fn serde_bincode_static_secret_matches_from_bytes() {
|
||||||
use bincode;
|
use bincode;
|
||||||
|
|
||||||
let expected = StaticSecret::from([0x24; 32]);
|
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();
|
let decoded: StaticSecret = bincode::deserialize(&clamped_bytes).unwrap();
|
||||||
|
|
||||||
assert_eq!(decoded.to_bytes(), expected.to_bytes());
|
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]
|
#[test]
|
||||||
fn rfc7748_ladder_test1_vectorset1() {
|
fn rfc7748_ladder_test1_vectorset1() {
|
||||||
let input_scalar: [u8; 32] = [
|
let input_scalar: [u8; 32] = [
|
||||||
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46,
|
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e,
|
||||||
0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44,
|
0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44,
|
||||||
0xba, 0x44, 0x9a, 0xc4,
|
0x9a, 0xc4,
|
||||||
];
|
];
|
||||||
let input_point: [u8; 32] = [
|
let input_point: [u8; 32] = [
|
||||||
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1,
|
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f,
|
||||||
0x5f, 0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6,
|
0x7c, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab,
|
||||||
0xd0, 0xab, 0x1c, 0x4c,
|
0x1c, 0x4c,
|
||||||
];
|
];
|
||||||
let expected: [u8; 32] = [
|
let expected: [u8; 32] = [
|
||||||
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d,
|
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08,
|
||||||
0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55,
|
0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2,
|
||||||
0x77, 0xa2, 0x85, 0x52,
|
0x85, 0x52,
|
||||||
];
|
];
|
||||||
|
|
||||||
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
|
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
|
||||||
|
|
@ -109,19 +100,19 @@ fn rfc7748_ladder_test1_vectorset1() {
|
||||||
#[test]
|
#[test]
|
||||||
fn rfc7748_ladder_test1_vectorset2() {
|
fn rfc7748_ladder_test1_vectorset2() {
|
||||||
let input_scalar: [u8; 32] = [
|
let input_scalar: [u8; 32] = [
|
||||||
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d,
|
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a,
|
||||||
0x6a, 0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e,
|
0xf5, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18,
|
||||||
0x79, 0x18, 0xba, 0x0d,
|
0xba, 0x0d,
|
||||||
];
|
];
|
||||||
let input_point: [u8; 32] = [
|
let input_point: [u8; 32] = [
|
||||||
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38,
|
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae,
|
||||||
0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49,
|
0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15,
|
||||||
0xc7, 0x15, 0xa4, 0x93,
|
0xa4, 0x93,
|
||||||
];
|
];
|
||||||
let expected: [u8; 32] = [
|
let expected: [u8; 32] = [
|
||||||
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8,
|
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73,
|
||||||
0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64,
|
0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac,
|
||||||
0x7a, 0xac, 0x79, 0x57,
|
0x79, 0x57,
|
||||||
];
|
];
|
||||||
|
|
||||||
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
|
do_rfc7748_ladder_test1(input_scalar, input_point, expected);
|
||||||
|
|
@ -189,4 +180,3 @@ fn rfc7748_ladder_test2() {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue