Resolve merging crypto-{audit, tweaks} and use the proper transcript in Bitcoin

This commit is contained in:
Luke Parker 2023-03-16 16:59:20 -04:00
parent 64924835ad
commit d2c1592c61
No known key found for this signature in database
8 changed files with 75 additions and 36 deletions

43
Cargo.lock generated
View file

@ -602,7 +602,7 @@ dependencies = [
"bitcoin",
"flexible-transcript",
"hex",
"k256",
"k256 0.12.0",
"lazy_static",
"modular-frost",
"rand_core 0.6.4",
@ -1037,7 +1037,7 @@ dependencies = [
"hex",
"k256 0.12.0",
"minimal-ed448",
"p256",
"p256 0.12.0",
"rand_core 0.6.4",
"sha2 0.10.6",
"sha3",
@ -2599,7 +2599,7 @@ version = "0.12.0"
dependencies = [
"group",
"k256 0.12.0",
"p256",
"p256 0.12.0",
"rand_core 0.6.4",
]
@ -3350,6 +3350,15 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
[[package]]
name = "hkdf"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
dependencies = [
"hmac 0.12.1",
]
[[package]]
name = "hmac"
version = "0.8.1"
@ -5575,6 +5584,17 @@ version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "p256"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594"
dependencies = [
"ecdsa 0.14.8",
"elliptic-curve",
"sha2 0.10.6",
]
[[package]]
name = "p256"
version = "0.12.0"
@ -5587,6 +5607,17 @@ dependencies = [
"sha2 0.10.6",
]
[[package]]
name = "p384"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa"
dependencies = [
"ecdsa 0.14.8",
"elliptic-curve",
"sha2 0.10.6",
]
[[package]]
name = "packed_simd_2"
version = "0.3.8"
@ -8224,7 +8255,7 @@ dependencies = [
"futures",
"group",
"hex",
"k256",
"k256 0.12.0",
"modular-frost",
"monero-serai",
"rand_core 0.6.4",
@ -10788,7 +10819,7 @@ dependencies = [
"hmac 0.12.1",
"log",
"oid-registry 0.6.1",
"p256",
"p256 0.11.1",
"p384",
"rand 0.8.5",
"rand_core 0.6.4",
@ -10799,7 +10830,7 @@ dependencies = [
"serde",
"sha1",
"sha2 0.10.6",
"signature",
"signature 1.6.4",
"subtle",
"thiserror",
"tokio",

View file

@ -18,7 +18,7 @@ sha2 = "0.10"
secp256k1 = { version = "0.24", features = ["global-context"] }
bitcoin = { version = "0.29", features = ["serde"] }
k256 = { version = "0.11", features = ["arithmetic"] }
k256 = { version = "0.12", features = ["arithmetic"] }
transcript = { package = "flexible-transcript", path = "../../crypto/transcript", version = "0.2", features = ["recommended"] }
frost = { version = "0.5", package = "modular-frost", path = "../../crypto/frost", features = ["secp256k1"] }

View file

@ -8,7 +8,8 @@ use bitcoin::hashes::{Hash as HashTrait, sha256::Hash};
use k256::Scalar;
use frost::{
curve::Secp256k1,
algorithm::Schnorr,
Participant,
algorithm::IetfSchnorr,
tests::{algorithm_machines, key_gen, sign},
};
@ -24,12 +25,12 @@ fn test_signing() {
*keys = keys.offset(Scalar::from(offset));
}
let algo = Schnorr::<Secp256k1, BitcoinHram>::new();
let algo = IetfSchnorr::<Secp256k1, BitcoinHram>::ietf();
let mut sig = sign(
&mut OsRng,
algo,
keys.clone(),
algorithm_machines(&mut OsRng, Schnorr::<Secp256k1, BitcoinHram>::new(), &keys),
algorithm_machines(&mut OsRng, IetfSchnorr::ietf(), &keys),
&Sha256::digest(MESSAGE),
);
@ -41,7 +42,7 @@ fn test_signing() {
.verify_schnorr(
&Signature::from_slice(&sig.serialize()[1 .. 65]).unwrap(),
&Message::from(Hash::hash(MESSAGE)),
&x_only(&keys[&1].group_key()),
&x_only(&keys[&Participant::new(1).unwrap()].group_key()),
)
.unwrap()
}

View file

@ -10,7 +10,7 @@ use transcript::{Transcript, RecommendedTranscript};
use k256::{elliptic_curve::sec1::ToEncodedPoint, Scalar};
use frost::{
curve::{Ciphersuite, Secp256k1},
ThresholdKeys, FrostError,
Participant, ThresholdKeys, FrostError,
algorithm::Schnorr,
sign::*,
};
@ -168,25 +168,21 @@ impl SignableTransaction {
let mut sigs = vec![];
for i in 0 .. tx.input.len() {
// TODO: Use the above transcript here
let mut transcript = transcript.clone();
transcript.append_message(b"signing_input", u32::try_from(i).unwrap().to_le_bytes());
sigs.push(
AlgorithmMachine::new(
Schnorr::<Secp256k1, BitcoinHram>::new(),
keys.clone().offset(self.1[i]),
)
.unwrap(),
AlgorithmMachine::new(Schnorr::new(transcript), keys.clone().offset(self.1[i])).unwrap(),
);
}
Ok(TransactionMachine { tx: self, transcript, sigs })
Ok(TransactionMachine { tx: self, sigs })
}
}
/// A FROST signing machine to produce a Bitcoin transaction.
pub struct TransactionMachine {
tx: SignableTransaction,
transcript: RecommendedTranscript,
sigs: Vec<AlgorithmMachine<Secp256k1, Schnorr<Secp256k1, BitcoinHram>>>,
sigs: Vec<AlgorithmMachine<Secp256k1, Schnorr<Secp256k1, RecommendedTranscript, BitcoinHram>>>,
}
impl PreprocessMachine for TransactionMachine {
@ -209,14 +205,14 @@ impl PreprocessMachine for TransactionMachine {
})
.collect();
(TransactionSignMachine { tx: self.tx, transcript: self.transcript, sigs }, preprocesses)
(TransactionSignMachine { tx: self.tx, sigs }, preprocesses)
}
}
pub struct TransactionSignMachine {
tx: SignableTransaction,
transcript: RecommendedTranscript,
sigs: Vec<AlgorithmSignMachine<Secp256k1, Schnorr<Secp256k1, BitcoinHram>>>,
sigs:
Vec<AlgorithmSignMachine<Secp256k1, Schnorr<Secp256k1, RecommendedTranscript, BitcoinHram>>>,
}
impl SignMachine<Transaction> for TransactionSignMachine {
@ -250,7 +246,7 @@ impl SignMachine<Transaction> for TransactionSignMachine {
fn sign(
mut self,
commitments: HashMap<u16, Self::Preprocess>,
commitments: HashMap<Participant, Self::Preprocess>,
msg: &[u8],
) -> Result<(TransactionSignatureMachine, Self::SignatureShare), FrostError> {
if !msg.is_empty() {
@ -293,7 +289,9 @@ impl SignMachine<Transaction> for TransactionSignMachine {
pub struct TransactionSignatureMachine {
tx: Transaction,
sigs: Vec<AlgorithmSignatureMachine<Secp256k1, Schnorr<Secp256k1, BitcoinHram>>>,
sigs: Vec<
AlgorithmSignatureMachine<Secp256k1, Schnorr<Secp256k1, RecommendedTranscript, BitcoinHram>>,
>,
}
impl SignatureMachine<Transaction> for TransactionSignatureMachine {
@ -305,7 +303,7 @@ impl SignatureMachine<Transaction> for TransactionSignatureMachine {
fn complete(
mut self,
mut shares: HashMap<u16, Self::SignatureShare>,
mut shares: HashMap<Participant, Self::SignatureShare>,
) -> Result<Transaction, FrostError> {
for (input, schnorr) in self.tx.input.iter_mut().zip(self.sigs.drain(..)) {
let mut sig = schnorr.complete(

View file

@ -12,9 +12,10 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
futures = "0.3"
lazy_static = "1"
thiserror = "1"
crc = "3"
rand_core = "0.6"
rand_chacha = { version = "0.3", optional = true }
@ -24,6 +25,7 @@ rand_distr = "0.4"
zeroize = { version = "^1.5", features = ["zeroize_derive"] }
subtle = "^2.4"
crc = "3"
sha3 = "0.10"
curve25519-dalek = { version = "^3.2", features = ["std"] }

View file

@ -184,7 +184,7 @@ fn core(
let L = (&s[i] * &ED25519_BASEPOINT_TABLE) + (c_p * P[i]) + (c_c * C[i]);
let PH = hash_to_point(P[i]);
// Shouldn't be an issue as all of the variables in this vartime statement are public
let R = (s[i] * PH) + images_precomp.vartime_multiscalar_mul(&[c_p, c_c]);
let R = (s[i] * PH) + images_precomp.vartime_multiscalar_mul([c_p, c_c]);
to_hash.truncate(((2 * n) + 3) * 32);
to_hash.extend(L.compress().to_bytes());

View file

@ -2,4 +2,4 @@ mod send;
pub(crate) use send::test_send;
mod bitcoin;
mod monero;
mod monero;

View file

@ -7,6 +7,8 @@ use async_trait::async_trait;
use rand_core::OsRng;
use frost::Participant;
use crate::{
NetworkError, Network,
coin::Coin,
@ -15,11 +17,11 @@ use crate::{
#[derive(Clone)]
struct LocalNetwork {
i: u16,
i: Participant,
size: u16,
round: usize,
#[allow(clippy::type_complexity)]
rounds: Arc<RwLock<Vec<HashMap<u16, Vec<u8>>>>>,
rounds: Arc<RwLock<Vec<HashMap<Participant, Vec<u8>>>>>,
}
impl LocalNetwork {
@ -27,7 +29,12 @@ impl LocalNetwork {
let rounds = Arc::new(RwLock::new(vec![]));
let mut res = vec![];
for i in 1 ..= size {
res.push(LocalNetwork { i, size, round: 0, rounds: rounds.clone() });
res.push(LocalNetwork {
i: Participant::new(i).unwrap(),
size,
round: 0,
rounds: rounds.clone(),
});
}
res
}
@ -35,7 +42,7 @@ impl LocalNetwork {
#[async_trait]
impl Network for LocalNetwork {
async fn round(&mut self, data: Vec<u8>) -> Result<HashMap<u16, Vec<u8>>, NetworkError> {
async fn round(&mut self, data: Vec<u8>) -> Result<HashMap<Participant, Vec<u8>>, NetworkError> {
{
let mut rounds = self.rounds.write().unwrap();
if rounds.len() == self.round {
@ -64,14 +71,14 @@ pub async fn test_send<C: Coin + Clone>(coin: C, fee: C::Fee) {
let latest = coin.get_latest_block_number().await.unwrap();
let mut keys = frost::tests::key_gen::<_, C::Curve>(&mut OsRng);
let threshold = keys[&1].params().t();
let threshold = keys[&Participant::new(1).unwrap()].params().t();
let mut networks = LocalNetwork::new(threshold);
let mut wallets = vec![];
for i in 1 ..= threshold {
let mut wallet = Wallet::new(MemCoinDb::new(), coin.clone());
wallet.acknowledge_block(0, latest);
wallet.add_keys(&WalletKeys::new(keys.remove(&i).unwrap(), 0));
wallet.add_keys(&WalletKeys::new(keys.remove(&Participant::new(i).unwrap()).unwrap(), 0));
wallets.push(wallet);
}