diff --git a/.gitignore b/.gitignore index eb5a316c..a9d37c56 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 9790fea5..00000000 --- a/Cargo.lock +++ /dev/null @@ -1,497 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "base58-monero" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "935c90240f9b7749c80746bf88ad9cb346f34b01ee30ad4d566dfdecd6e3cc6a" -dependencies = [ - "thiserror", -] - -[[package]] -name = "bitvec" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" -dependencies = [ - "crypto-mac", - "digest", - "opaque-debug", -] - -[[package]] -name = "bls12_381" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54757888b09a69be70b5ec303e382a74227392086ba808cb01eeca29233a2397" -dependencies = [ - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "curve25519-dalek" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" -dependencies = [ - "byteorder", - "digest", - "packed_simd_2", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "dalek-ff-group" -version = "0.1.0" -dependencies = [ - "curve25519-dalek", - "ff", - "group", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ff" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" -dependencies = [ - "bitvec", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "fixed-hash" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "frost" -version = "0.1.0" -dependencies = [ - "blake2", - "digest", - "ff", - "group", - "hex", - "jubjub", - "rand", - "rand_core 0.6.3", - "thiserror", -] - -[[package]] -name = "funty" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "group" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" -dependencies = [ - "byteorder", - "ff", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - -[[package]] -name = "jubjub" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "593fc4726ca80edb47ee18ab4d826719e25c2096991a79308b44fb915c6014ef" -dependencies = [ - "bitvec", - "bls12_381", - "ff", - "group", - "rand_core 0.6.3", - "subtle", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.124" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50" - -[[package]] -name = "libm" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" - -[[package]] -name = "monero" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3732061cea7e75dc68ef986e0d5a393b3606c258c996abb4a81b759613ea1a0" -dependencies = [ - "base58-monero", - "curve25519-dalek", - "fixed-hash", - "hex", - "hex-literal", - "sealed", - "thiserror", - "tiny-keccak", -] - -[[package]] -name = "monero-sign" -version = "0.1.0" -dependencies = [ - "blake2", - "curve25519-dalek", - "dalek-ff-group", - "digest", - "ff", - "frost", - "group", - "hex", - "lazy_static", - "monero", - "rand", - "rand_core 0.6.3", - "thiserror", - "tiny-keccak", -] - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "packed_simd_2" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defdcfef86dcc44ad208f71d9ff4ce28df6537a4e0d6b0e8e845cb8ca10059a6" -dependencies = [ - "cfg-if", - "libm", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro2" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.6", -] - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "sealed" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636b9882a0f4cc2039488df89a10eb4b7976d4b6c1917fc0518f3f0f5e2c72ca" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wyz" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" -dependencies = [ - "tap", -] - -[[package]] -name = "zeroize" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/sign/dalek-ff-group/.gitignore b/sign/dalek-ff-group/.gitignore deleted file mode 100644 index 03314f77..00000000 --- a/sign/dalek-ff-group/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Cargo.lock diff --git a/sign/dalek-ff-group/Cargo.toml b/sign/dalek-ff-group/Cargo.toml index 60ef3406..4dcec3cf 100644 --- a/sign/dalek-ff-group/Cargo.toml +++ b/sign/dalek-ff-group/Cargo.toml @@ -11,7 +11,7 @@ rand_core = "0.6" subtle = "2.4" -ff = "0.10" -group = "0.10" +ff = "0.11" +group = "0.11" curve25519-dalek = "3.2" diff --git a/sign/dalek-ff-group/src/lib.rs b/sign/dalek-ff-group/src/lib.rs index b6f15ffe..47f3b7ca 100644 --- a/sign/dalek-ff-group/src/lib.rs +++ b/sign/dalek-ff-group/src/lib.rs @@ -6,7 +6,7 @@ use core::{ use rand_core::RngCore; -use subtle::{Choice, CtOption, ConditionallySelectable}; +use subtle::{Choice, CtOption, ConstantTimeEq, ConditionallySelectable}; pub use curve25519_dalek as dalek; @@ -100,6 +100,10 @@ impl<'a> MulAssign<&'a Scalar> for Scalar { fn mul_assign(&mut self, other: &'a Scalar) { self.0 *= other.0 } } +impl ConstantTimeEq for Scalar { + fn ct_eq(&self, _: &Self) -> Choice { unimplemented!() } +} + impl ConditionallySelectable for Scalar { fn conditional_select(_: &Self, _: &Self, _: Choice) -> Self { unimplemented!() } } @@ -117,7 +121,7 @@ impl Field for Scalar { fn double(&self) -> Self { *self + self } fn invert(&self) -> CtOption { CtOption::new(Self(self.0.invert()), Choice::from(1 as u8)) } fn sqrt(&self) -> CtOption { unimplemented!() } - fn is_zero(&self) -> bool { self.0 == DScalar::zero() } + fn is_zero(&self) -> Choice { Choice::from(if self.0 == DScalar::zero() { 1 } else { 0 }) } fn cube(&self) -> Self { *self * self * self } fn pow_vartime>(&self, _exp: S) -> Self { unimplemented!() } } @@ -130,11 +134,14 @@ impl PrimeField for Scalar { type Repr = [u8; 32]; const NUM_BITS: u32 = 253; const CAPACITY: u32 = 252; - fn from_repr(bytes: [u8; 32]) -> Option { DScalar::from_canonical_bytes(bytes).map(|x| Scalar(x)) } + fn from_repr(bytes: [u8; 32]) -> CtOption { + let scalar = DScalar::from_canonical_bytes(bytes).map(|x| Scalar(x)); + CtOption::new(scalar.unwrap_or(Scalar::zero()), Choice::from(if scalar.is_some() { 1 } else { 0 })) + } fn to_repr(&self) -> [u8; 32] { self.0.to_bytes() } const S: u32 = 0; - fn is_odd(&self) -> bool { unimplemented!() } + fn is_odd(&self) -> Choice { unimplemented!() } fn multiplicative_generator() -> Self { unimplemented!() } fn root_of_unity() -> Self { unimplemented!() } } diff --git a/sign/frost/.gitignore b/sign/frost/.gitignore deleted file mode 100644 index 03314f77..00000000 --- a/sign/frost/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Cargo.lock diff --git a/sign/frost/Cargo.toml b/sign/frost/Cargo.toml index df7f93c8..92205db8 100644 --- a/sign/frost/Cargo.toml +++ b/sign/frost/Cargo.toml @@ -7,17 +7,16 @@ authors = ["kayabaNerve (Luke Parker) "] edition = "2021" [dependencies] -digest = "0.9" -blake2 = "0.9" +digest = "0.10" rand_core = "0.6" -ff = "0.10" -group = "0.10" +ff = "0.11" +group = "0.11" thiserror = "1" [dev-dependencies] -hex = "0.4" rand = "0.8" -jubjub = "0.7" +sha2 = "0.10" +k256 = { version = "0.10", features = ["arithmetic"] } diff --git a/sign/frost/src/algorithm.rs b/sign/frost/src/algorithm.rs index ab1f0642..58325bf7 100644 --- a/sign/frost/src/algorithm.rs +++ b/sign/frost/src/algorithm.rs @@ -1,13 +1,13 @@ use core::{marker::PhantomData, fmt::Debug}; use rand_core::{RngCore, CryptoRng}; -use digest::Digest; use group::Group; use crate::{Curve, FrostError, sign}; -pub trait Algorithm: Clone + Debug { +/// Algorithm to use FROST with +pub trait Algorithm: Clone { /// The resulting type of the signatures this algorithm will produce type Signature: Clone + Debug; @@ -59,40 +59,24 @@ pub trait Algorithm: Clone + Debug { ) -> bool; } -pub trait Hram: PartialEq + Eq + Copy + Clone + Debug { +pub trait Hram: Clone { + /// HRAM function to generate a challenge + /// H2 from the IETF draft despite having a different argument set (not pre-formatted) #[allow(non_snake_case)] - fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F; + fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F; } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Blake2bHram {} -impl Hram for Blake2bHram { - #[allow(non_snake_case)] - fn hram(R: &C::G, A: &C::G, m: &[u8]) -> C::F { - C::F_from_bytes_wide( - blake2::Blake2b::new() - .chain(C::G_to_bytes(R)) - .chain(C::G_to_bytes(A)) - .chain(m) - .finalize() - .as_slice() - .try_into() - .expect("couldn't convert a 64-byte hash to a 64-byte array") - ) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Schnorr { +#[derive(Clone)] +pub struct Schnorr> { c: Option, - hram: PhantomData, + _hram: PhantomData, } -impl Schnorr { +impl> Schnorr { pub fn new() -> Schnorr { Schnorr { c: None, - hram: PhantomData + _hram: PhantomData } } } @@ -104,7 +88,8 @@ pub struct SchnorrSignature { pub s: C::F, } -impl Algorithm for Schnorr { +/// Implementation of Schnorr signatures for use with FROST +impl> Algorithm for Schnorr { type Signature = SchnorrSignature; fn context(&self) -> Vec { @@ -141,7 +126,7 @@ impl Algorithm for Schnorr { nonce: C::F, msg: &[u8], ) -> C::F { - let c = H::hram::(&nonce_sum, ¶ms.group_key(), msg); + let c = H::hram(&nonce_sum, ¶ms.group_key(), msg); self.c = Some(c); nonce + (params.secret_share() * c) diff --git a/sign/frost/src/key_gen.rs b/sign/frost/src/key_gen.rs index 5c895db2..4354856a 100644 --- a/sign/frost/src/key_gen.rs +++ b/sign/frost/src/key_gen.rs @@ -1,13 +1,24 @@ -use core::{convert::{TryFrom, TryInto}, cmp::min, fmt}; +use core::{convert::TryFrom, cmp::min, fmt}; use rand_core::{RngCore, CryptoRng}; -use blake2::{Digest, Blake2b}; use ff::{Field, PrimeField}; use group::Group; use crate::{Curve, MultisigParams, MultisigKeys, FrostError}; +#[allow(non_snake_case)] +fn challenge(l: usize, context: &str, R: &[u8], Am: &[u8]) -> C::F { + let mut c = Vec::with_capacity(8 + context.len() + R.len() + Am.len()); + c.extend(&u64::try_from(l).unwrap().to_le_bytes()); + c.extend(context.as_bytes()); + c.extend(R); // R + c.extend(Am); // A of the first commitment, which is what we're proving we have the private key + // for + // m of the rest of the commitments, authenticating them + C::hash_to_F(&c) +} + // Implements steps 1 through 3 of round 1 of FROST DKG. Returns the coefficients, commitments, and // the serialized commitments to be broadcasted over an authenticated channel to all parties // TODO: This potentially could return a much more robust serialized message, including a signature @@ -44,19 +55,7 @@ fn generate_key_r1( let k = C::F::random(rng); #[allow(non_snake_case)] let R = C::generator_table() * k; - let c = C::F_from_bytes_wide( - Blake2b::new() - .chain(&u64::try_from(params.i).unwrap().to_le_bytes()) - .chain(context.as_bytes()) - .chain(&C::G_to_bytes(&R)) // R - .chain(&serialized) // A of the first commitment, which is what we're proving we have - // the private key for - // m of the rest of the commitments, authenticating them - .finalize() - .as_slice() - .try_into() - .expect("couldn't convert a 64-byte hash to a 64-byte array") - ); + let c = challenge::(params.i, context, &C::G_to_bytes(&R), &serialized); let s = k + (coefficients[0] * c); serialized.extend(&C::G_to_bytes(&R)); @@ -155,17 +154,11 @@ fn verify_r1( ); points.push(C::generator()); - let c = C::F_from_bytes_wide( - Blake2b::new() - // Bounded by n which is already checked to be within the u64 range - .chain(&u64::try_from(l).unwrap().to_le_bytes()) - .chain(context.as_bytes()) - .chain(&serialized[l][commitments_len .. commitments_len + C::G_len()]) - .chain(&serialized[l][0 .. commitments_len]) - .finalize() - .as_slice() - .try_into() - .expect("couldn't convert a 64-byte hash to a 64-byte array") + let c = challenge::( + l, + context, + &serialized[l][commitments_len .. commitments_len + C::G_len()], + &serialized[l][0 .. commitments_len] ); if first { @@ -195,17 +188,11 @@ fn verify_r1( &serialized[l][commitments_len + C::G_len() .. serialized[l].len()] ).map_err(|_| FrostError::InvalidProofOfKnowledge(l))?; - let c = C::F_from_bytes_wide( - Blake2b::new() - // Bounded by n which is already checked to be within the u64 range - .chain(&u64::try_from(l).unwrap().to_le_bytes()) - .chain(context.as_bytes()) - .chain(&serialized[l][commitments_len .. commitments_len + C::G_len()]) - .chain(&serialized[l][0 .. commitments_len]) - .finalize() - .as_slice() - .try_into() - .expect("couldn't convert a 64-byte hash to a 64-byte array") + let c = challenge::( + l, + context, + &serialized[l][commitments_len .. commitments_len + C::G_len()], + &serialized[l][0 .. commitments_len] ); if R != ((C::generator_table() * s) + (commitments[l][0] * (C::F::zero() - &c))) { @@ -389,6 +376,7 @@ impl fmt::Display for State { } /// State machine which manages key generation +#[allow(non_snake_case)] pub struct StateMachine { params: MultisigParams, context: String, @@ -396,7 +384,7 @@ pub struct StateMachine { coefficients: Option>, our_commitments: Option>, secret: Option, - commitments: Option>>, + commitments: Option>> } impl StateMachine { @@ -410,7 +398,7 @@ impl StateMachine { coefficients: None, our_commitments: None, secret: None, - commitments: None, + commitments: None } } diff --git a/sign/frost/src/lib.rs b/sign/frost/src/lib.rs index 245b05e0..f898b301 100644 --- a/sign/frost/src/lib.rs +++ b/sign/frost/src/lib.rs @@ -14,11 +14,10 @@ pub mod sign; pub enum CurveError { #[error("invalid length for data (expected {0}, got {0})")] InvalidLength(usize, usize), - // Push towards hex encoding in error messages - #[error("invalid scalar ({0})")] - InvalidScalar(String), - #[error("invalid point ({0})")] - InvalidPoint(String), + #[error("invalid scalar")] + InvalidScalar, + #[error("invalid point")] + InvalidPoint, } /// Unified trait to manage a field/group @@ -58,6 +57,16 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug { // This could also be written as -> Option with None for not implemented fn multiexp_vartime(scalars: &[Self::F], points: &[Self::G]) -> Self::G; + /// Hash the message as needed to calculate the binding factor + /// H3 from the IETF draft + fn hash_msg(msg: &[u8]) -> Vec; + + /// Field element from hash, used in key generation and to calculate the binding factor + /// H1 from the IETF draft + /// Key generation uses it as if it's H2 to generate a challenge for a Proof of Knowledge + #[allow(non_snake_case)] + fn hash_to_F(data: &[u8]) -> Self::F; + // The following methods would optimally be F:: and G:: yet developers can't control F/G // They can control a trait they pass into this library @@ -82,10 +91,6 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug { #[allow(non_snake_case)] fn F_from_le_slice(slice: &[u8]) -> Result; - /// Field element from slice. Must support reducing the input into a valid field element - #[allow(non_snake_case)] - fn F_from_le_slice_unreduced(slice: &[u8]) -> Self::F; - /// Group element from slice. Should be canonical #[allow(non_snake_case)] fn G_from_slice(slice: &[u8]) -> Result; @@ -97,10 +102,6 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug { /// Obtain a vector of the byte encoding of G #[allow(non_snake_case)] fn G_to_bytes(g: &Self::G) -> Vec; - - /// Takes 64-bytes and returns a scalar reduced mod n - #[allow(non_snake_case)] - fn F_from_bytes_wide(bytes: [u8; 64]) -> Self::F; } /// Parameters for a multisig diff --git a/sign/frost/src/sign.rs b/sign/frost/src/sign.rs index 58adcfdc..ec1cbaf4 100644 --- a/sign/frost/src/sign.rs +++ b/sign/frost/src/sign.rs @@ -2,19 +2,12 @@ use core::{convert::{TryFrom, TryInto}, cmp::min, fmt}; use std::rc::Rc; use rand_core::{RngCore, CryptoRng}; -use blake2::{Digest, Blake2b}; use ff::{Field, PrimeField}; use group::Group; use crate::{Curve, MultisigParams, MultisigKeys, FrostError, algorithm::Algorithm}; -// Matches ZCash's FROST Jubjub implementation -const BINDING_DST: &'static [u8; 9] = b"FROST_rho"; -// Doesn't match ZCash except for their desire for messages to be hashed in advance before used -// here and domain separated -const BINDING_MESSAGE_DST: &'static [u8; 17] = b"FROST_rho_message"; - /// Calculate the lagrange coefficient pub fn lagrange( i: usize, @@ -198,7 +191,18 @@ fn sign_with_share>( #[allow(non_snake_case)] let mut B = Vec::with_capacity(multisig_params.n + 1); B.push(None); - let mut b: Vec = vec![]; + + // Commitments + a presumed 32-byte hash of the message + let mut b: Vec = Vec::with_capacity((multisig_params.n * 2 * C::G_len()) + 32); + + // If the offset functionality provided by this library is in use, include it in the binding + // factor + if params.keys.offset.is_some() { + b.extend(&C::F_to_le_bytes(¶ms.keys.offset.unwrap())); + } + // Also include any context the algorithm may want to specify + b.extend(¶ms.algorithm.context()); + for l in 1 ..= multisig_params.n { if l == multisig_params.i { if commitments[l].is_some() { @@ -206,8 +210,7 @@ fn sign_with_share>( } B.push(Some(our_preprocess.commitments)); - // Slightly more robust - b.extend(&u64::try_from(l).unwrap().to_le_bytes()); + b.extend(&u16::try_from(l).unwrap().to_le_bytes()); b.extend(&our_preprocess.serialized[0 .. commit_len]); continue; } @@ -237,46 +240,26 @@ fn sign_with_share>( let E = C::G_from_slice(&commitments[C::G_len() .. commitments_len]) .map_err(|_| FrostError::InvalidCommitment(l))?; B.push(Some([D, E])); - b.extend(&u64::try_from(l).unwrap().to_le_bytes()); + b.extend(&u16::try_from(l).unwrap().to_le_bytes()); b.extend(&commitments[0 .. commit_len]); } - let offset = if params.keys.offset.is_some() { - C::F_to_le_bytes(¶ms.keys.offset.unwrap()) - } else { - vec![] - }; - let context = params.algorithm.context(); - let mut p = Vec::with_capacity(multisig_params.t); - let mut pi = C::F::zero(); - for l in ¶ms.view.included { - p.push( - C::F_from_bytes_wide( - Blake2b::new() - .chain(BINDING_DST) - .chain(u64::try_from(*l).unwrap().to_le_bytes()) - .chain(Blake2b::new().chain(BINDING_MESSAGE_DST).chain(msg).finalize()) - .chain(&offset) - .chain(&context) - .chain(&b) - .finalize() - .as_slice() - .try_into() - .expect("couldn't convert a 64-byte hash to a 64-byte array") - ) - ); + b.extend(&C::hash_msg(&msg)); + let b = C::hash_to_F(&b); - let view = ¶ms.view; + let view = ¶ms.view; + for l in ¶ms.view.included { params.algorithm.process_addendum( view, *l, B[*l].as_ref().unwrap(), - &p[p.len() - 1], + &b, if *l == multisig_params.i { - pi = p[p.len() - 1]; &our_preprocess.serialized[commitments_len .. our_preprocess.serialized.len()] } else { - &commitments[*l].as_ref().unwrap()[commitments_len .. commitments[*l].as_ref().unwrap().len()] + &commitments[*l].as_ref().unwrap()[ + commitments_len .. commitments[*l].as_ref().unwrap().len() + ] } )?; } @@ -288,7 +271,7 @@ fn sign_with_share>( for i in 0 .. params.view.included.len() { let commitments = B[params.view.included[i]].unwrap(); #[allow(non_snake_case)] - let this_R = commitments[0] + (commitments[1] * p[i]); + let this_R = commitments[0] + (commitments[1] * b); Ris.push(this_R); R += this_R; } @@ -297,7 +280,7 @@ fn sign_with_share>( let share = params.algorithm.sign_share( view, R, - our_preprocess.nonces[0] + (our_preprocess.nonces[1] * pi), + our_preprocess.nonces[0] + (our_preprocess.nonces[1] * b), msg ); Ok((Package { Ris, R, share }, C::F_to_le_bytes(&share))) diff --git a/sign/frost/tests/common.rs b/sign/frost/tests/common.rs index 3e610d09..0ef2902b 100644 --- a/sign/frost/tests/common.rs +++ b/sign/frost/tests/common.rs @@ -1,19 +1,28 @@ use core::convert::TryInto; -use group::{Group, GroupEncoding}; +use digest::Digest; +use ff::PrimeField; +use group::GroupEncoding; -use jubjub::{Fr, SubgroupPoint}; -use frost::{CurveError, Curve, multiexp_vartime}; +use sha2::{Sha256, Sha512}; + +use k256::{ + elliptic_curve::{generic_array::GenericArray, bigint::{ArrayEncoding, U512}, ops::Reduce}, + Scalar, + ProjectivePoint +}; + +use frost::{CurveError, Curve, multiexp_vartime, algorithm::Hram}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Jubjub; -impl Curve for Jubjub { - type F = Fr; - type G = SubgroupPoint; - type T = SubgroupPoint; +pub struct Secp256k1; +impl Curve for Secp256k1 { + type F = Scalar; + type G = ProjectivePoint; + type T = ProjectivePoint; fn id() -> String { - "Jubjub".to_string() + "secp256k1".to_string() } fn id_len() -> u8 { @@ -21,15 +30,28 @@ impl Curve for Jubjub { } fn generator() -> Self::G { - Self::G::generator() + Self::G::GENERATOR } fn generator_table() -> Self::T { - Self::G::generator() + Self::G::GENERATOR } fn multiexp_vartime(scalars: &[Self::F], points: &[Self::G]) -> Self::G { - multiexp_vartime::(scalars, points) + multiexp_vartime::(scalars, points) + } + + // The IETF draft doesn't specify a secp256k1 ciphersuite + // This test just uses the simplest ciphersuite which would still be viable to deploy + fn hash_msg(msg: &[u8]) -> Vec { + (&Sha256::digest(msg)).to_vec() + } + + // Use wide reduction for security + fn hash_to_F(data: &[u8]) -> Self::F { + Scalar::from_uint_reduced( + U512::from_be_byte_array(Sha512::new().chain_update("rho").chain_update(data).finalize()) + ) } fn F_len() -> usize { @@ -37,46 +59,54 @@ impl Curve for Jubjub { } fn G_len() -> usize { - 32 + 33 } fn F_from_le_slice(slice: &[u8]) -> Result { - let scalar = Self::F::from_bytes( - &slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))? - ); - if scalar.is_some().into() { - Ok(scalar.unwrap()) - } else { - Err(CurveError::InvalidScalar(hex::encode(slice))) + let mut bytes: [u8; 32] = slice.try_into().map_err( + |_| CurveError::InvalidLength(32, slice.len()) + )?; + bytes.reverse(); + let scalar = Scalar::from_repr(bytes.into()); + if scalar.is_none().unwrap_u8() == 1 { + Err(CurveError::InvalidScalar)?; } - } - - fn F_from_le_slice_unreduced(slice: &[u8]) -> Self::F { - let mut wide: [u8; 64] = [0; 64]; - wide[..slice.len()].copy_from_slice(slice); - Self::F::from_bytes_wide(&wide) + Ok(scalar.unwrap()) } fn G_from_slice(slice: &[u8]) -> Result { - let point = Self::G::from_bytes( - &slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))? - ); - if point.is_some().into() { - Ok(point.unwrap()) - } else { - Err(CurveError::InvalidPoint(hex::encode(slice)))? + let point = ProjectivePoint::from_bytes(GenericArray::from_slice(slice)); + if point.is_none().unwrap_u8() == 1 { + Err(CurveError::InvalidScalar)?; } + Ok(point.unwrap()) } fn F_to_le_bytes(f: &Self::F) -> Vec { - f.to_bytes().to_vec() + let mut res: [u8; 32] = f.to_bytes().into(); + res.reverse(); + res.to_vec() } fn G_to_bytes(g: &Self::G) -> Vec { - g.to_bytes().to_vec() - } - - fn F_from_bytes_wide(bytes: [u8; 64]) -> Self::F { - Self::F::from_bytes_wide(&bytes) + (&g.to_bytes()).to_vec() + } +} + +#[allow(non_snake_case)] +#[derive(Clone)] +pub struct TestHram {} +impl Hram for TestHram { + #[allow(non_snake_case)] + fn hram(R: &ProjectivePoint, A: &ProjectivePoint, m: &[u8]) -> Scalar { + Scalar::from_uint_reduced( + U512::from_be_byte_array( + Sha512::new() + .chain_update(Secp256k1::G_to_bytes(R)) + .chain_update(Secp256k1::G_to_bytes(A)) + .chain_update(m) + .finalize() + ) + ) } } diff --git a/sign/frost/tests/key_gen_and_sign.rs b/sign/frost/tests/key_gen_and_sign.rs index b7146049..382cc3b5 100644 --- a/sign/frost/tests/key_gen_and_sign.rs +++ b/sign/frost/tests/key_gen_and_sign.rs @@ -2,16 +2,19 @@ use std::rc::Rc; use rand::{RngCore, rngs::OsRng}; +use digest::Digest; +use sha2::Sha256; + use frost::{ Curve, MultisigParams, MultisigKeys, key_gen, - algorithm::{Algorithm, Schnorr, Blake2bHram, SchnorrSignature}, + algorithm::{Algorithm, Schnorr, SchnorrSignature}, sign }; mod common; -use common::Jubjub; +use common::{Secp256k1, TestHram}; const PARTICIPANTS: usize = 8; @@ -81,7 +84,7 @@ fn key_gen_and_sign() { ).unwrap() ); machines.push( - key_gen::StateMachine::::new( + key_gen::StateMachine::::new( params[i - 1], "FF/Group Rust key_gen test".to_string() ) @@ -114,7 +117,7 @@ fn key_gen_and_sign() { let these_keys = machines[i - 1].complete(our_secret_shares).unwrap(); assert_eq!( - MultisigKeys::::deserialize(&these_keys.serialize()).unwrap(), + MultisigKeys::::deserialize(&these_keys.serialize()).unwrap(), these_keys ); keys.push(Rc::new(these_keys.clone())); @@ -130,14 +133,14 @@ fn key_gen_and_sign() { assert_eq!(group_key.unwrap(), these_keys.group_key()); } - sign(Schnorr::::new(), keys.clone()); + sign(Schnorr::::new(), keys.clone()); let mut randomization = [0; 64]; (&mut OsRng).fill_bytes(&mut randomization); sign( - Schnorr::::new(), + Schnorr::::new(), keys.iter().map( - |keys| Rc::new(keys.offset(Jubjub::F_from_bytes_wide(randomization))) + |keys| Rc::new(keys.offset(Secp256k1::hash_to_F(&Sha256::digest(&randomization)))) ).collect() ); } diff --git a/sign/monero/.gitignore b/sign/monero/.gitignore index 2337a381..9871762c 100644 --- a/sign/monero/.gitignore +++ b/sign/monero/.gitignore @@ -1,3 +1 @@ -Cargo.lock - -.build +c/.build diff --git a/sign/monero/Cargo.toml b/sign/monero/Cargo.toml index 7f64829b..121e4cca 100644 --- a/sign/monero/Cargo.toml +++ b/sign/monero/Cargo.toml @@ -12,16 +12,13 @@ thiserror = "1" rand_core = "0.6" -hex = "0.4" - -digest = "0.9" tiny-keccak = { version = "2.0", features = ["keccak"] } -blake2 = "0.9" +blake2 = "0.10" curve25519-dalek = { version = "3.2", features = ["std", "simd_backend"] } -ff = { version = "0.10", optional = true } -group = { version = "0.10", optional = true } +ff = { version = "0.11", optional = true } +group = { version = "0.11", optional = true } dalek-ff-group = { path = "../dalek-ff-group", optional = true } frost = { path = "../frost", optional = true } diff --git a/sign/monero/src/clsag/mod.rs b/sign/monero/src/clsag/mod.rs index 19a4ca14..b1cab031 100644 --- a/sign/monero/src/clsag/mod.rs +++ b/sign/monero/src/clsag/mod.rs @@ -1,7 +1,6 @@ use rand_core::{RngCore, CryptoRng}; -use digest::Digest; -use blake2::Blake2b; +use blake2::{Digest, Blake2b512}; use curve25519_dalek::{ constants::ED25519_BASEPOINT_TABLE, @@ -82,10 +81,10 @@ pub(crate) fn sign_core( let z; let mut next_rand = rand_source; - next_rand = Blake2b::digest(&next_rand).as_slice().try_into().unwrap(); + next_rand = Blake2b512::digest(&next_rand).as_slice().try_into().unwrap(); { let a = Scalar::from_bytes_mod_order_wide(&next_rand); - next_rand = Blake2b::digest(&next_rand).as_slice().try_into().unwrap(); + next_rand = Blake2b512::digest(&next_rand).as_slice().try_into().unwrap(); C_out = commitment(&a, ssr.amount); for member in &ssr.ring { @@ -149,7 +148,7 @@ pub(crate) fn sign_core( s.resize(n, Scalar::zero()); while j != i { s[j] = Scalar::from_bytes_mod_order_wide(&next_rand); - next_rand = Blake2b::digest(&next_rand).as_slice().try_into().unwrap(); + next_rand = Blake2b512::digest(&next_rand).as_slice().try_into().unwrap(); let c_p = mu_P * c; let c_c = mu_C * c; diff --git a/sign/monero/src/clsag/multisig.rs b/sign/monero/src/clsag/multisig.rs index c9910438..4fbb3957 100644 --- a/sign/monero/src/clsag/multisig.rs +++ b/sign/monero/src/clsag/multisig.rs @@ -1,7 +1,6 @@ use rand_core::{RngCore, CryptoRng}; -use digest::Digest; -use blake2::Blake2b; +use blake2::{Digest, Blake2b512}; use curve25519_dalek::{ constants::ED25519_BASEPOINT_TABLE, @@ -11,7 +10,7 @@ use curve25519_dalek::{ use dalek_ff_group as dfg; use group::Group; -use frost::{Curve, FrostError, algorithm::Algorithm}; +use frost::{Curve, FrostError, algorithm::Algorithm, sign::ParamsView}; use monero::util::ringct::{Key, Clsag}; @@ -94,11 +93,11 @@ impl Algorithm for Multisig { fn preprocess_addendum( rng: &mut R, - group_key: &dfg::EdwardsPoint, + view: &ParamsView, nonces: &[dfg::Scalar; 2] ) -> Vec { #[allow(non_snake_case)] - let H = hash_to_point(&group_key.0); + let H = hash_to_point(&view.group_key().0); let h0 = nonces[0].0 * H; let h1 = nonces[1].0 * H; // 32 + 32 + 64 + 64 @@ -112,6 +111,7 @@ impl Algorithm for Multisig { fn process_addendum( &mut self, + _: &ParamsView, l: usize, commitments: &[dfg::EdwardsPoint; 2], p: &dfg::Scalar, @@ -147,19 +147,32 @@ impl Algorithm for Multisig { fn sign_share( &mut self, - _: dfg::EdwardsPoint, - secret: dfg::Scalar, - nonce: dfg::Scalar, + view: &ParamsView, nonce_sum: dfg::EdwardsPoint, - _: &[u8], + nonce: dfg::Scalar, + _: &[u8] ) -> dfg::Scalar { // Use everyone's commitments to derive a random source all signers can agree upon // Cannot be manipulated to effect and all signers must, and will, know this - let rand_source = Blake2b::new().chain("Clsag_randomness").chain(&self.b).finalize().as_slice().try_into().unwrap(); - #[allow(non_snake_case)] - let (clsag, c, mu_C, z, mu_P, C_out) = sign_core(rand_source, self.image, &self.msg, &self.ssr, nonce_sum.0, self.AH.0); + let rand_source = Keccak::v512() + .chain("Clsag_randomness") + .chain(&self.b) + .finalize() + .as_slice() + .try_into() + .unwrap(); - let share = dfg::Scalar(nonce.0 - (c * (mu_P * secret.0))); + #[allow(non_snake_case)] + let (clsag, c, mu_C, z, mu_P, C_out) = sign_core( + rand_source, + self.image, + &self.msg, + &self.ssr, + nonce_sum.0, + self.AH.0 + ); + + let share = dfg::Scalar(nonce.0 - (c * (mu_P * view.secret_share().0))); self.interim = Some(ClsagSignInterim { c, mu_C, z, mu_P, clsag, C_out }); share diff --git a/sign/monero/src/frost.rs b/sign/monero/src/frost.rs index 59660c46..41d674ce 100644 --- a/sign/monero/src/frost.rs +++ b/sign/monero/src/frost.rs @@ -2,8 +2,7 @@ use core::convert::TryInto; use rand_core::{RngCore, CryptoRng}; -use digest::Digest; -use blake2::Blake2b; +use blake2::{Digest, Blake2b512}; use curve25519_dalek::{ constants::ED25519_BASEPOINT_TABLE as DTable, @@ -49,6 +48,14 @@ impl Curve for Ed25519 { EdwardsPoint(DPoint::vartime_multiscalar_mul(scalars, points)) } + fn hash_msg(msg: &[u8]) -> Vec { + Blake2b512::digest(msg) + } + + fn hash_to_F(data: &[u8]) -> Self::F { + dfg::Scalar::from_hash(Blake2b512::new().chain(data)) + } + fn F_len() -> usize { 32 } @@ -61,19 +68,13 @@ impl Curve for Ed25519 { let scalar = Self::F::from_repr( slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))? ); - if scalar.is_some() { + if scalar.is_some().unwrap_u8() == 1 { Ok(scalar.unwrap()) } else { - Err(CurveError::InvalidScalar(hex::encode(slice))) + Err(CurveError::InvalidScalar) } } - fn F_from_le_slice_unreduced(slice: &[u8]) -> Self::F { - let mut wide: [u8; 64] = [0; 64]; - wide[..slice.len()].copy_from_slice(slice); - dfg::Scalar::from_bytes_mod_order_wide(&wide) - } - fn G_from_slice(slice: &[u8]) -> Result { let point = dfg::CompressedEdwardsY::new( slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))? @@ -83,11 +84,11 @@ impl Curve for Ed25519 { let point = point.unwrap(); // Ban torsioned points if !point.is_torsion_free() { - Err(CurveError::InvalidPoint(hex::encode(slice)))? + Err(CurveError::InvalidPoint)? } Ok(point) } else { - Err(CurveError::InvalidPoint(hex::encode(slice)))? + Err(CurveError::InvalidPoint) } } @@ -98,10 +99,6 @@ impl Curve for Ed25519 { fn G_to_bytes(g: &Self::G) -> Vec { g.compress().to_bytes().to_vec() } - - fn F_from_bytes_wide(bytes: [u8; 64]) -> Self::F { - dfg::Scalar::from_bytes_mod_order_wide(&bytes) - } } // Used to prove legitimacy in several locations @@ -124,7 +121,7 @@ impl DLEqProof { let R2 = r * H; let c = DScalar::from_hash( - Blake2b::new() + Blake2b512::new() .chain(R1.compress().to_bytes()) .chain(R2.compress().to_bytes()) .chain((secret * &DTable).compress().to_bytes()) @@ -148,7 +145,7 @@ impl DLEqProof { let R2 = (s * H) - (c * alt); let expected_c = DScalar::from_hash( - Blake2b::new() + Blake2b512::new() .chain(R1.compress().to_bytes()) .chain(R2.compress().to_bytes()) .chain(primary.compress().to_bytes())