#![cfg(all(feature = "zf-decaf377", feature = "decaf377"))]
use core::ops::{Add, Mul, Sub};
use decaf377::{Element, Encoding, Fr};
use frost_core::{Ciphersuite, Field, FieldError, Group, GroupError};
use rand_core::{CryptoRng, RngCore};
use sha2::{Digest, Sha512};
#[derive(Clone, Copy)]
pub struct Decaf377ScalarField;
impl Field for Decaf377ScalarField {
type Scalar = Fr;
type Serialization = [u8; 32];
fn zero() -> Self::Scalar {
Fr::ZERO
}
fn one() -> Self::Scalar {
Fr::ONE
}
fn invert(scalar: &Self::Scalar) -> Result<Self::Scalar, FieldError> {
scalar.inverse().ok_or(FieldError::InvalidZeroScalar)
}
fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar {
let mut bytes = [0u8; 64];
rng.fill_bytes(&mut bytes);
Fr::from_le_bytes_mod_order(&bytes)
}
fn serialize(scalar: &Self::Scalar) -> Self::Serialization {
Fr::to_bytes(scalar)
}
fn deserialize(buf: &Self::Serialization) -> Result<Self::Scalar, FieldError> {
Fr::from_bytes_checked(buf).map_err(|_| FieldError::MalformedScalar)
}
fn little_endian_serialize(scalar: &Self::Scalar) -> Self::Serialization {
Self::serialize(scalar)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Decaf377Element(pub Element);
impl Eq for Decaf377Element {}
impl Decaf377Element {
#[inline]
pub fn into_inner(self) -> Element {
self.0
}
}
impl From<Element> for Decaf377Element {
#[inline]
fn from(e: Element) -> Self {
Self(e)
}
}
impl Add for Decaf377Element {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}
}
impl Sub for Decaf377Element {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0)
}
}
impl Mul<Fr> for Decaf377Element {
type Output = Self;
#[inline]
fn mul(self, rhs: Fr) -> Self {
Self(self.0 * rhs)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Decaf377Group;
impl Group for Decaf377Group {
type Field = Decaf377ScalarField;
type Element = Decaf377Element;
type Serialization = [u8; 32];
fn cofactor() -> <Self::Field as Field>::Scalar {
Fr::ONE
}
fn identity() -> Self::Element {
Decaf377Element(Element::IDENTITY)
}
fn generator() -> Self::Element {
Decaf377Element(Element::GENERATOR)
}
fn serialize(element: &Self::Element) -> Result<Self::Serialization, GroupError> {
if *element == Self::identity() {
return Err(GroupError::InvalidIdentityElement);
}
Ok(element.0.vartime_compress().0)
}
fn deserialize(buf: &Self::Serialization) -> Result<Self::Element, GroupError> {
let element = Decaf377Element(
Encoding(*buf)
.vartime_decompress()
.map_err(|_| GroupError::MalformedElement)?,
);
if element == Self::identity() {
Err(GroupError::InvalidIdentityElement)
} else {
Ok(element)
}
}
}
fn hash_to_array(inputs: &[&[u8]]) -> [u8; 64] {
let mut h = Sha512::new();
for i in inputs {
h.update(i);
}
let mut output = [0u8; 64];
output.copy_from_slice(h.finalize().as_ref());
output
}
fn hash_to_scalar(inputs: &[&[u8]]) -> Fr {
Fr::from_le_bytes_mod_order(&hash_to_array(inputs))
}
const CONTEXT_STRING: &str = "FROST-decaf377-SHA512-v1";
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Decaf377Sha512;
impl Ciphersuite for Decaf377Sha512 {
const ID: &'static str = CONTEXT_STRING;
type Group = Decaf377Group;
type HashOutput = [u8; 64];
type SignatureSerialization = [u8; 64];
fn H1(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
hash_to_scalar(&[CONTEXT_STRING.as_bytes(), b"rho", m])
}
fn H2(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
hash_to_scalar(&[CONTEXT_STRING.as_bytes(), b"chal", m])
}
fn H3(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
hash_to_scalar(&[CONTEXT_STRING.as_bytes(), b"nonce", m])
}
fn H4(m: &[u8]) -> Self::HashOutput {
hash_to_array(&[CONTEXT_STRING.as_bytes(), b"msg", m])
}
fn H5(m: &[u8]) -> Self::HashOutput {
hash_to_array(&[CONTEXT_STRING.as_bytes(), b"com", m])
}
fn HDKG(m: &[u8]) -> Option<<<Self::Group as Group>::Field as Field>::Scalar> {
Some(hash_to_scalar(&[CONTEXT_STRING.as_bytes(), b"dkg", m]))
}
fn HID(m: &[u8]) -> Option<<<Self::Group as Group>::Field as Field>::Scalar> {
Some(hash_to_scalar(&[CONTEXT_STRING.as_bytes(), b"id", m]))
}
}