mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-17 01:17:36 +00:00
Have Transcript::append_message take in AsRef<[u8]>, not &[u8]
Simplifies calling it.
This commit is contained in:
parent
65df18d285
commit
8de465af87
20 changed files with 59 additions and 59 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2406,7 +2406,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "flexible-transcript"
|
||||
version = "0.1.3"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"blake2",
|
||||
"digest 0.10.5",
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"] }
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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)> {
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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"] }
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue