use super::{ExpandMsg, MapToCurve, hash_to_field};
use elliptic_curve::ProjectivePoint;
use elliptic_curve::array::typenum::NonZero;
use elliptic_curve::array::{Array, ArraySize};
use elliptic_curve::group::cofactor::CofactorGroup;
use elliptic_curve::ops::Reduce;
pub trait GroupDigest: MapToCurve {
const HASH_TO_CURVE_ID: &[u8];
const ENCODE_TO_CURVE_ID: &[u8];
type ExpandMsg: ExpandMsg<Self::SecurityLevel>;
fn hash_from_bytes(
msg: &[&[u8]],
dst: &[&[u8]],
) -> Result<ProjectivePoint<Self>, <Self::ExpandMsg as ExpandMsg<Self::SecurityLevel>>::Error>
{
hash_from_bytes::<Self, Self::ExpandMsg>(msg, dst)
}
fn encode_from_bytes(
msg: &[&[u8]],
dst: &[&[u8]],
) -> Result<ProjectivePoint<Self>, <Self::ExpandMsg as ExpandMsg<Self::SecurityLevel>>::Error>
{
encode_from_bytes::<Self, Self::ExpandMsg>(msg, dst)
}
}
pub fn hash_from_bytes<C, X>(msg: &[&[u8]], dst: &[&[u8]]) -> Result<ProjectivePoint<C>, X::Error>
where
C: MapToCurve,
X: ExpandMsg<C::SecurityLevel>,
{
let [u0, u1] = hash_to_field::<2, X, _, C::FieldElement, C::Length>(msg, dst)?;
let q0 = C::map_to_curve(u0);
let q1 = C::map_to_curve(u1);
Ok((q0 + q1).clear_cofactor())
}
pub fn encode_from_bytes<C, X>(msg: &[&[u8]], dst: &[&[u8]]) -> Result<ProjectivePoint<C>, X::Error>
where
C: MapToCurve,
X: ExpandMsg<C::SecurityLevel>,
{
let [u] = hash_to_field::<1, X, _, C::FieldElement, C::Length>(msg, dst)?;
let q0 = C::map_to_curve(u);
Ok(q0.clear_cofactor())
}
pub fn hash_to_scalar<C, X, L>(msg: &[&[u8]], dst: &[&[u8]]) -> Result<C::Scalar, X::Error>
where
C: MapToCurve,
X: ExpandMsg<C::SecurityLevel>,
L: ArraySize + NonZero,
C::Scalar: Reduce<Array<u8, L>>,
{
let [u] = hash_to_field::<1, X, _, C::Scalar, L>(msg, dst)?;
Ok(u)
}