Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions ed448-goldilocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,27 @@ It is intended to be portable, fast, and safe.
## Usage

```rust
use ed448_goldilocks::{Ed448, EdwardsPoint, CompressedEdwardsY, EdwardsScalar, sha3::Shake256};
use ed448_goldilocks::{Ed448, EdwardsPoint, CompressedEdwardsY, Scalar, sha3::Shake256};
use elliptic_curve::consts::U84;
use elliptic_curve::Field;
use elliptic_curve::group::GroupEncoding;
use hash2curve::{ExpandMsgXof, GroupDigest};
use rand_core::OsRng;

let secret_key = EdwardsScalar::TWO;
let secret_key = Scalar::TWO;
let public_key = EdwardsPoint::GENERATOR * &secret_key;

assert_eq!(public_key, EdwardsPoint::GENERATOR + EdwardsPoint::GENERATOR);

let secret_key = EdwardsScalar::try_from_rng(&mut OsRng).unwrap();
let secret_key = Scalar::try_from_rng(&mut OsRng).unwrap();
let public_key = EdwardsPoint::GENERATOR * &secret_key;
let compressed_public_key = public_key.to_bytes();

assert_eq!(compressed_public_key.len(), 57);

let hashed_scalar = hash2curve::hash_to_scalar::<Ed448, <Ed448 as GroupDigest>::ExpandMsg, U84>(&[b"test"], &[b"test DST"]).unwrap();
let input = hex_literal::hex!("8108d09ce4ea5707d44a6e52d75f290d0a0801cd5e366b9a0e6f72c75246ea5042963192c01703749adb0f5a4b1ab0586ccc6cf58cfd6d0e00");
let expected_scalar = EdwardsScalar::from_canonical_bytes(&input.into()).unwrap();
let input = hex_literal::hex!("8108d09ce4ea5707d44a6e52d75f290d0a0801cd5e366b9a0e6f72c75246ea5042963192c01703749adb0f5a4b1ab0586ccc6cf58cfd6d0e");
let expected_scalar = Scalar::from_canonical_bytes(&input.into()).unwrap();
assert_eq!(hashed_scalar, expected_scalar);

let hashed_point = Ed448::hash_from_bytes(b"test", b"test DST").unwrap();
Expand Down
10 changes: 4 additions & 6 deletions ed448-goldilocks/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
use ed448_goldilocks::{
Decaf448, DecafPoint, DecafScalar, Ed448, EdwardsPoint, EdwardsScalar, MontgomeryPoint,
};
use ed448_goldilocks::{Decaf448, DecafPoint, Ed448, EdwardsPoint, MontgomeryPoint, Scalar};
use elliptic_curve::group::GroupEncoding;
use elliptic_curve::{Field, Group};
use hash2curve::GroupDigest;
Expand All @@ -14,7 +12,7 @@ pub fn ed448(c: &mut Criterion) {
b.iter_batched(
|| {
let point = EdwardsPoint::try_from_rng(&mut OsRng).unwrap();
let scalar = EdwardsScalar::try_from_rng(&mut OsRng).unwrap();
let scalar = Scalar::try_from_rng(&mut OsRng).unwrap();
(point, scalar)
},
|(point, scalar)| point * scalar,
Expand Down Expand Up @@ -72,7 +70,7 @@ pub fn decaf448(c: &mut Criterion) {
b.iter_batched(
|| {
let point = DecafPoint::try_from_rng(&mut OsRng).unwrap();
let scalar = DecafScalar::try_from_rng(&mut OsRng).unwrap();
let scalar = Scalar::try_from_rng(&mut OsRng).unwrap();
(point, scalar)
},
|(point, scalar)| point * scalar,
Expand Down Expand Up @@ -131,7 +129,7 @@ pub fn x448(c: &mut Criterion) {
|| {
let mut point = MontgomeryPoint::default();
OsRng.try_fill_bytes(&mut point.0).unwrap();
let scalar = EdwardsScalar::try_from_rng(&mut OsRng).unwrap();
let scalar = Scalar::try_from_rng(&mut OsRng).unwrap();
(point, scalar)
},
|(point, scalar)| &point * &scalar,
Expand Down
11 changes: 6 additions & 5 deletions ed448-goldilocks/src/curve/scalar_mul/variable_base.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#![allow(non_snake_case)]

use super::window::wnaf::LookupTable;
use crate::EdwardsScalar;
use crate::Scalar;
use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
use subtle::{Choice, ConditionallyNegatable};

pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtensiblePoint {
pub fn variable_base(point: &ExtendedPoint, s: &Scalar) -> ExtensiblePoint {
let mut result = ExtensiblePoint::IDENTITY;

// Recode Scalar
Expand Down Expand Up @@ -40,12 +40,13 @@ mod test {
use crate::TWISTED_EDWARDS_BASE_POINT;
use crate::curve::scalar_mul::double_and_add;
use elliptic_curve::bigint::U448;
use elliptic_curve::scalar::FromUintUnchecked;

#[test]
fn test_scalar_mul() {
// XXX: In the future use known multiples from Sage in bytes form?
let twisted_point = TWISTED_EDWARDS_BASE_POINT;
let scalar = EdwardsScalar::new(U448::from_be_hex(
let scalar = Scalar::from_uint_unchecked(U448::from_be_hex(
"05ca185aee2e1b73def437f63c003777083f83043fe5bf1aab454c66b64629d1de8026c1307f665ead0b70151533427ce128ae786ee372b7",
));

Expand All @@ -66,11 +67,11 @@ mod test {
let x = TWISTED_EDWARDS_BASE_POINT;

// Test that 1 * P = P
let exp = variable_base(&x, &EdwardsScalar::from(1u8));
let exp = variable_base(&x, &Scalar::from(1u8));
assert!(x == exp);
// Test that 2 * (P + P) = 4 * P
let expected_two_x = x.add_extended(&x).double();
let got = variable_base(&x, &EdwardsScalar::from(4u8));
let got = variable_base(&x, &Scalar::from(4u8));
assert!(expected_two_x == got);
}
}
2 changes: 0 additions & 2 deletions ed448-goldilocks/src/decaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
pub mod affine;
mod ops;
pub mod points;
mod scalar;

pub use affine::AffinePoint;
pub use points::{CompressedDecaf, DecafPoint};
pub use scalar::{DecafScalar, DecafScalarBytes, WideDecafScalarBytes};

// https://www.rfc-editor.org/rfc/rfc9496#name-group-elements-from-uniform-
#[test]
Expand Down
12 changes: 7 additions & 5 deletions ed448-goldilocks/src/decaf/affine.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::curve::twedwards::affine::AffinePoint as InnerAffinePoint;
use crate::field::FieldElement;
use crate::{Decaf448FieldBytes, DecafPoint, DecafScalar, ORDER};
use crate::{Decaf448FieldBytes, DecafPoint, ORDER, Scalar};
use core::ops::Mul;
use elliptic_curve::scalar::FromUintUnchecked;
use elliptic_curve::{
Error,
point::{AffineCoordinates, NonIdentity},
Expand Down Expand Up @@ -47,7 +48,8 @@ impl AffineCoordinates for AffinePoint {

CtOption::new(
point,
point.0.is_on_curve() & (point * DecafScalar::new(*ORDER)).ct_eq(&DecafPoint::IDENTITY),
point.0.is_on_curve()
& (point * Scalar::from_uint_unchecked(*ORDER)).ct_eq(&DecafPoint::IDENTITY),
)
}

Expand Down Expand Up @@ -105,13 +107,13 @@ impl From<NonIdentity<AffinePoint>> for AffinePoint {
}
}

impl Mul<&DecafScalar> for &AffinePoint {
impl Mul<&Scalar> for &AffinePoint {
type Output = DecafPoint;

#[inline]
fn mul(self, scalar: &DecafScalar) -> DecafPoint {
fn mul(self, scalar: &Scalar) -> DecafPoint {
self.to_decaf() * scalar
}
}

define_mul_variants!(LHS = AffinePoint, RHS = DecafScalar, Output = DecafPoint);
define_mul_variants!(LHS = AffinePoint, RHS = Scalar, Output = DecafPoint);
20 changes: 11 additions & 9 deletions ed448-goldilocks/src/decaf/ops.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
use crate::{DecafAffinePoint, DecafScalar, curve::scalar_mul::double_and_add};
use crate::{Decaf448, DecafAffinePoint, Scalar, curve::scalar_mul::double_and_add};
use core::{
borrow::Borrow,
iter::Sum,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use elliptic_curve::CurveGroup;
use elliptic_curve::{CurveGroup, scalar::FromUintUnchecked};

use super::DecafPoint;

elliptic_curve::scalar_impls!(Decaf448, Scalar);

/// Scalar Mul Operations
impl Mul<&DecafScalar> for &DecafPoint {
impl Mul<&Scalar> for &DecafPoint {
type Output = DecafPoint;

fn mul(self, scalar: &DecafScalar) -> DecafPoint {
fn mul(self, scalar: &Scalar) -> DecafPoint {
// XXX: We can do better than double and add
DecafPoint(double_and_add(&self.0, scalar.bits()).to_extended())
}
}

define_mul_variants!(LHS = DecafPoint, RHS = DecafScalar, Output = DecafPoint);
define_mul_variants!(LHS = DecafPoint, RHS = Scalar, Output = DecafPoint);

impl<'s> MulAssign<&'s DecafScalar> for DecafPoint {
fn mul_assign(&mut self, scalar: &'s DecafScalar) {
impl<'s> MulAssign<&'s Scalar> for DecafPoint {
fn mul_assign(&mut self, scalar: &'s Scalar) {
*self = *self * scalar;
}
}
impl MulAssign<DecafScalar> for DecafPoint {
fn mul_assign(&mut self, scalar: DecafScalar) {
impl MulAssign<Scalar> for DecafPoint {
fn mul_assign(&mut self, scalar: Scalar) {
*self = *self * scalar;
}
}
Expand Down
75 changes: 72 additions & 3 deletions ed448-goldilocks/src/decaf/points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl TryFrom<&DecafPointBytes> for DecafPoint {
}

impl Group for DecafPoint {
type Scalar = DecafScalar;
type Scalar = Scalar;

fn try_from_rng<R>(rng: &mut R) -> Result<Self, R::Error>
where
Expand Down Expand Up @@ -239,9 +239,9 @@ impl CofactorGroup for DecafPoint {

impl PrimeGroup for DecafPoint {}

impl<const N: usize> LinearCombination<[(DecafPoint, DecafScalar); N]> for DecafPoint {}
impl<const N: usize> LinearCombination<[(DecafPoint, Scalar); N]> for DecafPoint {}

impl LinearCombination<[(DecafPoint, DecafScalar)]> for DecafPoint {}
impl LinearCombination<[(DecafPoint, Scalar)]> for DecafPoint {}

impl CurveGroup for DecafPoint {
type AffineRepr = DecafAffinePoint;
Expand Down Expand Up @@ -599,7 +599,10 @@ impl From<NonIdentity<DecafPoint>> for DecafPoint {
mod test {
use super::*;
use crate::TWISTED_EDWARDS_BASE_POINT;
use elliptic_curve::PrimeField;
use elliptic_curve::consts::U64;
use hash2curve::ExpandMsgXof;
use hex_literal::hex;
use sha3::Shake256;

#[test]
Expand Down Expand Up @@ -761,6 +764,72 @@ mod test {
assert_ne!(point, DecafPoint::GENERATOR);
}

#[test]
fn scalar_hash() {
let msg = b"hello world";
let dst = b"decaf448_XOF:SHAKE256_D448MAP_RO_";
let res =
hash2curve::hash_to_scalar::<Decaf448, ExpandMsgXof<Shake256>, U64>(&[msg], &[dst])
.unwrap();
let expected: [u8; 56] = hex_literal::hex!(
"55e7b59aa035db959409c6b69b817a18c8133d9ad06687665f5720672924da0a84eab7fee415ef13e7aaebdd227291ee8e156f32c507ad2e"
);
assert_eq!(res.to_repr(), Array::from(expected));
}

/// Taken from <https://www.rfc-editor.org/rfc/rfc9497.html#name-decaf448-shake256>.
#[test]
fn hash_to_scalar_voprf() {
struct TestVector {
dst: &'static [u8],
sk_sm: &'static [u8],
}

const KEY_INFO: &[u8] = b"test key";
const SEED: &[u8] =
&hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3");

const TEST_VECTORS: &[TestVector] = &[
TestVector {
dst: b"DeriveKeyPairOPRFV1-\x00-decaf448-SHAKE256",
sk_sm: &hex!(
"e8b1375371fd11ebeb224f832dcc16d371b4188951c438f751425699ed29ecc80c6c13e558ccd67634fd82eac94aa8d1f0d7fee990695d1e"
),
},
TestVector {
dst: b"DeriveKeyPairOPRFV1-\x01-decaf448-SHAKE256",
sk_sm: &hex!(
"e3c01519a076a326a0eb566343e9b21c115fa18e6e85577ddbe890b33104fcc2835ddfb14a928dc3f5d79b936e17c76b99e0bf6a1680930e"
),
},
TestVector {
dst: b"DeriveKeyPairOPRFV1-\x02-decaf448-SHAKE256",
sk_sm: &hex!(
"792a10dcbd3ba4a52a054f6f39186623208695301e7adb9634b74709ab22de402990eb143fd7c67ac66be75e0609705ecea800992aac8e19"
),
},
];

let key_info_len = u16::try_from(KEY_INFO.len()).unwrap().to_be_bytes();

'outer: for test_vector in TEST_VECTORS {
for counter in 0_u8..=u8::MAX {
let scalar = hash2curve::hash_to_scalar::<Decaf448, ExpandMsgXof<Shake256>, U64>(
&[SEED, &key_info_len, KEY_INFO, &counter.to_be_bytes()],
&[test_vector.dst],
)
.unwrap();

if !bool::from(scalar.is_zero()) {
assert_eq!(scalar.to_bytes().as_slice(), test_vector.sk_sm);
continue 'outer;
}
}

panic!("deriving key failed");
}
}

// TODO: uncomment once elliptic-curve-tools is updated to match elliptic-curve 0.14
// #[test]
// fn test_sum_of_products() { use elliptic_curve_tools::SumOfProducts; let values = [ (Scalar::from(8u8), DecafPoint::GENERATOR), (Scalar::from(9u8), DecafPoint::GENERATOR), (Scalar::from(10u8), DecafPoint::GENERATOR), (Scalar::from(11u8), DecafPoint::GENERATOR), (Scalar::from(12u8), DecafPoint::GENERATOR), ]; let expected = DecafPoint::GENERATOR * Scalar::from(50u8); let result = DecafPoint::sum_of_products(&values); assert_eq!(result, expected); }
Expand Down
Loading