Merge branch 'main' into v4.1.1

This commit is contained in:
bunnie 2024-03-25 06:59:43 +08:00 committed by GitHub
commit b486cda2a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 156 additions and 136 deletions

View file

@ -5,6 +5,10 @@ major series.
## 4.x series ## 4.x series
### 4.1.2
* Fix nightly SIMD build
### 4.1.1 ### 4.1.1
* Mark `constants::BASEPOINT_ORDER` deprecated from pub API * Mark `constants::BASEPOINT_ORDER` deprecated from pub API
@ -123,7 +127,7 @@ major series.
### 2.1.2 ### 2.1.2
* Multiple documenation typo fixes. * Multiple documentation typo fixes.
* Fix `alloc` feature working with stable rust. * Fix `alloc` feature working with stable rust.
### 2.1.1 ### 2.1.1

View file

@ -4,7 +4,7 @@ name = "curve25519-dalek"
# - update CHANGELOG # - update CHANGELOG
# - update README if required by semver # - update README if required by semver
# - if README was updated, also update module documentation in src/lib.rs # - if README was updated, also update module documentation in src/lib.rs
version = "4.1.1" version = "4.1.2"
edition = "2021" edition = "2021"
rust-version = "1.60.0" rust-version = "1.60.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>", authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
@ -38,7 +38,6 @@ rand = "0.8"
rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } rand_core = { version = "0.6", default-features = false, features = ["getrandom"] }
[build-dependencies] [build-dependencies]
platforms = "3.0.2"
rustc_version = "0.4.0" rustc_version = "0.4.0"
[[bench]] [[bench]]

View file

@ -25,15 +25,12 @@ fn main() {
let curve25519_dalek_bits = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BITS").as_deref() { let curve25519_dalek_bits = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BITS").as_deref() {
Ok("32") => DalekBits::Dalek32, Ok("32") => DalekBits::Dalek32,
Ok("64") => DalekBits::Dalek64, Ok("64") => DalekBits::Dalek64,
_ => deterministic::determine_curve25519_dalek_bits(), _ => deterministic::determine_curve25519_dalek_bits(&target_arch),
}; };
build_debug!("CARGO_CFG_CURVE25519_DALEK_BITS: {:?}", std::env::var("CARGO_CFG_CURVE25519_DALEK_BITS").as_deref()); build_debug!("CARGO_CFG_CURVE25519_DALEK_BITS: {:?}", std::env::var("CARGO_CFG_CURVE25519_DALEK_BITS").as_deref());
build_debug!("curve25519_dalek_bits {:?}", curve25519_dalek_bits); build_debug!("curve25519_dalek_bits {:?}", curve25519_dalek_bits);
match curve25519_dalek_bits { println!("cargo:rustc-cfg=curve25519_dalek_bits=\"{curve25519_dalek_bits}\"");
DalekBits::Dalek64 => println!("cargo:rustc-cfg=curve25519_dalek_bits=\"64\""),
DalekBits::Dalek32 => println!("cargo:rustc-cfg=curve25519_dalek_bits=\"32\""),
}
if rustc_version::version_meta() if rustc_version::version_meta()
.expect("failed to detect rustc version") .expect("failed to detect rustc version")
@ -105,11 +102,12 @@ mod deterministic {
use super::*; use super::*;
// Standard Cargo TARGET environment variable of triplet is required // Custom Rust non-cargo build tooling needs to set CARGO_CFG_TARGET_POINTER_WIDTH
static ERR_MSG_NO_TARGET: &str = "Standard Cargo TARGET environment variable is not set"; static ERR_MSG_NO_POINTER_WIDTH: &str =
"Standard Cargo TARGET_POINTER_WIDTH environment variable is not set.";
// Custom Non-Rust standard target platforms require explicit settings. // When either non-32 or 64 TARGET_POINTER_WIDTH detected
static ERR_MSG_NO_PLATFORM: &str = "Unknown Rust target platform."; static ERR_MSG_UNKNOWN_POINTER_WIDTH: &str = "Unknown TARGET_POINTER_WIDTH detected.";
// Warning when the curve25519_dalek_bits cannot be determined // Warning when the curve25519_dalek_bits cannot be determined
fn determine_curve25519_dalek_bits_warning(cause: &str) { fn determine_curve25519_dalek_bits_warning(cause: &str) {
@ -117,41 +115,30 @@ mod deterministic {
} }
// Determine the curve25519_dalek_bits based on Rust standard TARGET triplet // Determine the curve25519_dalek_bits based on Rust standard TARGET triplet
pub(super) fn determine_curve25519_dalek_bits() -> DalekBits { pub(super) fn determine_curve25519_dalek_bits(target_arch: &String) -> DalekBits {
use platforms::target::PointerWidth; let target_pointer_width = match std::env::var("CARGO_CFG_TARGET_POINTER_WIDTH") {
Ok(pw) => pw,
// TARGET environment is supplied by Cargo
// https://doc.rust-lang.org/cargo/reference/environment-variables.html
let target_triplet = match std::env::var("TARGET") {
Ok(t) => t,
Err(_) => { Err(_) => {
determine_curve25519_dalek_bits_warning(ERR_MSG_NO_TARGET); determine_curve25519_dalek_bits_warning(ERR_MSG_NO_POINTER_WIDTH);
return DalekBits::Dalek32;
}
};
// platforms crate is the source of truth used to determine the platform
let platform = match platforms::Platform::find(&target_triplet) {
Some(p) => p,
None => {
determine_curve25519_dalek_bits_warning(ERR_MSG_NO_PLATFORM);
return DalekBits::Dalek32; return DalekBits::Dalek32;
} }
}; };
#[allow(clippy::match_single_binding)] #[allow(clippy::match_single_binding)]
match platform.target_arch { match &target_arch {
//Issues: 449 and 456 //Issues: 449 and 456
//TODO: When adding arch defaults use proper types not String match
//TODO(Arm): Needs tests + benchmarks to back this up //TODO(Arm): Needs tests + benchmarks to back this up
//platforms::target::Arch::Arm => DalekBits::Dalek64,
//TODO(Wasm32): Needs tests + benchmarks to back this up //TODO(Wasm32): Needs tests + benchmarks to back this up
//platforms::target::Arch::Wasm32 => DalekBits::Dalek64, _ => match target_pointer_width.as_ref() {
_ => match platform.target_pointer_width { "64" => DalekBits::Dalek64,
PointerWidth::U64 => DalekBits::Dalek64, "32" => DalekBits::Dalek32,
PointerWidth::U32 => DalekBits::Dalek32,
// Intended default solely for non-32/64 target pointer widths // Intended default solely for non-32/64 target pointer widths
// Otherwise known target platforms only. // Otherwise known target platforms only.
_ => DalekBits::Dalek32, _ => {
determine_curve25519_dalek_bits_warning(ERR_MSG_UNKNOWN_POINTER_WIDTH);
DalekBits::Dalek32
}
}, },
} }
} }

View file

@ -351,7 +351,7 @@ This computation requires 25 `vpmadd52luq` and 25 `vpmadd52huq`
operations. For 256-bit vectors, IFMA operations execute on an operations. For 256-bit vectors, IFMA operations execute on an
i3-8121U with latency 4 cycles, throughput 0.5 cycles, so executing 50 i3-8121U with latency 4 cycles, throughput 0.5 cycles, so executing 50
instructions requires 25 cycles' worth of throughput. Accumulating instructions requires 25 cycles' worth of throughput. Accumulating
terms with coefficient \\(1\\) and \\(2\\) seperately means that the terms with coefficient \\(1\\) and \\(2\\) separately means that the
longest dependency chain has length 5, so the critical path has length longest dependency chain has length 5, so the critical path has length
20 cycles and the bottleneck is throughput. 20 cycles and the bottleneck is throughput.

View file

@ -87,24 +87,24 @@ where
match get_selected_backend() { match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => BackendKind::Avx2 =>
self::vector::scalar_mul::pippenger::spec_avx2::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points), vector::scalar_mul::pippenger::spec_avx2::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => BackendKind::Avx512 =>
self::vector::scalar_mul::pippenger::spec_avx512ifma_avx512vl::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points), vector::scalar_mul::pippenger::spec_avx512ifma_avx512vl::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
BackendKind::Serial => BackendKind::Serial =>
self::serial::scalar_mul::pippenger::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points), serial::scalar_mul::pippenger::Pippenger::optional_multiscalar_mul::<I, J>(scalars, points),
} }
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub(crate) enum VartimePrecomputedStraus { pub(crate) enum VartimePrecomputedStraus {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
Avx2(self::vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus), Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus),
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
Avx512ifma( Avx512ifma(
self::vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus, vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus,
), ),
Scalar(self::serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus), Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus),
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -119,12 +119,12 @@ impl VartimePrecomputedStraus {
match get_selected_backend() { match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => BackendKind::Avx2 =>
VartimePrecomputedStraus::Avx2(self::vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus::new(static_points)), VartimePrecomputedStraus::Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus::new(static_points)),
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => BackendKind::Avx512 =>
VartimePrecomputedStraus::Avx512ifma(self::vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus::new(static_points)), VartimePrecomputedStraus::Avx512ifma(vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus::new(static_points)),
BackendKind::Serial => BackendKind::Serial =>
VartimePrecomputedStraus::Scalar(self::serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points)) VartimePrecomputedStraus::Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points))
} }
} }
@ -179,19 +179,16 @@ where
match get_selected_backend() { match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => { BackendKind::Avx2 => {
self::vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::<I, J>( vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::<I, J>(scalars, points)
scalars, points,
)
} }
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => { BackendKind::Avx512 => {
self::vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::< vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::<I, J>(
I, scalars, points,
J, )
>(scalars, points)
} }
BackendKind::Serial => { BackendKind::Serial => {
self::serial::scalar_mul::straus::Straus::multiscalar_mul::<I, J>(scalars, points) serial::scalar_mul::straus::Straus::multiscalar_mul::<I, J>(scalars, points)
} }
} }
} }
@ -209,21 +206,19 @@ where
match get_selected_backend() { match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => { BackendKind::Avx2 => {
self::vector::scalar_mul::straus::spec_avx2::Straus::optional_multiscalar_mul::<I, J>( vector::scalar_mul::straus::spec_avx2::Straus::optional_multiscalar_mul::<I, J>(
scalars, points, scalars, points,
) )
} }
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => { BackendKind::Avx512 => {
self::vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::< vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::<
I, I,
J, J,
>(scalars, points) >(scalars, points)
} }
BackendKind::Serial => { BackendKind::Serial => {
self::serial::scalar_mul::straus::Straus::optional_multiscalar_mul::<I, J>( serial::scalar_mul::straus::Straus::optional_multiscalar_mul::<I, J>(scalars, points)
scalars, points,
)
} }
} }
} }
@ -232,12 +227,12 @@ where
pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint {
match get_selected_backend() { match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => self::vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar), BackendKind::Avx2 => vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar),
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => { BackendKind::Avx512 => {
self::vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar) vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar)
} }
BackendKind::Serial => self::serial::scalar_mul::variable_base::mul(point, scalar), BackendKind::Serial => serial::scalar_mul::variable_base::mul(point, scalar),
} }
} }
@ -246,11 +241,11 @@ pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint
pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint {
match get_selected_backend() { match get_selected_backend() {
#[cfg(curve25519_dalek_backend = "simd")] #[cfg(curve25519_dalek_backend = "simd")]
BackendKind::Avx2 => self::vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b), BackendKind::Avx2 => vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b),
#[cfg(all(curve25519_dalek_backend = "simd", nightly))] #[cfg(all(curve25519_dalek_backend = "simd", nightly))]
BackendKind::Avx512 => { BackendKind::Avx512 => {
self::vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b) vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b)
} }
BackendKind::Serial => self::serial::scalar_mul::vartime_double_base::mul(a, A, b), BackendKind::Serial => serial::scalar_mul::vartime_double_base::mul(a, A, b),
} }
} }

View file

@ -527,7 +527,7 @@ impl<'a> Neg for &'a AffineNielsPoint {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
impl Debug for ProjectivePoint { impl Debug for ProjectivePoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!( write!(
f, f,
"ProjectivePoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?}\n}}", "ProjectivePoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?}\n}}",
@ -537,7 +537,7 @@ impl Debug for ProjectivePoint {
} }
impl Debug for CompletedPoint { impl Debug for CompletedPoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!( write!(
f, f,
"CompletedPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", "CompletedPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}",
@ -547,7 +547,7 @@ impl Debug for CompletedPoint {
} }
impl Debug for AffineNielsPoint { impl Debug for AffineNielsPoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!( write!(
f, f,
"AffineNielsPoint{{\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n}}", "AffineNielsPoint{{\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n}}",
@ -557,7 +557,7 @@ impl Debug for AffineNielsPoint {
} }
impl Debug for ProjectiveNielsPoint { impl Debug for ProjectiveNielsPoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "ProjectiveNielsPoint{{\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n}}", write!(f, "ProjectiveNielsPoint{{\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n}}",
&self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d) &self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d)
} }

View file

@ -58,7 +58,7 @@ use fiat_crypto::curve25519_32::*;
pub struct FieldElement2625(pub(crate) fiat_25519_tight_field_element); pub struct FieldElement2625(pub(crate) fiat_25519_tight_field_element);
impl Debug for FieldElement2625 { impl Debug for FieldElement2625 {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "FieldElement2625({:?})", &(self.0).0[..]) write!(f, "FieldElement2625({:?})", &(self.0).0[..])
} }
} }

View file

@ -47,7 +47,7 @@ use fiat_crypto::curve25519_64::*;
pub struct FieldElement51(pub(crate) fiat_25519_tight_field_element); pub struct FieldElement51(pub(crate) fiat_25519_tight_field_element);
impl Debug for FieldElement51 { impl Debug for FieldElement51 {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "FieldElement51({:?})", &(self.0).0[..]) write!(f, "FieldElement51({:?})", &(self.0).0[..])
} }
} }

View file

@ -164,7 +164,6 @@ impl VartimeMultiscalarMul for Pippenger {
mod test { mod test {
use super::*; use super::*;
use crate::constants; use crate::constants;
use crate::scalar::Scalar;
#[test] #[test]
fn test_vartime_pippenger() { fn test_vartime_pippenger() {

View file

@ -54,7 +54,7 @@ use zeroize::Zeroize;
pub struct FieldElement2625(pub(crate) [u32; 10]); pub struct FieldElement2625(pub(crate) [u32; 10]);
impl Debug for FieldElement2625 { impl Debug for FieldElement2625 {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "FieldElement2625({:?})", &self.0[..]) write!(f, "FieldElement2625({:?})", &self.0[..])
} }
} }

View file

@ -24,7 +24,7 @@ use crate::constants;
pub struct Scalar29(pub [u32; 9]); pub struct Scalar29(pub [u32; 9]);
impl Debug for Scalar29 { impl Debug for Scalar29 {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Scalar29: {:?}", &self.0[..]) write!(f, "Scalar29: {:?}", &self.0[..])
} }
} }

View file

@ -43,7 +43,7 @@ use zeroize::Zeroize;
pub struct FieldElement51(pub(crate) [u64; 5]); pub struct FieldElement51(pub(crate) [u64; 5]);
impl Debug for FieldElement51 { impl Debug for FieldElement51 {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "FieldElement51({:?})", &self.0[..]) write!(f, "FieldElement51({:?})", &self.0[..])
} }
} }

View file

@ -25,7 +25,7 @@ use crate::constants;
pub struct Scalar52(pub [u64; 5]); pub struct Scalar52(pub [u64; 5]);
impl Debug for Scalar52 { impl Debug for Scalar52 {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Scalar52: {:?}", &self.0[..]) write!(f, "Scalar52: {:?}", &self.0[..])
} }
} }

View file

@ -35,7 +35,6 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use core::convert::From;
use core::ops::{Add, Neg, Sub}; use core::ops::{Add, Neg, Sub};
use subtle::Choice; use subtle::Choice;

View file

@ -96,7 +96,6 @@
use core::array::TryFromSliceError; use core::array::TryFromSliceError;
use core::borrow::Borrow; use core::borrow::Borrow;
use core::fmt::Debug; use core::fmt::Debug;
use core::iter::Iterator;
use core::iter::Sum; use core::iter::Sum;
use core::ops::{Add, Neg, Sub}; use core::ops::{Add, Neg, Sub};
use core::ops::{AddAssign, SubAssign}; use core::ops::{AddAssign, SubAssign};
@ -110,10 +109,12 @@ use digest::{generic_array::typenum::U64, Digest};
#[cfg(feature = "group")] #[cfg(feature = "group")]
use { use {
group::{cofactor::CofactorGroup, prime::PrimeGroup, GroupEncoding}, group::{cofactor::CofactorGroup, prime::PrimeGroup, GroupEncoding},
rand_core::RngCore,
subtle::CtOption, subtle::CtOption,
}; };
#[cfg(feature = "group")]
use rand_core::RngCore;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallyNegatable; use subtle::ConditionallyNegatable;
use subtle::ConditionallySelectable; use subtle::ConditionallySelectable;
@ -170,7 +171,7 @@ impl ConstantTimeEq for CompressedEdwardsY {
} }
impl Debug for CompressedEdwardsY { impl Debug for CompressedEdwardsY {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "CompressedEdwardsY: {:?}", self.as_bytes()) write!(f, "CompressedEdwardsY: {:?}", self.as_bytes())
} }
} }
@ -258,7 +259,7 @@ impl TryFrom<&[u8]> for CompressedEdwardsY {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::de::Visitor; use serde::de::Visitor;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
impl Serialize for EdwardsPoint { impl Serialize for EdwardsPoint {
@ -301,7 +302,7 @@ impl<'de> Deserialize<'de> for EdwardsPoint {
impl<'de> Visitor<'de> for EdwardsPointVisitor { impl<'de> Visitor<'de> for EdwardsPointVisitor {
type Value = EdwardsPoint; type Value = EdwardsPoint;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("a valid point in Edwards y + sign format") formatter.write_str("a valid point in Edwards y + sign format")
} }
@ -337,7 +338,7 @@ impl<'de> Deserialize<'de> for CompressedEdwardsY {
impl<'de> Visitor<'de> for CompressedEdwardsYVisitor { impl<'de> Visitor<'de> for CompressedEdwardsYVisitor {
type Value = CompressedEdwardsY; type Value = CompressedEdwardsY;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("32 bytes of data") formatter.write_str("32 bytes of data")
} }
@ -1052,7 +1053,7 @@ macro_rules! impl_basepoint_table {
} }
impl Debug for $name { impl Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}([\n", stringify!($name))?; write!(f, "{:?}([\n", stringify!($name))?;
for i in 0..32 { for i in 0..32 {
write!(f, "\t{:?},\n", &self.0[i])?; write!(f, "\t{:?},\n", &self.0[i])?;
@ -1263,7 +1264,7 @@ impl EdwardsPoint {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
impl Debug for EdwardsPoint { impl Debug for EdwardsPoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!( write!(
f, f,
"EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}",
@ -1591,8 +1592,10 @@ impl CofactorGroup for EdwardsPoint {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::{field::FieldElement, scalar::Scalar};
use subtle::ConditionallySelectable; // If `group` is set, then this is already imported in super
#[cfg(not(feature = "group"))]
use rand_core::RngCore;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
@ -1600,8 +1603,6 @@ mod test {
#[cfg(feature = "precomputed-tables")] #[cfg(feature = "precomputed-tables")]
use crate::constants::ED25519_BASEPOINT_TABLE; use crate::constants::ED25519_BASEPOINT_TABLE;
use rand_core::RngCore;
/// X coordinate of the basepoint. /// X coordinate of the basepoint.
/// = 15112221349535400772501151409588531511454012693041857206046113283949847762202 /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202
static BASE_X_COORD_BYTES: [u8; 32] = [ static BASE_X_COORD_BYTES: [u8; 32] = [

View file

@ -25,8 +25,6 @@
#[allow(unused_qualifications)] #[allow(unused_qualifications)]
use core::cmp::{Eq, PartialEq};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use subtle::Choice; use subtle::Choice;
@ -322,7 +320,6 @@ extern crate rand;
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::field::*; use crate::field::*;
use subtle::ConditionallyNegatable;
/// Random element a of GF(2^255-19), from Sage /// Random element a of GF(2^255-19), from Sage
/// a = 1070314506888354081329385823235218444233221\ /// a = 1070314506888354081329385823235218444233221\

View file

@ -10,7 +10,14 @@
// - Henry de Valence <hdevalence@hdevalence.ca> // - Henry de Valence <hdevalence@hdevalence.ca>
#![no_std] #![no_std]
#![cfg_attr(all(curve25519_dalek_backend = "simd", nightly), feature(stdsimd))] #![cfg_attr(
all(
curve25519_dalek_backend = "simd",
nightly,
any(target_arch = "x86", target_arch = "x86_64")
),
feature(stdarch_x86_avx512)
)]
#![cfg_attr( #![cfg_attr(
all(curve25519_dalek_backend = "simd", nightly), all(curve25519_dalek_backend = "simd", nightly),
feature(avx512_target_feature) feature(avx512_target_feature)

View file

@ -364,7 +364,7 @@ impl TryFrom<&[u8]> for CompressedRistretto {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::de::Visitor; use serde::de::Visitor;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
impl Serialize for RistrettoPoint { impl Serialize for RistrettoPoint {
@ -407,7 +407,7 @@ impl<'de> Deserialize<'de> for RistrettoPoint {
impl<'de> Visitor<'de> for RistrettoPointVisitor { impl<'de> Visitor<'de> for RistrettoPointVisitor {
type Value = RistrettoPoint; type Value = RistrettoPoint;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("a valid point in Ristretto format") formatter.write_str("a valid point in Ristretto format")
} }
@ -443,7 +443,7 @@ impl<'de> Deserialize<'de> for CompressedRistretto {
impl<'de> Visitor<'de> for CompressedRistrettoVisitor { impl<'de> Visitor<'de> for CompressedRistrettoVisitor {
type Value = CompressedRistretto; type Value = CompressedRistretto;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("32 bytes of data") formatter.write_str("32 bytes of data")
} }
@ -1155,13 +1155,13 @@ impl ConditionallySelectable for RistrettoPoint {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
impl Debug for CompressedRistretto { impl Debug for CompressedRistretto {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "CompressedRistretto: {:?}", self.as_bytes()) write!(f, "CompressedRistretto: {:?}", self.as_bytes())
} }
} }
impl Debug for RistrettoPoint { impl Debug for RistrettoPoint {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let coset = self.coset4(); let coset = self.coset4();
write!( write!(
f, f,
@ -1277,8 +1277,6 @@ impl Zeroize for RistrettoPoint {
mod test { mod test {
use super::*; use super::*;
use crate::edwards::CompressedEdwardsY; use crate::edwards::CompressedEdwardsY;
use crate::scalar::Scalar;
use crate::traits::Identity;
use rand_core::OsRng; use rand_core::OsRng;

View file

@ -112,8 +112,6 @@
//! has been enabled. //! has been enabled.
use core::borrow::Borrow; use core::borrow::Borrow;
use core::cmp::{Eq, PartialEq};
use core::convert::TryInto;
use core::fmt::Debug; use core::fmt::Debug;
use core::iter::{Product, Sum}; use core::iter::{Product, Sum};
use core::ops::Index; use core::ops::Index;
@ -124,13 +122,13 @@ use core::ops::{Sub, SubAssign};
use cfg_if::cfg_if; use cfg_if::cfg_if;
#[cfg(feature = "group")]
use group::ff::{Field, FromUniformBytes, PrimeField};
#[cfg(feature = "group-bits")] #[cfg(feature = "group-bits")]
use group::ff::{FieldBits, PrimeFieldBits}; use group::ff::{FieldBits, PrimeFieldBits};
#[cfg(feature = "group")]
use { #[cfg(any(test, feature = "group"))]
group::ff::{Field, FromUniformBytes, PrimeField}, use rand_core::RngCore;
rand_core::RngCore,
};
#[cfg(any(test, feature = "rand_core"))] #[cfg(any(test, feature = "rand_core"))]
use rand_core::CryptoRngCore; use rand_core::CryptoRngCore;
@ -294,7 +292,7 @@ impl Scalar {
} }
impl Debug for Scalar { impl Debug for Scalar {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Scalar{{\n\tbytes: {:?},\n}}", &self.bytes) write!(f, "Scalar{{\n\tbytes: {:?},\n}}", &self.bytes)
} }
} }
@ -409,7 +407,7 @@ impl ConditionallySelectable for Scalar {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::de::Visitor; use serde::de::Visitor;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
@ -439,7 +437,7 @@ impl<'de> Deserialize<'de> for Scalar {
impl<'de> Visitor<'de> for ScalarVisitor { impl<'de> Visitor<'de> for ScalarVisitor {
type Value = Scalar; type Value = Scalar;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str( formatter.write_str(
"a sequence of 32 bytes whose little-endian interpretation is less than the \ "a sequence of 32 bytes whose little-endian interpretation is less than the \
basepoint order ", basepoint order ",
@ -840,7 +838,7 @@ impl Scalar {
} }
#[cfg(feature = "zeroize")] #[cfg(feature = "zeroize")]
zeroize::Zeroize::zeroize(&mut scratch); Zeroize::zeroize(&mut scratch);
ret ret
} }
@ -1401,13 +1399,10 @@ pub const fn clamp_integer(mut bytes: [u8; 32]) -> [u8; 32] {
#[cfg(test)] #[cfg(test)]
pub(crate) mod test { pub(crate) mod test {
use super::*; use super::*;
use crate::constants;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
use rand::RngCore;
/// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 /// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222
pub static X: Scalar = Scalar { pub static X: Scalar = Scalar {
bytes: [ bytes: [

View file

@ -15,9 +15,8 @@
use core::borrow::Borrow; use core::borrow::Borrow;
use subtle;
use crate::scalar::{clamp_integer, Scalar}; use crate::scalar::{clamp_integer, Scalar};
use subtle::ConstantTimeEq;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Public Traits // Public Traits
@ -41,7 +40,7 @@ pub trait IsIdentity {
/// constructor. /// constructor.
impl<T> IsIdentity for T impl<T> IsIdentity for T
where where
T: subtle::ConstantTimeEq + Identity, T: ConstantTimeEq + Identity,
{ {
fn is_identity(&self) -> bool { fn is_identity(&self) -> bool {
self.ct_eq(&T::identity()).into() self.ct_eq(&T::identity()).into()
@ -409,6 +408,7 @@ pub trait VartimePrecomputedMultiscalarMul: Sized {
/// This trait is only for debugging/testing, since it should be /// This trait is only for debugging/testing, since it should be
/// impossible for a `curve25519-dalek` user to construct an invalid /// impossible for a `curve25519-dalek` user to construct an invalid
/// point. /// point.
#[allow(dead_code)]
pub(crate) trait ValidityCheck { pub(crate) trait ValidityCheck {
/// Checks whether the point is on the curve. Not CT. /// Checks whether the point is on the curve. Not CT.
fn is_valid(&self) -> bool; fn is_valid(&self) -> bool;

View file

@ -83,7 +83,7 @@ macro_rules! impl_lookup_table {
} }
impl<T: Debug> Debug for $name<T> { impl<T: Debug> Debug for $name<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}(", stringify!($name))?; write!(f, "{:?}(", stringify!($name))?;
for x in self.0.iter() { for x in self.0.iter() {
@ -193,7 +193,7 @@ impl<T: Copy> NafLookupTable5<T> {
} }
impl<T: Debug> Debug for NafLookupTable5<T> { impl<T: Debug> Debug for NafLookupTable5<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "NafLookupTable5({:?})", self.0) write!(f, "NafLookupTable5({:?})", self.0)
} }
} }
@ -240,7 +240,7 @@ impl<T: Copy> NafLookupTable8<T> {
#[cfg(any(feature = "precomputed-tables", feature = "alloc"))] #[cfg(any(feature = "precomputed-tables", feature = "alloc"))]
impl<T: Debug> Debug for NafLookupTable8<T> { impl<T: Debug> Debug for NafLookupTable8<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "NafLookupTable8([")?; writeln!(f, "NafLookupTable8([")?;
for i in 0..64 { for i in 0..64 {
writeln!(f, "\t{:?},", &self.0[i])?; writeln!(f, "\t{:?},", &self.0[i])?;

View file

@ -10,6 +10,10 @@ Entries are listed in reverse chronological order per undeprecated major series.
# 2.x series # 2.x series
## 2.1.1
* Fix nightly SIMD build
## 2.1.0 ## 2.1.0
* Add `SigningKey::to_scalar_bytes` for getting the unclamped scalar from a signing key * Add `SigningKey::to_scalar_bytes` for getting the unclamped scalar from a signing key

View file

@ -1,6 +1,6 @@
[package] [package]
name = "ed25519-dalek" name = "ed25519-dalek"
version = "2.1.0" version = "2.1.1"
edition = "2021" edition = "2021"
authors = [ authors = [
"isis lovecruft <isis@patternsinthevoid.net>", "isis lovecruft <isis@patternsinthevoid.net>",

View file

@ -31,7 +31,7 @@ This crate is `#[no_std]` compatible with `default-features = false`.
# Major Changes # Major Changes
See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past version of this crate. See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past versions of this crate.
## Breaking Changes in 2.0.0 ## Breaking Changes in 2.0.0
@ -63,7 +63,7 @@ SemVer exemptions are outlined below for MSRV and public API.
| 2.x | 1.60 | | 2.x | 1.60 |
| 1.x | 1.41 | | 1.x | 1.41 |
From 2.x and on, MSRV changes will be accompanied by a minor version bump. From 2.x onwards, MSRV changes will be accompanied by a minor version bump.
## Public API SemVer Exemptions ## Public API SemVer Exemptions
@ -130,7 +130,7 @@ Backend selection details and instructions can be found in the [curve25519-dalek
# Contributing # Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) See [CONTRIBUTING.md](../CONTRIBUTING.md)
# Batch Signature Verification # Batch Signature Verification

View file

@ -11,7 +11,6 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use core::convert::TryFrom;
use core::iter::once; use core::iter::once;
use curve25519_dalek::constants; use curve25519_dalek::constants;

View file

@ -21,6 +21,7 @@
#![cfg_attr(feature = "rand_core", doc = "```")] #![cfg_attr(feature = "rand_core", doc = "```")]
#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] #![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
//! # fn main() { //! # fn main() {
//! // $ cargo add ed25519_dalek --features rand_core
//! use rand::rngs::OsRng; //! use rand::rngs::OsRng;
//! use ed25519_dalek::SigningKey; //! use ed25519_dalek::SigningKey;
//! use ed25519_dalek::Signature; //! use ed25519_dalek::Signature;

View file

@ -9,7 +9,6 @@
//! An ed25519 signature. //! An ed25519 signature.
use core::convert::TryFrom;
use core::fmt::Debug; use core::fmt::Debug;
use curve25519_dalek::edwards::CompressedEdwardsY; use curve25519_dalek::edwards::CompressedEdwardsY;
@ -58,7 +57,7 @@ impl Clone for InternalSignature {
} }
impl Debug for InternalSignature { impl Debug for InternalSignature {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s) write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s)
} }
} }

View file

@ -543,7 +543,7 @@ impl AsRef<VerifyingKey> for SigningKey {
} }
impl Debug for SigningKey { impl Debug for SigningKey {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SigningKey") f.debug_struct("SigningKey")
.field("verifying_key", &self.verifying_key) .field("verifying_key", &self.verifying_key)
.finish_non_exhaustive() // avoids printing `secret_key` .finish_non_exhaustive() // avoids printing `secret_key`
@ -742,7 +742,7 @@ impl<'d> Deserialize<'d> for SigningKey {
impl<'de> serde::de::Visitor<'de> for SigningKeyVisitor { impl<'de> serde::de::Visitor<'de> for SigningKeyVisitor {
type Value = SigningKey; type Value = SigningKey;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(formatter, concat!("An ed25519 signing (private) key")) write!(formatter, concat!("An ed25519 signing (private) key"))
} }

View file

@ -9,7 +9,6 @@
//! ed25519 public keys. //! ed25519 public keys.
use core::convert::TryFrom;
use core::fmt::Debug; use core::fmt::Debug;
use core::hash::{Hash, Hasher}; use core::hash::{Hash, Hasher};
@ -505,6 +504,11 @@ impl VerifyingKey {
pub fn to_montgomery(&self) -> MontgomeryPoint { pub fn to_montgomery(&self) -> MontgomeryPoint {
self.point.to_montgomery() self.point.to_montgomery()
} }
/// Return this verifying key in Edwards form.
pub fn to_edwards(&self) -> EdwardsPoint {
self.point
}
} }
impl Verifier<ed25519::Signature> for VerifyingKey { impl Verifier<ed25519::Signature> for VerifyingKey {
@ -563,6 +567,12 @@ impl TryFrom<&[u8]> for VerifyingKey {
} }
} }
impl From<VerifyingKey> for EdwardsPoint {
fn from(vk: VerifyingKey) -> EdwardsPoint {
vk.point
}
}
#[cfg(all(feature = "alloc", feature = "pkcs8"))] #[cfg(all(feature = "alloc", feature = "pkcs8"))]
impl pkcs8::EncodePublicKey for VerifyingKey { impl pkcs8::EncodePublicKey for VerifyingKey {
fn to_public_key_der(&self) -> pkcs8::spki::Result<pkcs8::Document> { fn to_public_key_der(&self) -> pkcs8::spki::Result<pkcs8::Document> {
@ -632,7 +642,7 @@ impl<'d> Deserialize<'d> for VerifyingKey {
impl<'de> serde::de::Visitor<'de> for VerifyingKeyVisitor { impl<'de> serde::de::Visitor<'de> for VerifyingKeyVisitor {
type Value = VerifyingKey; type Value = VerifyingKey;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(formatter, concat!("An ed25519 verifying (public) key")) write!(formatter, concat!("An ed25519 verifying (public) key"))
} }

View file

@ -27,10 +27,11 @@ mod vectors {
scalar::Scalar, scalar::Scalar,
traits::IsIdentity, traits::IsIdentity,
}; };
#[cfg(not(feature = "digest"))]
use sha2::{digest::Digest, Sha512}; use sha2::{digest::Digest, Sha512};
use std::{ use std::{
convert::TryFrom,
fs::File, fs::File,
io::{BufRead, BufReader}, io::{BufRead, BufReader},
ops::Neg, ops::Neg,
@ -288,8 +289,6 @@ mod vectors {
mod integrations { mod integrations {
use super::*; use super::*;
use rand::rngs::OsRng; use rand::rngs::OsRng;
#[cfg(feature = "digest")]
use sha2::Sha512;
use std::collections::HashMap; use std::collections::HashMap;
#[test] #[test]
@ -459,6 +458,29 @@ mod integrations {
assert_eq!(v, "Second public key"); assert_eq!(v, "Second public key");
assert_eq!(m.len(), 2usize); assert_eq!(m.len(), 2usize);
} }
#[test]
fn montgomery_and_edwards_conversion() {
let mut rng = rand::rngs::OsRng;
let signing_key = SigningKey::generate(&mut rng);
let verifying_key = signing_key.verifying_key();
let ed = verifying_key.to_edwards();
// Check that to_edwards and From return same result:
assert_eq!(ed, curve25519_dalek::EdwardsPoint::from(verifying_key));
// The verifying key serialization is simply the compressed Edwards point
assert_eq!(verifying_key.to_bytes(), ed.compress().0);
// Check that modulo sign, to_montgomery().to_edwards() returns the original point
let monty = verifying_key.to_montgomery();
let via_monty0 = monty.to_edwards(0).unwrap();
let via_monty1 = monty.to_edwards(1).unwrap();
assert!(via_monty0 != via_monty1);
assert!(ed == via_monty0 || ed == via_monty1);
}
} }
#[cfg(all(test, feature = "serde"))] #[cfg(all(test, feature = "serde"))]

View file

@ -22,7 +22,7 @@ const VERIFY_ALLOWED_EDGECASES: &[Flag] = &[
const VERIFY_STRICT_ALLOWED_EDGECASES: &[Flag] = const VERIFY_STRICT_ALLOWED_EDGECASES: &[Flag] =
&[Flag::LowOrderComponentA, Flag::LowOrderComponentR]; &[Flag::LowOrderComponentA, Flag::LowOrderComponentR];
/// Each variant describes a specfiic edge case that can occur in an Ed25519 signature. Refer to /// Each variant describes a specific edge case that can occur in an Ed25519 signature. Refer to
/// the test vector [README][] for more info. /// the test vector [README][] for more info.
/// ///
/// [README]: https://github.com/C2SP/CCTV/blob/5ea85644bd035c555900a2f707f7e4c31ea65ced/ed25519vectors/README.md /// [README]: https://github.com/C2SP/CCTV/blob/5ea85644bd035c555900a2f707f7e4c31ea65ced/ed25519vectors/README.md

View file

@ -6,6 +6,10 @@ Entries are listed in reverse chronological order.
* Note: All `x255919-dalek` 2.x releases are in sync with the underlying `curve25519-dalek` 4.x releases. * Note: All `x255919-dalek` 2.x releases are in sync with the underlying `curve25519-dalek` 4.x releases.
## 2.0.1
* Fix nightly SIMD build
## 2.0.0-rc.3 ## 2.0.0-rc.3
* `StaticSecret` serialization and `to_bytes()` no longer returns clamped integers. Clamping is still always done during scalar-point multiplication. * `StaticSecret` serialization and `to_bytes()` no longer returns clamped integers. Clamping is still always done during scalar-point multiplication.

View file

@ -6,7 +6,7 @@ edition = "2021"
# - 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 = "2.0.0" version = "2.0.1"
authors = [ authors = [
"Isis Lovecruft <isis@patternsinthevoid.net>", "Isis Lovecruft <isis@patternsinthevoid.net>",
"DebugSteven <debugsteven@gmail.com>", "DebugSteven <debugsteven@gmail.com>",