mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-17 01:17:36 +00:00
Add support for Ristretto
Replaces P-256 as the curve used for testing FROST.
This commit is contained in:
parent
e0ce6e5c12
commit
301634dd8e
12 changed files with 477 additions and 412 deletions
|
@ -11,7 +11,7 @@ use curve25519_dalek::{
|
||||||
|
|
||||||
use transcript::{Transcript as TranscriptTrait, DigestTranscript};
|
use transcript::{Transcript as TranscriptTrait, DigestTranscript};
|
||||||
use frost::Curve;
|
use frost::Curve;
|
||||||
pub use frost::curves::ed25519::Ed25519;
|
pub use frost::curves::dalek::Ed25519;
|
||||||
use dalek_ff_group as dfg;
|
use dalek_ff_group as dfg;
|
||||||
|
|
||||||
use crate::random_scalar;
|
use crate::random_scalar;
|
||||||
|
|
|
@ -16,88 +16,123 @@ use dalek::{
|
||||||
traits::Identity,
|
traits::Identity,
|
||||||
scalar::Scalar as DScalar,
|
scalar::Scalar as DScalar,
|
||||||
edwards::{
|
edwards::{
|
||||||
EdwardsPoint as DPoint,
|
EdwardsPoint as DEdwardsPoint,
|
||||||
EdwardsBasepointTable as DTable,
|
EdwardsBasepointTable as DEdwardsBasepointTable,
|
||||||
CompressedEdwardsY as DCompressed
|
CompressedEdwardsY as DCompressedEdwards
|
||||||
|
},
|
||||||
|
ristretto::{
|
||||||
|
RistrettoPoint as DRistrettoPoint,
|
||||||
|
RistrettoBasepointTable as DRistrettoBasepointTable,
|
||||||
|
CompressedRistretto as DCompressedRistretto
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
use group::{ff::{Field, PrimeField}, Group};
|
use group::{ff::{Field, PrimeField}, Group};
|
||||||
|
|
||||||
|
macro_rules! deref_borrow {
|
||||||
|
($Source: ident, $Target: ident) => {
|
||||||
|
impl Deref for $Source {
|
||||||
|
type Target = $Target;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Borrow<$Target> for $Source {
|
||||||
|
fn borrow(&self) -> &$Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Borrow<$Target> for &$Source {
|
||||||
|
fn borrow(&self) -> &$Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! math {
|
||||||
|
($Value: ident, $Factor: ident, $Product: ident) => {
|
||||||
|
impl Add<$Value> for $Value {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, other: $Value) -> Self::Output { Self(self.0 + other.0) }
|
||||||
|
}
|
||||||
|
impl AddAssign for $Value {
|
||||||
|
fn add_assign(&mut self, other: $Value) { self.0 += other.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<&'a $Value> for $Value {
|
||||||
|
type Output = Self;
|
||||||
|
fn add(self, other: &'a $Value) -> Self::Output { Self(self.0 + other.0) }
|
||||||
|
}
|
||||||
|
impl<'a> AddAssign<&'a $Value> for $Value {
|
||||||
|
fn add_assign(&mut self, other: &'a $Value) { self.0 += other.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<$Value> for $Value {
|
||||||
|
type Output = Self;
|
||||||
|
fn sub(self, other: $Value) -> Self::Output { Self(self.0 - other.0) }
|
||||||
|
}
|
||||||
|
impl SubAssign for $Value {
|
||||||
|
fn sub_assign(&mut self, other: $Value) { self.0 -= other.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Sub<&'a $Value> for $Value {
|
||||||
|
type Output = Self;
|
||||||
|
fn sub(self, other: &'a $Value) -> Self::Output { Self(self.0 - other.0) }
|
||||||
|
}
|
||||||
|
impl<'a> SubAssign<&'a $Value> for $Value {
|
||||||
|
fn sub_assign(&mut self, other: &'a $Value) { self.0 -= other.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for $Value {
|
||||||
|
type Output = Self;
|
||||||
|
fn neg(self) -> Self::Output { Self(-self.0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<$Factor> for $Value {
|
||||||
|
type Output = $Product;
|
||||||
|
fn mul(self, other: $Factor) -> Self::Output { Self(self.0 * other.0) }
|
||||||
|
}
|
||||||
|
impl MulAssign<$Factor> for $Value {
|
||||||
|
fn mul_assign(&mut self, other: $Factor) { self.0 *= other.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Mul<&'a $Factor> for $Value {
|
||||||
|
type Output = Self;
|
||||||
|
fn mul(self, b: &'a $Factor) -> $Product { Self(b.0 * self.0) }
|
||||||
|
}
|
||||||
|
impl<'a> MulAssign<&'a $Factor> for $Value {
|
||||||
|
fn mul_assign(&mut self, other: &'a $Factor) { self.0 *= other.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||||
pub struct Scalar(pub DScalar);
|
pub struct Scalar(pub DScalar);
|
||||||
|
deref_borrow!(Scalar, DScalar);
|
||||||
|
math!(Scalar, Scalar, Scalar);
|
||||||
|
|
||||||
impl Deref for Scalar {
|
impl Scalar {
|
||||||
type Target = DScalar;
|
pub fn from_canonical_bytes(bytes: [u8; 32]) -> Option<Scalar> {
|
||||||
|
DScalar::from_canonical_bytes(bytes).map(|x| Self(x))
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Borrow<DScalar> for Scalar {
|
pub fn from_bytes_mod_order(bytes: [u8; 32]) -> Scalar {
|
||||||
fn borrow(&self) -> &DScalar {
|
Self(DScalar::from_bytes_mod_order(bytes))
|
||||||
&self.0
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Borrow<DScalar> for &Scalar {
|
pub fn from_bytes_mod_order_wide(bytes: &[u8; 64]) -> Scalar {
|
||||||
fn borrow(&self) -> &DScalar {
|
Self(DScalar::from_bytes_mod_order_wide(bytes))
|
||||||
&self.0
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Add<Scalar> for Scalar {
|
pub fn from_hash<D: Digest<OutputSize = U64>>(hash: D) -> Scalar {
|
||||||
type Output = Self;
|
let mut output = [0u8; 64];
|
||||||
fn add(self, other: Scalar) -> Scalar { Self(self.0 + other.0) }
|
output.copy_from_slice(&hash.finalize());
|
||||||
}
|
Scalar(DScalar::from_bytes_mod_order_wide(&output))
|
||||||
impl AddAssign for Scalar {
|
}
|
||||||
fn add_assign(&mut self, other: Scalar) { self.0 += other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Add<&'a Scalar> for Scalar {
|
|
||||||
type Output = Self;
|
|
||||||
fn add(self, other: &'a Scalar) -> Scalar { Self(self.0 + other.0) }
|
|
||||||
}
|
|
||||||
impl<'a> AddAssign<&'a Scalar> for Scalar {
|
|
||||||
fn add_assign(&mut self, other: &'a Scalar) { self.0 += other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sub<Scalar> for Scalar {
|
|
||||||
type Output = Self;
|
|
||||||
fn sub(self, other: Scalar) -> Scalar { Self(self.0 - other.0) }
|
|
||||||
}
|
|
||||||
impl SubAssign for Scalar {
|
|
||||||
fn sub_assign(&mut self, other: Scalar) { self.0 -= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Sub<&'a Scalar> for Scalar {
|
|
||||||
type Output = Self;
|
|
||||||
fn sub(self, other: &'a Scalar) -> Scalar { Self(self.0 - other.0) }
|
|
||||||
}
|
|
||||||
impl<'a> SubAssign<&'a Scalar> for Scalar {
|
|
||||||
fn sub_assign(&mut self, other: &'a Scalar) { self.0 -= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Neg for Scalar {
|
|
||||||
type Output = Self;
|
|
||||||
fn neg(self) -> Scalar { Self(-self.0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul<Scalar> for Scalar {
|
|
||||||
type Output = Self;
|
|
||||||
fn mul(self, other: Scalar) -> Scalar { Self(self.0 * other.0) }
|
|
||||||
}
|
|
||||||
impl MulAssign for Scalar {
|
|
||||||
fn mul_assign(&mut self, other: Scalar) { self.0 *= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Mul<&'a Scalar> for Scalar {
|
|
||||||
type Output = Self;
|
|
||||||
fn mul(self, other: &'a Scalar) -> Scalar { Self(self.0 * other.0) }
|
|
||||||
}
|
|
||||||
impl<'a> MulAssign<&'a Scalar> for Scalar {
|
|
||||||
fn mul_assign(&mut self, other: &'a Scalar) { self.0 *= other.0 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstantTimeEq for Scalar {
|
impl ConstantTimeEq for Scalar {
|
||||||
|
@ -153,163 +188,106 @@ impl PrimeField for Scalar {
|
||||||
fn root_of_unity() -> Self { unimplemented!() }
|
fn root_of_unity() -> Self { unimplemented!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scalar {
|
macro_rules! dalek_group {
|
||||||
pub fn from_hash<D: Digest<OutputSize = U64>>(hash: D) -> Scalar {
|
(
|
||||||
let mut output = [0u8; 64];
|
$Point: ident,
|
||||||
output.copy_from_slice(&hash.finalize());
|
$DPoint: ident,
|
||||||
Scalar(DScalar::from_bytes_mod_order_wide(&output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
$Table: ident,
|
||||||
pub struct EdwardsPoint(pub DPoint);
|
$DTable: ident,
|
||||||
pub const ED25519_BASEPOINT_POINT: EdwardsPoint = EdwardsPoint(constants::ED25519_BASEPOINT_POINT);
|
|
||||||
|
|
||||||
impl Deref for EdwardsPoint {
|
$Compressed: ident,
|
||||||
type Target = DPoint;
|
$DCompressed: ident,
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
$BASEPOINT_POINT: ident,
|
||||||
&self.0
|
$BASEPOINT_TABLE: ident
|
||||||
|
) => {
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub struct $Point(pub $DPoint);
|
||||||
|
deref_borrow!($Point, $DPoint);
|
||||||
|
math!($Point, Scalar, $Point);
|
||||||
|
|
||||||
|
pub const $BASEPOINT_POINT: $Point = $Point(constants::$BASEPOINT_POINT);
|
||||||
|
|
||||||
|
impl Sum<$Point> for $Point {
|
||||||
|
fn sum<I: Iterator<Item = $Point>>(iter: I) -> $Point { Self($DPoint::sum(iter)) }
|
||||||
}
|
}
|
||||||
|
impl<'a> Sum<&'a $Point> for $Point {
|
||||||
|
fn sum<I: Iterator<Item = &'a $Point>>(iter: I) -> $Point { Self($DPoint::sum(iter)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Group for $Point {
|
||||||
|
type Scalar = Scalar;
|
||||||
|
fn random(rng: impl RngCore) -> Self { &$BASEPOINT_TABLE * Scalar::random(rng) }
|
||||||
|
fn identity() -> Self { Self($DPoint::identity()) }
|
||||||
|
fn generator() -> Self { $BASEPOINT_POINT }
|
||||||
|
fn is_identity(&self) -> Choice { self.0.ct_eq(&$DPoint::identity()) }
|
||||||
|
fn double(&self) -> Self { *self + self }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct $Compressed(pub $DCompressed);
|
||||||
|
deref_borrow!($Compressed, $DCompressed);
|
||||||
|
impl $Compressed {
|
||||||
|
pub fn new(y: [u8; 32]) -> $Compressed {
|
||||||
|
Self($DCompressed(y))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decompress(&self) -> Option<$Point> {
|
||||||
|
self.0.decompress().map(|x| $Point(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_bytes(&self) -> [u8; 32] {
|
||||||
|
self.0.to_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $Point {
|
||||||
|
pub fn compress(&self) -> $Compressed {
|
||||||
|
$Compressed(self.0.compress())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct $Table(pub $DTable);
|
||||||
|
deref_borrow!($Table, $DTable);
|
||||||
|
pub const $BASEPOINT_TABLE: $Table = $Table(constants::$BASEPOINT_TABLE);
|
||||||
|
|
||||||
|
impl Mul<Scalar> for &$Table {
|
||||||
|
type Output = $Point;
|
||||||
|
fn mul(self, b: Scalar) -> $Point { $Point(&b.0 * &self.0) }
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Borrow<DPoint> for EdwardsPoint {
|
dalek_group!(
|
||||||
fn borrow(&self) -> &DPoint {
|
EdwardsPoint,
|
||||||
&self.0
|
DEdwardsPoint,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Borrow<DPoint> for &EdwardsPoint {
|
EdwardsBasepointTable,
|
||||||
fn borrow(&self) -> &DPoint {
|
DEdwardsBasepointTable,
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add<EdwardsPoint> for EdwardsPoint {
|
CompressedEdwardsY,
|
||||||
type Output = Self;
|
DCompressedEdwards,
|
||||||
fn add(self, b: EdwardsPoint) -> EdwardsPoint { Self(self.0 + b.0) }
|
|
||||||
}
|
|
||||||
impl AddAssign<EdwardsPoint> for EdwardsPoint {
|
|
||||||
fn add_assign(&mut self, other: EdwardsPoint) { self.0 += other.0 }
|
|
||||||
}
|
|
||||||
impl Sum<EdwardsPoint> for EdwardsPoint {
|
|
||||||
fn sum<I: Iterator<Item = EdwardsPoint>>(iter: I) -> EdwardsPoint { Self(DPoint::sum(iter)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Add<&'a EdwardsPoint> for EdwardsPoint {
|
ED25519_BASEPOINT_POINT,
|
||||||
type Output = Self;
|
ED25519_BASEPOINT_TABLE
|
||||||
fn add(self, b: &'a EdwardsPoint) -> EdwardsPoint { Self(self.0 + b.0) }
|
);
|
||||||
}
|
|
||||||
impl<'a> AddAssign<&'a EdwardsPoint> for EdwardsPoint {
|
|
||||||
fn add_assign(&mut self, other: &'a EdwardsPoint) { self.0 += other.0 }
|
|
||||||
}
|
|
||||||
impl<'a> Sum<&'a EdwardsPoint> for EdwardsPoint {
|
|
||||||
fn sum<I: Iterator<Item = &'a EdwardsPoint>>(iter: I) -> EdwardsPoint { Self(DPoint::sum(iter)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sub<EdwardsPoint> for EdwardsPoint {
|
|
||||||
type Output = Self;
|
|
||||||
fn sub(self, b: EdwardsPoint) -> EdwardsPoint { Self(self.0 - b.0) }
|
|
||||||
}
|
|
||||||
impl SubAssign<EdwardsPoint> for EdwardsPoint {
|
|
||||||
fn sub_assign(&mut self, other: EdwardsPoint) { self.0 -= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Sub<&'a EdwardsPoint> for EdwardsPoint {
|
|
||||||
type Output = Self;
|
|
||||||
fn sub(self, b: &'a EdwardsPoint) -> EdwardsPoint { Self(self.0 - b.0) }
|
|
||||||
}
|
|
||||||
impl<'a> SubAssign<&'a EdwardsPoint> for EdwardsPoint {
|
|
||||||
fn sub_assign(&mut self, other: &'a EdwardsPoint) { self.0 -= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Neg for EdwardsPoint {
|
|
||||||
type Output = Self;
|
|
||||||
fn neg(self) -> EdwardsPoint { Self(-self.0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul<Scalar> for EdwardsPoint {
|
|
||||||
type Output = Self;
|
|
||||||
fn mul(self, b: Scalar) -> EdwardsPoint { Self(b.0 * self.0) }
|
|
||||||
}
|
|
||||||
impl MulAssign<Scalar> for EdwardsPoint {
|
|
||||||
fn mul_assign(&mut self, other: Scalar) { self.0 *= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Mul<&'a Scalar> for EdwardsPoint {
|
|
||||||
type Output = Self;
|
|
||||||
fn mul(self, b: &'a Scalar) -> EdwardsPoint { Self(b.0 * self.0) }
|
|
||||||
}
|
|
||||||
impl<'a> MulAssign<&'a Scalar> for EdwardsPoint {
|
|
||||||
fn mul_assign(&mut self, other: &'a Scalar) { self.0 *= other.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Group for EdwardsPoint {
|
|
||||||
type Scalar = Scalar;
|
|
||||||
fn random(rng: impl RngCore) -> Self { &ED25519_BASEPOINT_TABLE * Scalar::random(rng) }
|
|
||||||
fn identity() -> Self { Self(DPoint::identity()) }
|
|
||||||
fn generator() -> Self { ED25519_BASEPOINT_POINT }
|
|
||||||
fn is_identity(&self) -> Choice { self.0.ct_eq(&DPoint::identity()) }
|
|
||||||
fn double(&self) -> Self { *self + self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scalar {
|
|
||||||
pub fn from_canonical_bytes(bytes: [u8; 32]) -> Option<Scalar> {
|
|
||||||
DScalar::from_canonical_bytes(bytes).map(|x| Self(x))
|
|
||||||
}
|
|
||||||
pub fn from_bytes_mod_order(bytes: [u8; 32]) -> Scalar {
|
|
||||||
Self(DScalar::from_bytes_mod_order(bytes))
|
|
||||||
}
|
|
||||||
pub fn from_bytes_mod_order_wide(bytes: &[u8; 64]) -> Scalar {
|
|
||||||
Self(DScalar::from_bytes_mod_order_wide(bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CompressedEdwardsY(pub DCompressed);
|
|
||||||
impl CompressedEdwardsY {
|
|
||||||
pub fn new(y: [u8; 32]) -> CompressedEdwardsY {
|
|
||||||
Self(DCompressed(y))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decompress(&self) -> Option<EdwardsPoint> {
|
|
||||||
self.0.decompress().map(|x| EdwardsPoint(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> [u8; 32] {
|
|
||||||
self.0.to_bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EdwardsPoint {
|
impl EdwardsPoint {
|
||||||
pub fn is_torsion_free(&self) -> bool {
|
pub fn is_torsion_free(&self) -> bool {
|
||||||
self.0.is_torsion_free()
|
self.0.is_torsion_free()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compress(&self) -> CompressedEdwardsY {
|
|
||||||
CompressedEdwardsY(self.0.compress())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EdwardsBasepointTable(pub DTable);
|
dalek_group!(
|
||||||
pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = EdwardsBasepointTable(
|
RistrettoPoint,
|
||||||
constants::ED25519_BASEPOINT_TABLE
|
DRistrettoPoint,
|
||||||
|
|
||||||
|
RistrettoBasepointTable,
|
||||||
|
DRistrettoBasepointTable,
|
||||||
|
|
||||||
|
CompressedRistretto,
|
||||||
|
DCompressedRistretto,
|
||||||
|
|
||||||
|
RISTRETTO_BASEPOINT_POINT,
|
||||||
|
RISTRETTO_BASEPOINT_TABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Deref for EdwardsBasepointTable {
|
|
||||||
type Target = DTable;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Borrow<DTable> for &EdwardsBasepointTable {
|
|
||||||
fn borrow(&self) -> &DTable {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul<Scalar> for &EdwardsBasepointTable {
|
|
||||||
type Output = EdwardsPoint;
|
|
||||||
fn mul(self, b: Scalar) -> EdwardsPoint { EdwardsPoint(&b.0 * &self.0) }
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,12 +30,13 @@ multiexp = { path = "../multiexp", features = ["batch"] }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
elliptic-curve = { version = "0.12", features = ["hash2curve"] }
|
dalek-ff-group = { path = "../dalek-ff-group" }
|
||||||
p256 = { version = "0.11", features = ["arithmetic", "hash2curve"] }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
curves = []
|
curves = ["sha2"] # All officially denoted curves use the SHA2 family of hashes
|
||||||
kp256 = ["elliptic-curve"]
|
kp256 = ["elliptic-curve", "curves"]
|
||||||
p256 = ["curves", "kp256", "sha2", "dep:p256"]
|
p256 = ["dep:p256", "kp256"]
|
||||||
k256 = ["curves", "kp256", "sha2", "dep:k256"]
|
k256 = ["dep:k256", "kp256"]
|
||||||
ed25519 = ["curves", "sha2", "dalek-ff-group"]
|
dalek = ["curves", "dalek-ff-group"]
|
||||||
|
ed25519 = ["dalek"]
|
||||||
|
ristretto = ["dalek"]
|
||||||
|
|
163
crypto/frost/src/curves/dalek.rs
Normal file
163
crypto/frost/src/curves/dalek.rs
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
use core::convert::TryInto;
|
||||||
|
|
||||||
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
|
use sha2::{Digest, Sha512};
|
||||||
|
|
||||||
|
use ff::PrimeField;
|
||||||
|
use group::Group;
|
||||||
|
|
||||||
|
use dalek_ff_group::Scalar;
|
||||||
|
|
||||||
|
use crate::{CurveError, Curve, algorithm::Hram};
|
||||||
|
|
||||||
|
macro_rules! dalek_curve {
|
||||||
|
(
|
||||||
|
$Curve: ident,
|
||||||
|
$Hram: ident,
|
||||||
|
$Point: ident,
|
||||||
|
$Compressed: ident,
|
||||||
|
$Table: ident,
|
||||||
|
|
||||||
|
$POINT: ident,
|
||||||
|
$TABLE: ident,
|
||||||
|
|
||||||
|
$torsioned: expr,
|
||||||
|
|
||||||
|
$ID: literal,
|
||||||
|
$CONTEXT: literal,
|
||||||
|
$chal: literal,
|
||||||
|
$digest: literal,
|
||||||
|
) => {
|
||||||
|
use dalek_ff_group::{$Point, $Compressed, $Table, $POINT, $TABLE};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub struct $Curve;
|
||||||
|
impl Curve for $Curve {
|
||||||
|
type F = Scalar;
|
||||||
|
type G = $Point;
|
||||||
|
type T = &'static $Table;
|
||||||
|
|
||||||
|
const ID: &'static [u8] = $ID;
|
||||||
|
|
||||||
|
const GENERATOR: Self::G = $POINT;
|
||||||
|
const GENERATOR_TABLE: Self::T = &$TABLE;
|
||||||
|
|
||||||
|
const LITTLE_ENDIAN: bool = true;
|
||||||
|
|
||||||
|
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
|
||||||
|
let mut seed = vec![0; 32];
|
||||||
|
rng.fill_bytes(&mut seed);
|
||||||
|
seed.extend(&secret.to_bytes());
|
||||||
|
Self::hash_to_F(b"nonce", &seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash_msg(msg: &[u8]) -> Vec<u8> {
|
||||||
|
Sha512::new()
|
||||||
|
.chain_update($CONTEXT)
|
||||||
|
.chain_update($digest)
|
||||||
|
.chain_update(msg)
|
||||||
|
.finalize()
|
||||||
|
.to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash_binding_factor(binding: &[u8]) -> Self::F {
|
||||||
|
Self::hash_to_F(b"rho", binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F {
|
||||||
|
Scalar::from_hash(Sha512::new().chain_update($CONTEXT).chain_update(dst).chain_update(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn F_len() -> usize {
|
||||||
|
32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn G_len() -> usize {
|
||||||
|
32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn F_from_slice(slice: &[u8]) -> Result<Self::F, CurveError> {
|
||||||
|
let scalar = Self::F::from_repr(
|
||||||
|
slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
||||||
|
);
|
||||||
|
if scalar.is_some().unwrap_u8() == 0 {
|
||||||
|
Err(CurveError::InvalidScalar)?;
|
||||||
|
}
|
||||||
|
Ok(scalar.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn G_from_slice(slice: &[u8]) -> Result<Self::G, CurveError> {
|
||||||
|
let bytes = slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?;
|
||||||
|
let point = $Compressed::new(bytes).decompress();
|
||||||
|
|
||||||
|
if let Some(point) = point {
|
||||||
|
// Ban identity
|
||||||
|
if point.is_identity().into() {
|
||||||
|
Err(CurveError::InvalidPoint)?;
|
||||||
|
}
|
||||||
|
// Ban torsioned points to meet the prime order group requirement
|
||||||
|
if $torsioned(point) {
|
||||||
|
Err(CurveError::InvalidPoint)?;
|
||||||
|
}
|
||||||
|
// Ban points which weren't canonically encoded
|
||||||
|
if point.compress().to_bytes() != bytes {
|
||||||
|
Err(CurveError::InvalidPoint)?;
|
||||||
|
}
|
||||||
|
Ok(point)
|
||||||
|
} else {
|
||||||
|
Err(CurveError::InvalidPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn F_to_bytes(f: &Self::F) -> Vec<u8> {
|
||||||
|
f.to_repr().to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn G_to_bytes(g: &Self::G) -> Vec<u8> {
|
||||||
|
g.compress().to_bytes().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct $Hram;
|
||||||
|
impl Hram<$Curve> for $Hram {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn hram(R: &$Point, A: &$Point, m: &[u8]) -> Scalar {
|
||||||
|
$Curve::hash_to_F($chal, &[&R.compress().to_bytes(), &A.compress().to_bytes(), m].concat())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ed25519")]
|
||||||
|
dalek_curve!(
|
||||||
|
Ed25519,
|
||||||
|
IetfEd25519Hram,
|
||||||
|
EdwardsPoint,
|
||||||
|
CompressedEdwardsY,
|
||||||
|
EdwardsBasepointTable,
|
||||||
|
ED25519_BASEPOINT_POINT,
|
||||||
|
ED25519_BASEPOINT_TABLE,
|
||||||
|
|point: EdwardsPoint| !bool::from(point.is_torsion_free()),
|
||||||
|
b"edwards25519",
|
||||||
|
b"",
|
||||||
|
b"",
|
||||||
|
b"",
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "ristretto"))]
|
||||||
|
dalek_curve!(
|
||||||
|
Ristretto,
|
||||||
|
IetfRistrettoHram,
|
||||||
|
RistrettoPoint,
|
||||||
|
CompressedRistretto,
|
||||||
|
RistrettoBasepointTable,
|
||||||
|
RISTRETTO_BASEPOINT_POINT,
|
||||||
|
RISTRETTO_BASEPOINT_TABLE,
|
||||||
|
|_| false,
|
||||||
|
b"ristretto",
|
||||||
|
b"FROST-RISTRETTO255-SHA512-v5",
|
||||||
|
b"chal",
|
||||||
|
b"digest",
|
||||||
|
);
|
|
@ -1,104 +0,0 @@
|
||||||
use core::convert::TryInto;
|
|
||||||
|
|
||||||
use rand_core::{RngCore, CryptoRng};
|
|
||||||
|
|
||||||
use sha2::{Digest, Sha512};
|
|
||||||
|
|
||||||
use ff::PrimeField;
|
|
||||||
use group::Group;
|
|
||||||
|
|
||||||
use dalek_ff_group::{
|
|
||||||
EdwardsBasepointTable,
|
|
||||||
ED25519_BASEPOINT_POINT, ED25519_BASEPOINT_TABLE,
|
|
||||||
Scalar, EdwardsPoint, CompressedEdwardsY
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{CurveError, Curve, algorithm::Hram};
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Ed25519;
|
|
||||||
impl Curve for Ed25519 {
|
|
||||||
type F = Scalar;
|
|
||||||
type G = EdwardsPoint;
|
|
||||||
type T = &'static EdwardsBasepointTable;
|
|
||||||
|
|
||||||
const ID: &'static [u8] = b"edwards25519";
|
|
||||||
|
|
||||||
const GENERATOR: Self::G = ED25519_BASEPOINT_POINT;
|
|
||||||
const GENERATOR_TABLE: Self::T = &ED25519_BASEPOINT_TABLE;
|
|
||||||
|
|
||||||
const LITTLE_ENDIAN: bool = true;
|
|
||||||
|
|
||||||
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
|
|
||||||
let mut seed = vec![0; 32];
|
|
||||||
rng.fill_bytes(&mut seed);
|
|
||||||
seed.extend(&secret.to_bytes());
|
|
||||||
Self::hash_to_F(b"nonce", &seed)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_msg(msg: &[u8]) -> Vec<u8> {
|
|
||||||
Sha512::digest(msg).to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_binding_factor(binding: &[u8]) -> Self::F {
|
|
||||||
Self::hash_to_F(b"rho", binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F {
|
|
||||||
Scalar::from_hash(Sha512::new().chain_update(dst).chain_update(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn F_len() -> usize {
|
|
||||||
32
|
|
||||||
}
|
|
||||||
|
|
||||||
fn G_len() -> usize {
|
|
||||||
32
|
|
||||||
}
|
|
||||||
|
|
||||||
fn F_from_slice(slice: &[u8]) -> Result<Self::F, CurveError> {
|
|
||||||
let scalar = Self::F::from_repr(
|
|
||||||
slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
|
||||||
);
|
|
||||||
if scalar.is_some().unwrap_u8() == 0 {
|
|
||||||
Err(CurveError::InvalidScalar)?;
|
|
||||||
}
|
|
||||||
Ok(scalar.unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn G_from_slice(slice: &[u8]) -> Result<Self::G, CurveError> {
|
|
||||||
let bytes = slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?;
|
|
||||||
let point = CompressedEdwardsY::new(bytes).decompress();
|
|
||||||
|
|
||||||
if let Some(point) = point {
|
|
||||||
// Ban identity and torsioned points
|
|
||||||
if point.is_identity().into() || (!bool::from(point.is_torsion_free())) {
|
|
||||||
Err(CurveError::InvalidPoint)?;
|
|
||||||
}
|
|
||||||
// Ban points which weren't canonically encoded
|
|
||||||
if point.compress().to_bytes() != bytes {
|
|
||||||
Err(CurveError::InvalidPoint)?;
|
|
||||||
}
|
|
||||||
Ok(point)
|
|
||||||
} else {
|
|
||||||
Err(CurveError::InvalidPoint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn F_to_bytes(f: &Self::F) -> Vec<u8> {
|
|
||||||
f.to_repr().to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn G_to_bytes(g: &Self::G) -> Vec<u8> {
|
|
||||||
g.compress().to_bytes().to_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct IetfEd25519Hram;
|
|
||||||
impl Hram<Ed25519> for IetfEd25519Hram {
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn hram(R: &EdwardsPoint, A: &EdwardsPoint, m: &[u8]) -> Scalar {
|
|
||||||
Ed25519::hash_to_F(b"", &[&R.compress().to_bytes(), &A.compress().to_bytes(), m].concat())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ use group::{Group, GroupEncoding};
|
||||||
use elliptic_curve::{bigint::{Encoding, U384}, hash2curve::{Expander, ExpandMsg, ExpandMsgXmd}};
|
use elliptic_curve::{bigint::{Encoding, U384}, hash2curve::{Expander, ExpandMsg, ExpandMsgXmd}};
|
||||||
|
|
||||||
use crate::{CurveError, Curve};
|
use crate::{CurveError, Curve};
|
||||||
#[cfg(any(test, feature = "p256"))]
|
#[cfg(feature = "p256")]
|
||||||
use crate::algorithm::Hram;
|
use crate::algorithm::Hram;
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
@ -25,9 +25,9 @@ pub(crate) trait KP256Instance<G> {
|
||||||
const GENERATOR: G;
|
const GENERATOR: G;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "p256"))]
|
#[cfg(feature = "p256")]
|
||||||
pub type P256 = KP256<p256::ProjectivePoint>;
|
pub type P256 = KP256<p256::ProjectivePoint>;
|
||||||
#[cfg(any(test, feature = "p256"))]
|
#[cfg(feature = "p256")]
|
||||||
impl KP256Instance<p256::ProjectivePoint> for P256 {
|
impl KP256Instance<p256::ProjectivePoint> for P256 {
|
||||||
const CONTEXT: &'static [u8] = b"FROST-P256-SHA256-v5";
|
const CONTEXT: &'static [u8] = b"FROST-P256-SHA256-v5";
|
||||||
const ID: &'static [u8] = b"P-256";
|
const ID: &'static [u8] = b"P-256";
|
||||||
|
@ -139,10 +139,10 @@ impl<G: Group + GroupEncoding> Curve for KP256<G> where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "p256"))]
|
#[cfg(feature = "p256")]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct IetfP256Hram;
|
pub struct IetfP256Hram;
|
||||||
#[cfg(any(test, feature = "p256"))]
|
#[cfg(feature = "p256")]
|
||||||
impl Hram<P256> for IetfP256Hram {
|
impl Hram<P256> for IetfP256Hram {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn hram(R: &p256::ProjectivePoint, A: &p256::ProjectivePoint, m: &[u8]) -> p256::Scalar {
|
fn hram(R: &p256::ProjectivePoint, A: &p256::ProjectivePoint, m: &[u8]) -> p256::Scalar {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#[cfg(any(test, feature = "kp256"))]
|
#[cfg(any(test, feature = "dalek"))]
|
||||||
pub mod kp256;
|
pub mod dalek;
|
||||||
|
|
||||||
#[cfg(feature = "ed25519")]
|
#[cfg(feature = "kp256")]
|
||||||
pub mod ed25519;
|
pub mod kp256;
|
||||||
|
|
77
crypto/frost/src/tests/literal/dalek.rs
Normal file
77
crypto/frost/src/tests/literal/dalek.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
|
use crate::{curves::dalek, tests::vectors::{Vectors, test_with_vectors}};
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "ristretto"))]
|
||||||
|
#[test]
|
||||||
|
fn ristretto_vectors() {
|
||||||
|
test_with_vectors::<_, dalek::Ristretto, dalek::IetfRistrettoHram>(
|
||||||
|
&mut OsRng,
|
||||||
|
Vectors {
|
||||||
|
threshold: 2,
|
||||||
|
shares: &[
|
||||||
|
"5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e",
|
||||||
|
"b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01",
|
||||||
|
"f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04"
|
||||||
|
],
|
||||||
|
group_secret: "1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab265f2ebc4f970b",
|
||||||
|
group_key: "e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d05083c7254f57",
|
||||||
|
|
||||||
|
msg: "74657374",
|
||||||
|
included: &[1, 3],
|
||||||
|
nonces: &[
|
||||||
|
[
|
||||||
|
"b358743151e33d84bf00c12f71808f4103957c3e2cabab7b895c436b5e70f90c",
|
||||||
|
"7bd112153b9ae1ab9b31f5e78f61f5c4ca9ee67b7ea6d1181799c409d14c350c"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"22acad88478e0d0373a991092a322ebd1b9a2dad90451a976d0db3215426af0e",
|
||||||
|
"9155e3d7bcf7cd468b980c7e20b2c77cbdfbe33a1dcae031fd8bc6b1403f4b04"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
sig_shares: &[
|
||||||
|
"ff801b4e0839faa67f16dee4127b9f7fbcf5fd007900257b0e2bbc02cbe5e709",
|
||||||
|
"afdf5481023c855bf3411a5c8a5fafa92357296a078c3b80dc168f294cb4f504"
|
||||||
|
],
|
||||||
|
sig: "deae61af10e8ee48ba492573592fba547f5debeff6bd6e2024e8673584746f5e".to_owned() +
|
||||||
|
"ae6070cf0a757f027358f8409dda4e29e04c276b808c60fbea414b2c179add0e"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ed25519")]
|
||||||
|
#[test]
|
||||||
|
fn ed25519_vectors() {
|
||||||
|
test_with_vectors::<_, dalek::Ed25519, dalek::IetfEd25519Hram>(
|
||||||
|
&mut OsRng,
|
||||||
|
Vectors {
|
||||||
|
threshold: 2,
|
||||||
|
shares: &[
|
||||||
|
"929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509",
|
||||||
|
"a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d",
|
||||||
|
"d3cb090a075eb154e82fdb4b3cb507f110040905468bb9c46da8bdea643a9a02"
|
||||||
|
],
|
||||||
|
group_secret: "7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a790c6e13a98304",
|
||||||
|
group_key: "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673",
|
||||||
|
|
||||||
|
msg: "74657374",
|
||||||
|
included: &[1, 3],
|
||||||
|
nonces: &[
|
||||||
|
[
|
||||||
|
"8c76af04340e83bb5fc427c117d38347fc8ef86d5397feea9aa6412d96c05b0a",
|
||||||
|
"14a37ddbeae8d9e9687369e5eb3c6d54f03dc19d76bb54fb5425131bc37a600b"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"5ca39ebab6874f5e7b5089f3521819a2aa1e2cf738bae6974ee80555de2ef70e",
|
||||||
|
"0afe3650c4815ff37becd3c6948066e906e929ea9b8f546c74e10002dbcc150c"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
sig_shares: &[
|
||||||
|
"4369474a398aa10357b60d683da91ea6a767dcf53fd541a8ed6b4d780827ea0a",
|
||||||
|
"32fcc690d926075e45d2dfb746bab71447943cddbefe80d122c39174aa2e1004"
|
||||||
|
],
|
||||||
|
sig: "2b8d9c6995333c5990e3a3dd6568785539d3322f7f0376452487ea35cfda587b".to_owned() +
|
||||||
|
"75650edb12b1a8619c88ed1f8463d6baeefb18d3fed3c279102fdfecb255fa0e"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
use rand::rngs::OsRng;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
curves::ed25519::{Ed25519, IetfEd25519Hram},
|
|
||||||
tests::{curve::test_curve, schnorr::test_schnorr, vectors::{Vectors, vectors}}
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ed25519_curve() {
|
|
||||||
test_curve::<_, Ed25519>(&mut OsRng);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ed25519_schnorr() {
|
|
||||||
test_schnorr::<_, Ed25519>(&mut OsRng);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ed25519_vectors() {
|
|
||||||
vectors::<Ed25519, IetfEd25519Hram>(
|
|
||||||
Vectors {
|
|
||||||
threshold: 2,
|
|
||||||
shares: &[
|
|
||||||
"929dcc590407aae7d388761cddb0c0db6f5627aea8e217f4a033f2ec83d93509",
|
|
||||||
"a91e66e012e4364ac9aaa405fcafd370402d9859f7b6685c07eed76bf409e80d",
|
|
||||||
"d3cb090a075eb154e82fdb4b3cb507f110040905468bb9c46da8bdea643a9a02"
|
|
||||||
],
|
|
||||||
group_secret: "7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a790c6e13a98304",
|
|
||||||
group_key: "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673",
|
|
||||||
|
|
||||||
msg: "74657374",
|
|
||||||
included: &[1, 3],
|
|
||||||
nonces: &[
|
|
||||||
[
|
|
||||||
"8c76af04340e83bb5fc427c117d38347fc8ef86d5397feea9aa6412d96c05b0a",
|
|
||||||
"14a37ddbeae8d9e9687369e5eb3c6d54f03dc19d76bb54fb5425131bc37a600b"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"5ca39ebab6874f5e7b5089f3521819a2aa1e2cf738bae6974ee80555de2ef70e",
|
|
||||||
"0afe3650c4815ff37becd3c6948066e906e929ea9b8f546c74e10002dbcc150c"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
sig_shares: &[
|
|
||||||
"4369474a398aa10357b60d683da91ea6a767dcf53fd541a8ed6b4d780827ea0a",
|
|
||||||
"32fcc690d926075e45d2dfb746bab71447943cddbefe80d122c39174aa2e1004"
|
|
||||||
],
|
|
||||||
sig: "2b8d9c6995333c5990e3a3dd6568785539d3322f7f0376452487ea35cfda587b".to_owned() +
|
|
||||||
"75650edb12b1a8619c88ed1f8463d6baeefb18d3fed3c279102fdfecb255fa0e"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,26 +1,27 @@
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
use crate::{
|
#[cfg(feature = "k256")]
|
||||||
curves::kp256::{P256, IetfP256Hram},
|
use crate::tests::{curve::test_curve, schnorr::test_schnorr};
|
||||||
tests::{curve::test_curve, schnorr::test_schnorr, vectors::{Vectors, vectors}}
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "k256")]
|
#[cfg(feature = "k256")]
|
||||||
use crate::curves::kp256::K256;
|
use crate::curves::kp256::K256;
|
||||||
|
|
||||||
|
#[cfg(feature = "p256")]
|
||||||
|
use crate::tests::vectors::{Vectors, test_with_vectors};
|
||||||
|
#[cfg(feature = "p256")]
|
||||||
|
use crate::curves::kp256::{P256, IetfP256Hram};
|
||||||
|
|
||||||
|
#[cfg(feature = "k256")]
|
||||||
#[test]
|
#[test]
|
||||||
fn p256_curve() {
|
fn k256_not_ietf() {
|
||||||
test_curve::<_, P256>(&mut OsRng);
|
test_curve::<_, K256>(&mut OsRng);
|
||||||
}
|
test_schnorr::<_, K256>(&mut OsRng);
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn p256_schnorr() {
|
|
||||||
test_schnorr::<_, P256>(&mut OsRng);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "p256")]
|
||||||
#[test]
|
#[test]
|
||||||
fn p256_vectors() {
|
fn p256_vectors() {
|
||||||
vectors::<P256, IetfP256Hram>(
|
test_with_vectors::<_, P256, IetfP256Hram>(
|
||||||
|
&mut OsRng,
|
||||||
Vectors {
|
Vectors {
|
||||||
threshold: 2,
|
threshold: 2,
|
||||||
shares: &[
|
shares: &[
|
||||||
|
@ -52,15 +53,3 @@ fn p256_vectors() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "k256")]
|
|
||||||
#[test]
|
|
||||||
fn k256_curve() {
|
|
||||||
test_curve::<_, K256>(&mut OsRng);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "k256")]
|
|
||||||
#[test]
|
|
||||||
fn k256_schnorr() {
|
|
||||||
test_schnorr::<_, K256>(&mut OsRng);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[cfg(any(test, feature = "dalek"))]
|
||||||
|
mod dalek;
|
||||||
|
#[cfg(feature = "kp256")]
|
||||||
mod kp256;
|
mod kp256;
|
||||||
#[cfg(feature = "ed25519")]
|
|
||||||
mod ed25519;
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use std::{sync::Arc, collections::HashMap};
|
use std::{sync::Arc, collections::HashMap};
|
||||||
|
|
||||||
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Curve, MultisigKeys,
|
Curve, MultisigKeys,
|
||||||
algorithm::{Schnorr, Hram},
|
algorithm::{Schnorr, Hram},
|
||||||
sign::{PreprocessPackage, StateMachine, AlgorithmMachine},
|
sign::{PreprocessPackage, StateMachine, AlgorithmMachine},
|
||||||
tests::recover
|
tests::{curve::test_curve, schnorr::test_schnorr, recover}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Vectors {
|
pub struct Vectors {
|
||||||
|
@ -55,7 +57,16 @@ fn vectors_to_multisig_keys<C: Curve>(vectors: &Vectors) -> HashMap<u16, Multisi
|
||||||
keys
|
keys
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vectors<C: Curve, H: Hram<C>>(vectors: Vectors) {
|
pub fn test_with_vectors<
|
||||||
|
R: RngCore + CryptoRng,
|
||||||
|
C: Curve,
|
||||||
|
H: Hram<C>
|
||||||
|
>(rng: &mut R, vectors: Vectors) {
|
||||||
|
// Do basic tests before trying the vectors
|
||||||
|
test_curve::<_, C>(&mut *rng);
|
||||||
|
test_schnorr::<_, C>(rng);
|
||||||
|
|
||||||
|
// Test against the vectors
|
||||||
let keys = vectors_to_multisig_keys::<C>(&vectors);
|
let keys = vectors_to_multisig_keys::<C>(&vectors);
|
||||||
let group_key = C::G_from_slice(&hex::decode(vectors.group_key).unwrap()).unwrap();
|
let group_key = C::G_from_slice(&hex::decode(vectors.group_key).unwrap()).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in a new issue