mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-23 03:59:22 +00:00
Fix incorrect sig_hash generation
sig_hash was used as a challenge. challenges should be of the form H(R, A, m). These sig hashes were solely H(A, m), allowing trivial forgeries.
This commit is contained in:
parent
c6982b5dfc
commit
dfa3106a38
3 changed files with 20 additions and 13 deletions
|
@ -458,11 +458,9 @@ impl Transaction {
|
||||||
signed_ref.signer = Ristretto::generator() * key.deref();
|
signed_ref.signer = Ristretto::generator() * key.deref();
|
||||||
signed_ref.nonce = nonce;
|
signed_ref.nonce = nonce;
|
||||||
|
|
||||||
|
let sig_nonce = Zeroizing::new(<Ristretto as Ciphersuite>::F::random(rng));
|
||||||
|
signed(self).signature.R = <Ristretto as Ciphersuite>::generator() * sig_nonce.deref();
|
||||||
let sig_hash = self.sig_hash(genesis);
|
let sig_hash = self.sig_hash(genesis);
|
||||||
signed(self).signature = SchnorrSignature::<Ristretto>::sign(
|
signed(self).signature = SchnorrSignature::<Ristretto>::sign(key, sig_nonce, sig_hash);
|
||||||
key,
|
|
||||||
Zeroizing::new(<Ristretto as Ciphersuite>::F::random(rng)),
|
|
||||||
sig_hash,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use core::ops::Deref;
|
||||||
use std::{io, collections::HashMap};
|
use std::{io, collections::HashMap};
|
||||||
|
|
||||||
use zeroize::Zeroizing;
|
use zeroize::Zeroizing;
|
||||||
|
@ -114,11 +115,9 @@ pub fn signed_transaction<R: RngCore + CryptoRng>(
|
||||||
let mut tx =
|
let mut tx =
|
||||||
SignedTransaction(data, Signed { signer, nonce, signature: random_signed(rng).signature });
|
SignedTransaction(data, Signed { signer, nonce, signature: random_signed(rng).signature });
|
||||||
|
|
||||||
tx.1.signature = SchnorrSignature::sign(
|
let sig_nonce = Zeroizing::new(<Ristretto as Ciphersuite>::F::random(rng));
|
||||||
key,
|
tx.1.signature.R = Ristretto::generator() * sig_nonce.deref();
|
||||||
Zeroizing::new(<Ristretto as Ciphersuite>::F::random(rng)),
|
tx.1.signature = SchnorrSignature::sign(key, sig_nonce, tx.sig_hash(genesis));
|
||||||
tx.sig_hash(genesis),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut nonces = HashMap::from([(signer, nonce)]);
|
let mut nonces = HashMap::from([(signer, nonce)]);
|
||||||
verify_transaction(&tx, genesis, &mut nonces).unwrap();
|
verify_transaction(&tx, genesis, &mut nonces).unwrap();
|
||||||
|
|
|
@ -98,10 +98,20 @@ pub trait Transaction: 'static + Send + Sync + Clone + Eq + Debug + ReadWrite {
|
||||||
/// Obtain the challenge for this transaction's signature.
|
/// Obtain the challenge for this transaction's signature.
|
||||||
///
|
///
|
||||||
/// Do not override this unless you know what you're doing.
|
/// Do not override this unless you know what you're doing.
|
||||||
|
///
|
||||||
|
/// Panics if called on non-signed transactions.
|
||||||
fn sig_hash(&self, genesis: [u8; 32]) -> <Ristretto as Ciphersuite>::F {
|
fn sig_hash(&self, genesis: [u8; 32]) -> <Ristretto as Ciphersuite>::F {
|
||||||
|
match self.kind() {
|
||||||
|
TransactionKind::Signed(Signed { signature, .. }) => {
|
||||||
<Ristretto as Ciphersuite>::F::from_bytes_mod_order_wide(
|
<Ristretto as Ciphersuite>::F::from_bytes_mod_order_wide(
|
||||||
&Blake2b512::digest([genesis, self.hash()].concat()).into(),
|
&Blake2b512::digest(
|
||||||
|
[genesis.as_ref(), &self.hash(), signature.R.to_bytes().as_ref()].concat(),
|
||||||
)
|
)
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => panic!("sig_hash called on non-signed transaction"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue