mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-16 17:07:35 +00:00
Update FROST signing to match the IETF draft
Modernizes dependencies
This commit is contained in:
parent
76a6ff46be
commit
e22dcb1441
18 changed files with 226 additions and 724 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
target
|
||||
Cargo.lock
|
||||
|
|
497
Cargo.lock
generated
497
Cargo.lock
generated
|
@ -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"
|
1
sign/dalek-ff-group/.gitignore
vendored
1
sign/dalek-ff-group/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
Cargo.lock
|
|
@ -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"
|
||||
|
|
|
@ -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<Self> { CtOption::new(Self(self.0.invert()), Choice::from(1 as u8)) }
|
||||
fn sqrt(&self) -> CtOption<Self> { 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<S: AsRef<[u64]>>(&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<Self> { DScalar::from_canonical_bytes(bytes).map(|x| Scalar(x)) }
|
||||
fn from_repr(bytes: [u8; 32]) -> CtOption<Self> {
|
||||
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!() }
|
||||
}
|
||||
|
|
1
sign/frost/.gitignore
vendored
1
sign/frost/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
Cargo.lock
|
|
@ -7,17 +7,16 @@ authors = ["kayabaNerve (Luke Parker) <lukeparker5132@gmail.com>"]
|
|||
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"] }
|
||||
|
|
|
@ -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<C: Curve>: Clone + Debug {
|
||||
/// Algorithm to use FROST with
|
||||
pub trait Algorithm<C: Curve>: Clone {
|
||||
/// The resulting type of the signatures this algorithm will produce
|
||||
type Signature: Clone + Debug;
|
||||
|
||||
|
@ -59,40 +59,24 @@ pub trait Algorithm<C: Curve>: Clone + Debug {
|
|||
) -> bool;
|
||||
}
|
||||
|
||||
pub trait Hram: PartialEq + Eq + Copy + Clone + Debug {
|
||||
pub trait Hram<C: Curve>: 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<C: Curve>(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<C: Curve>(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<C: Curve, H: Hram> {
|
||||
#[derive(Clone)]
|
||||
pub struct Schnorr<C: Curve, H: Hram<C>> {
|
||||
c: Option<C::F>,
|
||||
hram: PhantomData<H>,
|
||||
_hram: PhantomData<H>,
|
||||
}
|
||||
|
||||
impl<C: Curve, H: Hram> Schnorr<C, H> {
|
||||
impl<C: Curve, H: Hram<C>> Schnorr<C, H> {
|
||||
pub fn new() -> Schnorr<C, H> {
|
||||
Schnorr {
|
||||
c: None,
|
||||
hram: PhantomData
|
||||
_hram: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +88,8 @@ pub struct SchnorrSignature<C: Curve> {
|
|||
pub s: C::F,
|
||||
}
|
||||
|
||||
impl<C: Curve, H: Hram> Algorithm<C> for Schnorr<C, H> {
|
||||
/// Implementation of Schnorr signatures for use with FROST
|
||||
impl<C: Curve, H: Hram<C>> Algorithm<C> for Schnorr<C, H> {
|
||||
type Signature = SchnorrSignature<C>;
|
||||
|
||||
fn context(&self) -> Vec<u8> {
|
||||
|
@ -141,7 +126,7 @@ impl<C: Curve, H: Hram> Algorithm<C> for Schnorr<C, H> {
|
|||
nonce: C::F,
|
||||
msg: &[u8],
|
||||
) -> C::F {
|
||||
let c = H::hram::<C>(&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)
|
||||
|
|
|
@ -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<C: Curve>(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<R: RngCore + CryptoRng, C: Curve>(
|
|||
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::<C>(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<R: RngCore + CryptoRng, C: Curve>(
|
|||
);
|
||||
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::<C>(
|
||||
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<R: RngCore + CryptoRng, C: Curve>(
|
|||
&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::<C>(
|
||||
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<C: Curve> {
|
||||
params: MultisigParams,
|
||||
context: String,
|
||||
|
@ -396,7 +384,7 @@ pub struct StateMachine<C: Curve> {
|
|||
coefficients: Option<Vec<C::F>>,
|
||||
our_commitments: Option<Vec<C::G>>,
|
||||
secret: Option<C::F>,
|
||||
commitments: Option<Vec<Vec<C::G>>>,
|
||||
commitments: Option<Vec<Vec<C::G>>>
|
||||
}
|
||||
|
||||
impl<C: Curve> StateMachine<C> {
|
||||
|
@ -410,7 +398,7 @@ impl<C: Curve> StateMachine<C> {
|
|||
coefficients: None,
|
||||
our_commitments: None,
|
||||
secret: None,
|
||||
commitments: None,
|
||||
commitments: None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<C::G> 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<u8>;
|
||||
|
||||
/// 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<Self::F, CurveError>;
|
||||
|
||||
/// 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<Self::G, CurveError>;
|
||||
|
@ -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<u8>;
|
||||
|
||||
/// 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
|
||||
|
|
|
@ -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<F: PrimeField>(
|
||||
i: usize,
|
||||
|
@ -198,7 +191,18 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
|
|||
#[allow(non_snake_case)]
|
||||
let mut B = Vec::with_capacity(multisig_params.n + 1);
|
||||
B.push(None);
|
||||
let mut b: Vec<u8> = vec![];
|
||||
|
||||
// Commitments + a presumed 32-byte hash of the message
|
||||
let mut b: Vec<u8> = 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<C: Curve, A: Algorithm<C>>(
|
|||
}
|
||||
|
||||
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<C: Curve, A: Algorithm<C>>(
|
|||
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<C: Curve, A: Algorithm<C>>(
|
|||
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<C: Curve, A: Algorithm<C>>(
|
|||
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)))
|
||||
|
|
|
@ -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::<Jubjub>(scalars, points)
|
||||
multiexp_vartime::<Secp256k1>(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<u8> {
|
||||
(&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<Self::F, CurveError> {
|
||||
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<Self::G, CurveError> {
|
||||
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<u8> {
|
||||
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<u8> {
|
||||
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<Secp256k1> 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()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<Jubjub>::new(
|
||||
key_gen::StateMachine::<Secp256k1>::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::<Jubjub>::deserialize(&these_keys.serialize()).unwrap(),
|
||||
MultisigKeys::<Secp256k1>::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::<Jubjub, Blake2bHram>::new(), keys.clone());
|
||||
sign(Schnorr::<Secp256k1, TestHram>::new(), keys.clone());
|
||||
|
||||
let mut randomization = [0; 64];
|
||||
(&mut OsRng).fill_bytes(&mut randomization);
|
||||
sign(
|
||||
Schnorr::<Jubjub, Blake2bHram>::new(),
|
||||
Schnorr::<Secp256k1, TestHram>::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()
|
||||
);
|
||||
}
|
||||
|
|
4
sign/monero/.gitignore
vendored
4
sign/monero/.gitignore
vendored
|
@ -1,3 +1 @@
|
|||
Cargo.lock
|
||||
|
||||
.build
|
||||
c/.build
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<Ed25519> for Multisig {
|
|||
|
||||
fn preprocess_addendum<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
group_key: &dfg::EdwardsPoint,
|
||||
view: &ParamsView<Ed25519>,
|
||||
nonces: &[dfg::Scalar; 2]
|
||||
) -> Vec<u8> {
|
||||
#[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<Ed25519> for Multisig {
|
|||
|
||||
fn process_addendum(
|
||||
&mut self,
|
||||
_: &ParamsView<Ed25519>,
|
||||
l: usize,
|
||||
commitments: &[dfg::EdwardsPoint; 2],
|
||||
p: &dfg::Scalar,
|
||||
|
@ -147,19 +147,32 @@ impl Algorithm<Ed25519> for Multisig {
|
|||
|
||||
fn sign_share(
|
||||
&mut self,
|
||||
_: dfg::EdwardsPoint,
|
||||
secret: dfg::Scalar,
|
||||
nonce: dfg::Scalar,
|
||||
view: &ParamsView<Ed25519>,
|
||||
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
|
||||
|
|
|
@ -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<u8> {
|
||||
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<Self::G, CurveError> {
|
||||
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<u8> {
|
||||
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())
|
||||
|
|
Loading…
Reference in a new issue