Use HashMarker for Transcript and when generating scalars from digests

This commit is contained in:
Luke Parker 2022-09-29 05:33:46 -04:00
parent ca091a5f04
commit 8d9315b797
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
3 changed files with 10 additions and 10 deletions

View file

@ -10,7 +10,7 @@ use zeroize::Zeroize;
use subtle::{ConstantTimeEq, ConditionallySelectable}; use subtle::{ConstantTimeEq, ConditionallySelectable};
use rand_core::RngCore; use rand_core::RngCore;
use digest::{consts::U64, Digest}; use digest::{consts::U64, Digest, HashMarker};
use subtle::{Choice, CtOption}; use subtle::{Choice, CtOption};
@ -182,7 +182,7 @@ impl Scalar {
} }
/// Derive a Scalar without bias from a digest via wide reduction. /// Derive a Scalar without bias from a digest via wide reduction.
pub fn from_hash<D: Digest<OutputSize = U64>>(hash: D) -> Scalar { pub fn from_hash<D: Digest<OutputSize = U64> + HashMarker>(hash: D) -> Scalar {
let mut output = [0u8; 64]; let mut output = [0u8; 64];
output.copy_from_slice(&hash.finalize()); output.copy_from_slice(&hash.finalize());
let res = Scalar(DScalar::from_bytes_mod_order_wide(&output)); let res = Scalar(DScalar::from_bytes_mod_order_wide(&output));

View file

@ -4,7 +4,7 @@ use rand_core::{RngCore, CryptoRng};
use zeroize::Zeroize; use zeroize::Zeroize;
use digest::Digest; use digest::{Digest, HashMarker};
use transcript::Transcript; use transcript::Transcript;
@ -280,8 +280,8 @@ where
/// to safely and securely generate a Scalar, without risk of failure, nor bias. /// to safely and securely generate a Scalar, without risk of failure, nor bias.
/// It also ensures a lack of determinable relation between keys, guaranteeing security in the /// It also ensures a lack of determinable relation between keys, guaranteeing security in the
/// currently expected use case for this, atomic swaps, where each swap leaks the key. Knowing /// currently expected use case for this, atomic swaps, where each swap leaks the key. Knowing
pub fn prove<R: RngCore + CryptoRng, T: Clone + Transcript, D: Digest>(
/// the relationship between keys would allow breaking all swaps after just one. /// the relationship between keys would allow breaking all swaps after just one.
pub fn prove<R: RngCore + CryptoRng, T: Clone + Transcript, D: Digest + HashMarker>(
rng: &mut R, rng: &mut R,
transcript: &mut T, transcript: &mut T,
generators: (Generators<G0>, Generators<G1>), generators: (Generators<G0>, Generators<G1>),

View file

@ -6,7 +6,7 @@ mod merlin;
#[cfg(feature = "merlin")] #[cfg(feature = "merlin")]
pub use crate::merlin::MerlinTranscript; pub use crate::merlin::MerlinTranscript;
use digest::{typenum::type_operators::IsGreaterOrEqual, consts::U256, Digest, Output}; use digest::{typenum::type_operators::IsGreaterOrEqual, consts::U256, Digest, Output, HashMarker};
pub trait Transcript { pub trait Transcript {
type Challenge: Clone + Send + Sync + AsRef<[u8]>; type Challenge: Clone + Send + Sync + AsRef<[u8]>;
@ -50,16 +50,16 @@ impl DigestTranscriptMember {
} }
} }
pub trait SecureDigest: Clone + Digest {}
impl<D: Clone + Digest> SecureDigest for D where D::OutputSize: IsGreaterOrEqual<U256> {}
/// A trait defining cryptographic Digests with at least a 256-byte output size, assuming at least /// A trait defining cryptographic Digests with at least a 256-byte output size, assuming at least
/// a 128-bit level of security accordingly. /// a 128-bit level of security accordingly.
pub trait SecureDigest: Digest + HashMarker {}
impl<D: Digest + HashMarker> SecureDigest for D where D::OutputSize: IsGreaterOrEqual<U256> {}
/// A simple transcript format constructed around the specified hash algorithm. /// A simple transcript format constructed around the specified hash algorithm.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DigestTranscript<D: SecureDigest>(D); pub struct DigestTranscript<D: Clone + SecureDigest>(D);
impl<D: SecureDigest> DigestTranscript<D> { impl<D: Clone + SecureDigest> DigestTranscript<D> {
fn append(&mut self, kind: DigestTranscriptMember, value: &[u8]) { fn append(&mut self, kind: DigestTranscriptMember, value: &[u8]) {
self.0.update([kind.as_u8()]); self.0.update([kind.as_u8()]);
// Assumes messages don't exceed 16 exabytes // Assumes messages don't exceed 16 exabytes
@ -68,7 +68,7 @@ impl<D: SecureDigest> DigestTranscript<D> {
} }
} }
impl<D: SecureDigest> Transcript for DigestTranscript<D> { impl<D: Clone + SecureDigest> Transcript for DigestTranscript<D> {
type Challenge = Output<D>; type Challenge = Output<D>;
fn new(name: &'static [u8]) -> Self { fn new(name: &'static [u8]) -> Self {