mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-10 05:09:22 +00:00
Move FROST to Read
Fixes https://github.com/serai-dex/serai/issues/33 and https://github.com/serai-dex/serai/issues/35. Also fixes a few potential panics/DoS AFAICT.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use sha2::{digest::Update, Digest, Sha256};
|
||||
@@ -6,7 +8,7 @@ use group::{ff::Field, GroupEncoding};
|
||||
|
||||
use elliptic_curve::{bigint::{Encoding, U384}, hash2curve::{Expander, ExpandMsg, ExpandMsgXmd}};
|
||||
|
||||
use crate::{curve::{Curve, F_from_slice}, algorithm::Hram};
|
||||
use crate::{curve::Curve, algorithm::Hram};
|
||||
|
||||
macro_rules! kp_curve {
|
||||
(
|
||||
@@ -58,16 +60,18 @@ macro_rules! kp_curve {
|
||||
let mut modulus = vec![0; 16];
|
||||
modulus.extend((Self::F::zero() - Self::F::one()).to_bytes());
|
||||
let modulus = U384::from_be_slice(&modulus).wrapping_add(&U384::ONE);
|
||||
F_from_slice::<Self::F>(
|
||||
&U384::from_be_slice(&{
|
||||
let mut bytes = [0; 48];
|
||||
ExpandMsgXmd::<Sha256>::expand_message(
|
||||
&[msg],
|
||||
dst,
|
||||
48
|
||||
).unwrap().fill_bytes(&mut bytes);
|
||||
bytes
|
||||
}).reduce(&modulus).unwrap().to_be_bytes()[16 ..]
|
||||
Self::read_F(
|
||||
&mut Cursor::new(
|
||||
&U384::from_be_slice(&{
|
||||
let mut bytes = [0; 48];
|
||||
ExpandMsgXmd::<Sha256>::expand_message(
|
||||
&[msg],
|
||||
dst,
|
||||
48
|
||||
).unwrap().fill_bytes(&mut bytes);
|
||||
bytes
|
||||
}).reduce(&modulus).unwrap().to_be_bytes()[16 ..]
|
||||
)
|
||||
).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use core::fmt::Debug;
|
||||
use std::io::Read;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -77,41 +78,37 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
|
||||
// hash_msg and hash_binding_factor
|
||||
#[allow(non_snake_case)]
|
||||
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F;
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub(crate) fn F_len<C: Curve>() -> usize {
|
||||
<C::F as PrimeField>::Repr::default().as_ref().len()
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub(crate) fn G_len<C: Curve>() -> usize {
|
||||
<C::G as GroupEncoding>::Repr::default().as_ref().len()
|
||||
}
|
||||
|
||||
/// Field element from slice
|
||||
#[allow(non_snake_case)]
|
||||
pub(crate) fn F_from_slice<F: PrimeField>(slice: &[u8]) -> Result<F, CurveError> {
|
||||
let mut encoding = F::Repr::default();
|
||||
encoding.as_mut().copy_from_slice(slice);
|
||||
|
||||
let point = Option::<F>::from(F::from_repr(encoding)).ok_or(CurveError::InvalidScalar)?;
|
||||
if point.to_repr().as_ref() != slice {
|
||||
Err(CurveError::InvalidScalar)?;
|
||||
#[allow(non_snake_case)]
|
||||
fn F_len() -> usize {
|
||||
<Self::F as PrimeField>::Repr::default().as_ref().len()
|
||||
}
|
||||
Ok(point)
|
||||
}
|
||||
|
||||
/// Group element from slice
|
||||
#[allow(non_snake_case)]
|
||||
pub(crate) fn G_from_slice<G: PrimeGroup>(slice: &[u8]) -> Result<G, CurveError> {
|
||||
let mut encoding = G::Repr::default();
|
||||
encoding.as_mut().copy_from_slice(slice);
|
||||
|
||||
let point = Option::<G>::from(G::from_bytes(&encoding)).ok_or(CurveError::InvalidPoint)?;
|
||||
// Ban the identity, per the FROST spec, and non-canonical points
|
||||
if (point.is_identity().into()) || (point.to_bytes().as_ref() != slice) {
|
||||
Err(CurveError::InvalidPoint)?;
|
||||
#[allow(non_snake_case)]
|
||||
fn G_len() -> usize {
|
||||
<Self::G as GroupEncoding>::Repr::default().as_ref().len()
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn read_F<R: Read>(r: &mut R) -> Result<Self::F, CurveError> {
|
||||
let mut encoding = <Self::F as PrimeField>::Repr::default();
|
||||
r.read_exact(encoding.as_mut()).map_err(|_| CurveError::InvalidScalar)?;
|
||||
// ff mandates this is canonical
|
||||
Option::<Self::F>::from(Self::F::from_repr(encoding)).ok_or(CurveError::InvalidScalar)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn read_G<R: Read>(r: &mut R) -> Result<Self::G, CurveError> {
|
||||
let mut encoding = <Self::G as GroupEncoding>::Repr::default();
|
||||
r.read_exact(encoding.as_mut()).map_err(|_| CurveError::InvalidPoint)?;
|
||||
|
||||
let point = Option::<Self::G>::from(
|
||||
Self::G::from_bytes(&encoding)
|
||||
).ok_or(CurveError::InvalidPoint)?;
|
||||
// Ban the identity, per the FROST spec, and non-canonical points
|
||||
if (point.is_identity().into()) || (point.to_bytes().as_ref() != encoding.as_ref()) {
|
||||
Err(CurveError::InvalidPoint)?;
|
||||
}
|
||||
Ok(point)
|
||||
}
|
||||
Ok(point)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user