Have Transcript::append_message take in AsRef<[u8]>, not &[u8]

Simplifies calling it.
This commit is contained in:
Luke Parker 2022-11-05 18:43:36 -04:00
parent 65df18d285
commit 8de465af87
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
20 changed files with 59 additions and 59 deletions

2
Cargo.lock generated
View file

@ -2406,7 +2406,7 @@ dependencies = [
[[package]]
name = "flexible-transcript"
version = "0.1.3"
version = "0.2.0"
dependencies = [
"blake2",
"digest 0.10.5",

View file

@ -33,7 +33,7 @@ group = { version = "0.12" }
dalek-ff-group = { path = "../../crypto/dalek-ff-group", version = "0.1" }
multiexp = { path = "../../crypto/multiexp", version = "0.2", features = ["batch"] }
transcript = { package = "flexible-transcript", path = "../../crypto/transcript", version = "0.1", features = ["recommended"], optional = true }
transcript = { package = "flexible-transcript", path = "../../crypto/transcript", version = "0.2", features = ["recommended"], optional = true }
frost = { package = "modular-frost", path = "../../crypto/frost", version = "0.4", features = ["ed25519"], optional = true }
dleq = { path = "../../crypto/dleq", version = "0.1", features = ["serialize"], optional = true }

View file

@ -41,7 +41,7 @@ impl ClsagInput {
// Doesn't domain separate as this is considered part of the larger CLSAG proof
// Ring index
transcript.append_message(b"ring_index", &[self.decoys.i]);
transcript.append_message(b"ring_index", [self.decoys.i]);
// Ring
let mut ring = vec![];
@ -52,7 +52,7 @@ impl ClsagInput {
ring.extend(pair[0].compress().to_bytes());
ring.extend(pair[1].compress().to_bytes());
}
transcript.append_message(b"ring", &ring);
transcript.append_message(b"ring", ring);
// Doesn't include the commitment's parts as the above ring + index includes the commitment
// The only potential malleability would be if the G/H relationship is known breaking the
@ -195,10 +195,10 @@ impl Algorithm<Ed25519> for ClsagMultisig {
if self.image.is_identity() {
self.transcript.domain_separate(b"CLSAG");
self.input().transcript(&mut self.transcript);
self.transcript.append_message(b"mask", &self.mask().to_bytes());
self.transcript.append_message(b"mask", self.mask().to_bytes());
}
self.transcript.append_message(b"participant", &l.to_be_bytes());
self.transcript.append_message(b"participant", l.to_be_bytes());
addendum
.dleq
@ -211,7 +211,7 @@ impl Algorithm<Ed25519> for ClsagMultisig {
self
.transcript
.append_message(b"key_image_share", addendum.key_image.compress().to_bytes().as_ref());
.append_message(b"key_image_share", addendum.key_image.compress().to_bytes());
self.image += addendum.key_image.0;
Ok(())

View file

@ -90,24 +90,24 @@ impl SignableTransaction {
// Include the height we're using for our data
// The data itself will be included, making this unnecessary, yet a lot of this is technically
// unnecessary. Anything which further increases security at almost no cost should be followed
transcript.append_message(b"height", &u64::try_from(height).unwrap().to_le_bytes());
transcript.append_message(b"height", u64::try_from(height).unwrap().to_le_bytes());
// Also include the spend_key as below only the key offset is included, so this transcripts the
// sum product
// Useful as transcripting the sum product effectively transcripts the key image, further
// guaranteeing the one time properties noted below
transcript.append_message(b"spend_key", &keys.group_key().0.compress().to_bytes());
transcript.append_message(b"spend_key", keys.group_key().0.compress().to_bytes());
for input in &self.inputs {
// These outputs can only be spent once. Therefore, it forces all RNGs derived from this
// transcript (such as the one used to create one time keys) to be unique
transcript.append_message(b"input_hash", &input.output.absolute.tx);
transcript.append_message(b"input_output_index", &[input.output.absolute.o]);
transcript.append_message(b"input_hash", input.output.absolute.tx);
transcript.append_message(b"input_output_index", [input.output.absolute.o]);
// Not including this, with a doxxed list of payments, would allow brute forcing the inputs
// to determine RNG seeds and therefore the true spends
transcript.append_message(b"input_shared_key", &input.key_offset().to_bytes());
transcript.append_message(b"input_shared_key", input.key_offset().to_bytes());
}
for payment in &self.payments {
transcript.append_message(b"payment_address", payment.0.to_string().as_bytes());
transcript.append_message(b"payment_amount", &payment.1.to_le_bytes());
transcript.append_message(b"payment_amount", payment.1.to_le_bytes());
}
// Sort included before cloning it around
@ -243,7 +243,7 @@ impl SignMachine<Transaction> for TransactionSignMachine {
// While each CLSAG will do this as they need to for security, they have their own
// transcripts cloned from this TX's initial premise's transcript. For our TX
// transcript to have the CLSAG data for entropy, it'll have to be added ourselves here
self.transcript.append_message(b"participant", &(*l).to_be_bytes());
self.transcript.append_message(b"participant", (*l).to_be_bytes());
let preprocess = if *l == self.i {
self.our_preprocess[c].clone()
@ -254,7 +254,7 @@ impl SignMachine<Transaction> for TransactionSignMachine {
{
let mut buf = vec![];
preprocess.write(&mut buf).unwrap();
self.transcript.append_message(b"preprocess", &buf);
self.transcript.append_message(b"preprocess", buf);
}
// While here, calculate the key image

View file

@ -31,7 +31,7 @@ group = "0.12"
ciphersuite = { path = "../ciphersuite", version = "0.1", features = ["std"] }
transcript = { package = "flexible-transcript", path = "../transcript", features = ["recommended"], version = "^0.1.3" }
transcript = { package = "flexible-transcript", path = "../transcript", version = "0.2", features = ["recommended"] }
multiexp = { path = "../multiexp", version = "0.2", features = ["batch"] }

View file

@ -29,8 +29,8 @@ pub trait CiphersuitePromote<C2: Ciphersuite> {
fn transcript<G: GroupEncoding>(key: G, i: u16) -> RecommendedTranscript {
let mut transcript = RecommendedTranscript::new(b"FROST Generator Update");
transcript.append_message(b"group_key", key.to_bytes().as_ref());
transcript.append_message(b"participant", &i.to_be_bytes());
transcript.append_message(b"group_key", key.to_bytes());
transcript.append_message(b"participant", i.to_be_bytes());
transcript
}

View file

@ -19,7 +19,7 @@ zeroize = { version = "1.3", features = ["zeroize_derive"] }
digest = "0.10"
transcript = { package = "flexible-transcript", path = "../transcript", version = "0.1" }
transcript = { package = "flexible-transcript", path = "../transcript", version = "0.2" }
ff = "0.12"
group = "0.12"

View file

@ -62,9 +62,9 @@ where
#[allow(non_snake_case)]
fn nonces<T: Transcript>(mut transcript: T, nonces: (G0, G1)) -> (G0::Scalar, G1::Scalar) {
transcript.domain_separate(b"aos_membership_proof");
transcript.append_message(b"ring_len", &u8::try_from(RING_LEN).unwrap().to_le_bytes());
transcript.append_message(b"nonce_0", nonces.0.to_bytes().as_ref());
transcript.append_message(b"nonce_1", nonces.1.to_bytes().as_ref());
transcript.append_message(b"ring_len", u8::try_from(RING_LEN).unwrap().to_le_bytes());
transcript.append_message(b"nonce_0", nonces.0.to_bytes());
transcript.append_message(b"nonce_1", nonces.1.to_bytes());
mutual_scalar_from_bytes(transcript.challenge(b"challenge").as_ref())
}

View file

@ -91,9 +91,9 @@ where
{
fn transcript<T: Transcript>(transcript: &mut T, i: usize, commitments: (G0, G1)) {
transcript.domain_separate(b"bits");
transcript.append_message(b"group", &u16::try_from(i).unwrap().to_le_bytes());
transcript.append_message(b"commitment_0", commitments.0.to_bytes().as_ref());
transcript.append_message(b"commitment_1", commitments.1.to_bytes().as_ref());
transcript.append_message(b"group", u16::try_from(i).unwrap().to_le_bytes());
transcript.append_message(b"commitment_0", commitments.0.to_bytes());
transcript.append_message(b"commitment_1", commitments.1.to_bytes());
}
fn ring(pow_2: (G0, G1), commitments: (G0, G1)) -> Vec<(G0, G1)> {

View file

@ -52,8 +52,8 @@ impl<G: PrimeGroup> Generators<G> {
fn transcript<T: Transcript>(&self, transcript: &mut T) {
transcript.domain_separate(b"generators");
transcript.append_message(b"primary", self.primary.to_bytes().as_ref());
transcript.append_message(b"alternate", self.alt.to_bytes().as_ref());
transcript.append_message(b"primary", self.primary.to_bytes());
transcript.append_message(b"alternate", self.alt.to_bytes());
}
}
@ -153,8 +153,8 @@ where
generators.0.transcript(transcript);
generators.1.transcript(transcript);
transcript.domain_separate(b"points");
transcript.append_message(b"point_0", keys.0.to_bytes().as_ref());
transcript.append_message(b"point_1", keys.1.to_bytes().as_ref());
transcript.append_message(b"point_0", keys.0.to_bytes());
transcript.append_message(b"point_1", keys.1.to_bytes());
}
pub(crate) fn blinding_key<R: RngCore + CryptoRng, F: PrimeField>(

View file

@ -30,13 +30,13 @@ impl<G: PrimeGroup + Zeroize> SchnorrPoK<G>
where
G::Scalar: PrimeFieldBits + Zeroize,
{
// Not hram due to the lack of m
// Not HRAm due to the lack of m
#[allow(non_snake_case)]
fn hra<T: Transcript>(transcript: &mut T, generator: G, R: G, A: G) -> G::Scalar {
transcript.domain_separate(b"schnorr_proof_of_knowledge");
transcript.append_message(b"generator", generator.to_bytes().as_ref());
transcript.append_message(b"nonce", R.to_bytes().as_ref());
transcript.append_message(b"public_key", A.to_bytes().as_ref());
transcript.append_message(b"generator", generator.to_bytes());
transcript.append_message(b"nonce", R.to_bytes());
transcript.append_message(b"public_key", A.to_bytes());
challenge(transcript)
}

View file

@ -70,9 +70,9 @@ pub struct DLEqProof<G: PrimeGroup> {
#[allow(non_snake_case)]
impl<G: PrimeGroup> DLEqProof<G> {
fn transcript<T: Transcript>(transcript: &mut T, generator: G, nonce: G, point: G) {
transcript.append_message(b"generator", generator.to_bytes().as_ref());
transcript.append_message(b"nonce", nonce.to_bytes().as_ref());
transcript.append_message(b"point", point.to_bytes().as_ref());
transcript.append_message(b"generator", generator.to_bytes());
transcript.append_message(b"nonce", nonce.to_bytes());
transcript.append_message(b"point", point.to_bytes());
}
pub fn prove<R: RngCore + CryptoRng, T: Transcript>(

View file

@ -34,7 +34,7 @@ minimal-ed448 = { path = "../ed448", version = "^0.1.2", optional = true }
ciphersuite = { path = "../ciphersuite", version = "0.1", features = ["std"] }
transcript = { package = "flexible-transcript", path = "../transcript", features = ["recommended"], version = "^0.1.3" }
transcript = { package = "flexible-transcript", path = "../transcript", version = "0.2", features = ["recommended"] }
multiexp = { path = "../multiexp", version = "0.2", features = ["batch"] }

View file

@ -93,8 +93,8 @@ impl Transcript for IetfTranscript {
fn domain_separate(&mut self, _: &[u8]) {}
fn append_message(&mut self, _: &'static [u8], message: &[u8]) {
self.0.extend(message);
fn append_message<M: AsRef<[u8]>>(&mut self, _: &'static [u8], message: M) {
self.0.extend(message.as_ref());
}
fn challenge(&mut self, _: &'static [u8]) -> Vec<u8> {

View file

@ -162,8 +162,8 @@ impl<C: Curve> Commitments<C> {
pub(crate) fn transcript<T: Transcript>(&self, t: &mut T) {
for nonce in &self.nonces {
for commitments in &nonce.generators {
t.append_message(b"commitment_D", commitments.0[0].to_bytes().as_ref());
t.append_message(b"commitment_E", commitments.0[1].to_bytes().as_ref());
t.append_message(b"commitment_D", commitments.0[0].to_bytes());
t.append_message(b"commitment_E", commitments.0[1].to_bytes());
}
// Transcripting the DLEqs implicitly transcripts the exact generators used for this nonce
@ -215,7 +215,7 @@ impl<C: Curve> BindingFactor<C> {
pub(crate) fn calculate_binding_factors<T: Clone + Transcript>(&mut self, transcript: &mut T) {
for (l, binding) in self.0.iter_mut() {
let mut transcript = transcript.clone();
transcript.append_message(b"participant", C::F::from(u64::from(*l)).to_repr().as_ref());
transcript.append_message(b"participant", C::F::from(u64::from(*l)).to_repr());
// It *should* be perfectly fine to reuse a binding factor for multiple nonces
// This generates a binding factor per nonce just to ensure it never comes up as a question
binding.binding_factors = Some(

View file

@ -266,7 +266,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
.params
.algorithm
.transcript()
.append_message(b"participant", C::F::from(u64::from(*l)).to_repr().as_ref());
.append_message(b"participant", C::F::from(u64::from(*l)).to_repr());
}
if *l == self.params.keys.params().i() {
@ -277,7 +277,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
{
let mut buf = vec![];
addendum.write(&mut buf).unwrap();
self.params.algorithm.transcript().append_message(b"addendum", &buf);
self.params.algorithm.transcript().append_message(b"addendum", buf);
}
B.insert(*l, commitments);
@ -288,7 +288,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
{
let mut buf = vec![];
preprocess.addendum.write(&mut buf).unwrap();
self.params.algorithm.transcript().append_message(b"addendum", &buf);
self.params.algorithm.transcript().append_message(b"addendum", buf);
}
B.insert(*l, preprocess.commitments);
@ -298,7 +298,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
// Re-format into the FROST-expected rho transcript
let mut rho_transcript = A::Transcript::new(b"FROST_rho");
rho_transcript.append_message(b"message", &C::hash_msg(msg));
rho_transcript.append_message(b"message", C::hash_msg(msg));
rho_transcript.append_message(
b"preprocesses",
&C::hash_commitments(
@ -317,7 +317,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
// While further code edits would still be required for such a model (having the offset
// communicated as a point along with only a single party applying the offset), this means
// it wouldn't require a transcript change as well
rho_transcript.append_message(b"offset", (C::generator() * offset).to_bytes().as_ref());
rho_transcript.append_message(b"offset", (C::generator() * offset).to_bytes());
}
// Generate the per-signer binding factors
@ -329,7 +329,7 @@ impl<C: Curve, A: Algorithm<C>> SignMachine<A::Signature> for AlgorithmSignMachi
.params
.algorithm
.transcript()
.append_message(b"rho_transcript", rho_transcript.challenge(b"merge").as_ref());
.append_message(b"rho_transcript", rho_transcript.challenge(b"merge"));
}
#[allow(non_snake_case)]

View file

@ -1,6 +1,6 @@
[package]
name = "flexible-transcript"
version = "0.1.3"
version = "0.2.0"
description = "A simple transcript trait definition, along with viable options"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/crypto/transcript"

View file

@ -18,7 +18,7 @@ pub trait Transcript {
fn domain_separate(&mut self, label: &'static [u8]);
/// Append a message to the transcript.
fn append_message(&mut self, label: &'static [u8], message: &[u8]);
fn append_message<M: AsRef<[u8]>>(&mut self, label: &'static [u8], message: M);
/// Produce a challenge. This MUST update the transcript as it does so, preventing the same
/// challenge from being generated multiple times.
@ -77,13 +77,13 @@ impl<D: Clone + SecureDigest> Transcript for DigestTranscript<D> {
res
}
fn domain_separate(&mut self, label: &[u8]) {
fn domain_separate(&mut self, label: &'static [u8]) {
self.append(DigestTranscriptMember::Domain, label);
}
fn append_message(&mut self, label: &'static [u8], message: &[u8]) {
fn append_message<M: AsRef<[u8]>>(&mut self, label: &'static [u8], message: M) {
self.append(DigestTranscriptMember::Label, label);
self.append(DigestTranscriptMember::Value, message);
self.append(DigestTranscriptMember::Value, message.as_ref());
}
fn challenge(&mut self, label: &'static [u8]) -> Self::Challenge {

View file

@ -27,8 +27,8 @@ impl Transcript for MerlinTranscript {
self.append_message(b"dom-sep", label);
}
fn append_message(&mut self, label: &'static [u8], message: &[u8]) {
self.0.append_message(label, message);
fn append_message<M: AsRef<[u8]>>(&mut self, label: &'static [u8], message: M) {
self.0.append_message(label, message.as_ref());
}
fn challenge(&mut self, label: &'static [u8]) -> Self::Challenge {

View file

@ -39,7 +39,7 @@ impl<C: Curve> WalletKeys<C> {
let mut transcript = RecommendedTranscript::new(DST);
transcript.append_message(b"chain", chain);
transcript.append_message(b"curve", C::ID);
transcript.append_message(b"group_key", self.keys.group_key().to_bytes().as_ref());
transcript.append_message(b"group_key", self.keys.group_key().to_bytes());
self.keys.offset(<C as Ciphersuite>::hash_to_F(DST, &transcript.challenge(b"offset")))
}
}
@ -314,12 +314,12 @@ impl<D: CoinDb, C: Coin> Wallet<D, C> {
// Create the transcript for this transaction
let mut transcript = RecommendedTranscript::new(b"Serai Processor Wallet Send");
transcript
.append_message(b"canonical_block", &u64::try_from(canonical).unwrap().to_le_bytes());
.append_message(b"canonical_block", u64::try_from(canonical).unwrap().to_le_bytes());
transcript.append_message(
b"acknowledged_block",
&u64::try_from(acknowledged_block).unwrap().to_le_bytes(),
u64::try_from(acknowledged_block).unwrap().to_le_bytes(),
);
transcript.append_message(b"index", &u64::try_from(txs.len()).unwrap().to_le_bytes());
transcript.append_message(b"index", u64::try_from(txs.len()).unwrap().to_le_bytes());
let tx = self
.coin