mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Update FROST signing to match the IETF draft
Modernizes dependencies
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
target
|
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"
|
subtle = "2.4"
|
||||||
|
|
||||||
ff = "0.10"
|
ff = "0.11"
|
||||||
group = "0.10"
|
group = "0.11"
|
||||||
|
|
||||||
curve25519-dalek = "3.2"
|
curve25519-dalek = "3.2"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use core::{
|
|||||||
|
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
|
|
||||||
use subtle::{Choice, CtOption, ConditionallySelectable};
|
use subtle::{Choice, CtOption, ConstantTimeEq, ConditionallySelectable};
|
||||||
|
|
||||||
pub use curve25519_dalek as dalek;
|
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 }
|
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 {
|
impl ConditionallySelectable for Scalar {
|
||||||
fn conditional_select(_: &Self, _: &Self, _: Choice) -> Self { unimplemented!() }
|
fn conditional_select(_: &Self, _: &Self, _: Choice) -> Self { unimplemented!() }
|
||||||
}
|
}
|
||||||
@@ -117,7 +121,7 @@ impl Field for Scalar {
|
|||||||
fn double(&self) -> Self { *self + self }
|
fn double(&self) -> Self { *self + self }
|
||||||
fn invert(&self) -> CtOption<Self> { CtOption::new(Self(self.0.invert()), Choice::from(1 as u8)) }
|
fn invert(&self) -> CtOption<Self> { CtOption::new(Self(self.0.invert()), Choice::from(1 as u8)) }
|
||||||
fn sqrt(&self) -> CtOption<Self> { unimplemented!() }
|
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 cube(&self) -> Self { *self * self * self }
|
||||||
fn pow_vartime<S: AsRef<[u64]>>(&self, _exp: S) -> Self { unimplemented!() }
|
fn pow_vartime<S: AsRef<[u64]>>(&self, _exp: S) -> Self { unimplemented!() }
|
||||||
}
|
}
|
||||||
@@ -130,11 +134,14 @@ impl PrimeField for Scalar {
|
|||||||
type Repr = [u8; 32];
|
type Repr = [u8; 32];
|
||||||
const NUM_BITS: u32 = 253;
|
const NUM_BITS: u32 = 253;
|
||||||
const CAPACITY: u32 = 252;
|
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() }
|
fn to_repr(&self) -> [u8; 32] { self.0.to_bytes() }
|
||||||
|
|
||||||
const S: u32 = 0;
|
const S: u32 = 0;
|
||||||
fn is_odd(&self) -> bool { unimplemented!() }
|
fn is_odd(&self) -> Choice { unimplemented!() }
|
||||||
fn multiplicative_generator() -> Self { unimplemented!() }
|
fn multiplicative_generator() -> Self { unimplemented!() }
|
||||||
fn root_of_unity() -> 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"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
digest = "0.9"
|
digest = "0.10"
|
||||||
blake2 = "0.9"
|
|
||||||
|
|
||||||
rand_core = "0.6"
|
rand_core = "0.6"
|
||||||
|
|
||||||
ff = "0.10"
|
ff = "0.11"
|
||||||
group = "0.10"
|
group = "0.11"
|
||||||
|
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4"
|
|
||||||
rand = "0.8"
|
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 core::{marker::PhantomData, fmt::Debug};
|
||||||
|
|
||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
use digest::Digest;
|
|
||||||
|
|
||||||
use group::Group;
|
use group::Group;
|
||||||
|
|
||||||
use crate::{Curve, FrostError, sign};
|
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
|
/// The resulting type of the signatures this algorithm will produce
|
||||||
type Signature: Clone + Debug;
|
type Signature: Clone + Debug;
|
||||||
|
|
||||||
@@ -59,40 +59,24 @@ pub trait Algorithm<C: Curve>: Clone + Debug {
|
|||||||
) -> bool;
|
) -> 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)]
|
#[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)]
|
#[derive(Clone)]
|
||||||
pub struct Blake2bHram {}
|
pub struct Schnorr<C: Curve, H: Hram<C>> {
|
||||||
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> {
|
|
||||||
c: Option<C::F>,
|
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> {
|
pub fn new() -> Schnorr<C, H> {
|
||||||
Schnorr {
|
Schnorr {
|
||||||
c: None,
|
c: None,
|
||||||
hram: PhantomData
|
_hram: PhantomData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +88,8 @@ pub struct SchnorrSignature<C: Curve> {
|
|||||||
pub s: C::F,
|
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>;
|
type Signature = SchnorrSignature<C>;
|
||||||
|
|
||||||
fn context(&self) -> Vec<u8> {
|
fn context(&self) -> Vec<u8> {
|
||||||
@@ -141,7 +126,7 @@ impl<C: Curve, H: Hram> Algorithm<C> for Schnorr<C, H> {
|
|||||||
nonce: C::F,
|
nonce: C::F,
|
||||||
msg: &[u8],
|
msg: &[u8],
|
||||||
) -> C::F {
|
) -> 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);
|
self.c = Some(c);
|
||||||
|
|
||||||
nonce + (params.secret_share() * 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 rand_core::{RngCore, CryptoRng};
|
||||||
use blake2::{Digest, Blake2b};
|
|
||||||
|
|
||||||
use ff::{Field, PrimeField};
|
use ff::{Field, PrimeField};
|
||||||
use group::Group;
|
use group::Group;
|
||||||
|
|
||||||
use crate::{Curve, MultisigParams, MultisigKeys, FrostError};
|
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
|
// 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
|
// 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
|
// 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);
|
let k = C::F::random(rng);
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let R = C::generator_table() * k;
|
let R = C::generator_table() * k;
|
||||||
let c = C::F_from_bytes_wide(
|
let c = challenge::<C>(params.i, context, &C::G_to_bytes(&R), &serialized);
|
||||||
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 s = k + (coefficients[0] * c);
|
let s = k + (coefficients[0] * c);
|
||||||
|
|
||||||
serialized.extend(&C::G_to_bytes(&R));
|
serialized.extend(&C::G_to_bytes(&R));
|
||||||
@@ -155,17 +154,11 @@ fn verify_r1<R: RngCore + CryptoRng, C: Curve>(
|
|||||||
);
|
);
|
||||||
points.push(C::generator());
|
points.push(C::generator());
|
||||||
|
|
||||||
let c = C::F_from_bytes_wide(
|
let c = challenge::<C>(
|
||||||
Blake2b::new()
|
l,
|
||||||
// Bounded by n which is already checked to be within the u64 range
|
context,
|
||||||
.chain(&u64::try_from(l).unwrap().to_le_bytes())
|
&serialized[l][commitments_len .. commitments_len + C::G_len()],
|
||||||
.chain(context.as_bytes())
|
&serialized[l][0 .. commitments_len]
|
||||||
.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")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if first {
|
if first {
|
||||||
@@ -195,17 +188,11 @@ fn verify_r1<R: RngCore + CryptoRng, C: Curve>(
|
|||||||
&serialized[l][commitments_len + C::G_len() .. serialized[l].len()]
|
&serialized[l][commitments_len + C::G_len() .. serialized[l].len()]
|
||||||
).map_err(|_| FrostError::InvalidProofOfKnowledge(l))?;
|
).map_err(|_| FrostError::InvalidProofOfKnowledge(l))?;
|
||||||
|
|
||||||
let c = C::F_from_bytes_wide(
|
let c = challenge::<C>(
|
||||||
Blake2b::new()
|
l,
|
||||||
// Bounded by n which is already checked to be within the u64 range
|
context,
|
||||||
.chain(&u64::try_from(l).unwrap().to_le_bytes())
|
&serialized[l][commitments_len .. commitments_len + C::G_len()],
|
||||||
.chain(context.as_bytes())
|
&serialized[l][0 .. commitments_len]
|
||||||
.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")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if R != ((C::generator_table() * s) + (commitments[l][0] * (C::F::zero() - &c))) {
|
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
|
/// State machine which manages key generation
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub struct StateMachine<C: Curve> {
|
pub struct StateMachine<C: Curve> {
|
||||||
params: MultisigParams,
|
params: MultisigParams,
|
||||||
context: String,
|
context: String,
|
||||||
@@ -396,7 +384,7 @@ pub struct StateMachine<C: Curve> {
|
|||||||
coefficients: Option<Vec<C::F>>,
|
coefficients: Option<Vec<C::F>>,
|
||||||
our_commitments: Option<Vec<C::G>>,
|
our_commitments: Option<Vec<C::G>>,
|
||||||
secret: Option<C::F>,
|
secret: Option<C::F>,
|
||||||
commitments: Option<Vec<Vec<C::G>>>,
|
commitments: Option<Vec<Vec<C::G>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Curve> StateMachine<C> {
|
impl<C: Curve> StateMachine<C> {
|
||||||
@@ -410,7 +398,7 @@ impl<C: Curve> StateMachine<C> {
|
|||||||
coefficients: None,
|
coefficients: None,
|
||||||
our_commitments: None,
|
our_commitments: None,
|
||||||
secret: None,
|
secret: None,
|
||||||
commitments: None,
|
commitments: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,10 @@ pub mod sign;
|
|||||||
pub enum CurveError {
|
pub enum CurveError {
|
||||||
#[error("invalid length for data (expected {0}, got {0})")]
|
#[error("invalid length for data (expected {0}, got {0})")]
|
||||||
InvalidLength(usize, usize),
|
InvalidLength(usize, usize),
|
||||||
// Push towards hex encoding in error messages
|
#[error("invalid scalar")]
|
||||||
#[error("invalid scalar ({0})")]
|
InvalidScalar,
|
||||||
InvalidScalar(String),
|
#[error("invalid point")]
|
||||||
#[error("invalid point ({0})")]
|
InvalidPoint,
|
||||||
InvalidPoint(String),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unified trait to manage a field/group
|
/// 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
|
// 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;
|
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
|
// 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
|
// 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)]
|
#[allow(non_snake_case)]
|
||||||
fn F_from_le_slice(slice: &[u8]) -> Result<Self::F, CurveError>;
|
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
|
/// Group element from slice. Should be canonical
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn G_from_slice(slice: &[u8]) -> Result<Self::G, CurveError>;
|
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
|
/// Obtain a vector of the byte encoding of G
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn G_to_bytes(g: &Self::G) -> Vec<u8>;
|
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
|
/// Parameters for a multisig
|
||||||
|
|||||||
@@ -2,19 +2,12 @@ use core::{convert::{TryFrom, TryInto}, cmp::min, fmt};
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
use blake2::{Digest, Blake2b};
|
|
||||||
|
|
||||||
use ff::{Field, PrimeField};
|
use ff::{Field, PrimeField};
|
||||||
use group::Group;
|
use group::Group;
|
||||||
|
|
||||||
use crate::{Curve, MultisigParams, MultisigKeys, FrostError, algorithm::Algorithm};
|
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
|
/// Calculate the lagrange coefficient
|
||||||
pub fn lagrange<F: PrimeField>(
|
pub fn lagrange<F: PrimeField>(
|
||||||
i: usize,
|
i: usize,
|
||||||
@@ -198,7 +191,18 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let mut B = Vec::with_capacity(multisig_params.n + 1);
|
let mut B = Vec::with_capacity(multisig_params.n + 1);
|
||||||
B.push(None);
|
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 {
|
for l in 1 ..= multisig_params.n {
|
||||||
if l == multisig_params.i {
|
if l == multisig_params.i {
|
||||||
if commitments[l].is_some() {
|
if commitments[l].is_some() {
|
||||||
@@ -206,8 +210,7 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
B.push(Some(our_preprocess.commitments));
|
B.push(Some(our_preprocess.commitments));
|
||||||
// Slightly more robust
|
b.extend(&u16::try_from(l).unwrap().to_le_bytes());
|
||||||
b.extend(&u64::try_from(l).unwrap().to_le_bytes());
|
|
||||||
b.extend(&our_preprocess.serialized[0 .. commit_len]);
|
b.extend(&our_preprocess.serialized[0 .. commit_len]);
|
||||||
continue;
|
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])
|
let E = C::G_from_slice(&commitments[C::G_len() .. commitments_len])
|
||||||
.map_err(|_| FrostError::InvalidCommitment(l))?;
|
.map_err(|_| FrostError::InvalidCommitment(l))?;
|
||||||
B.push(Some([D, E]));
|
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]);
|
b.extend(&commitments[0 .. commit_len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = if params.keys.offset.is_some() {
|
b.extend(&C::hash_msg(&msg));
|
||||||
C::F_to_le_bytes(¶ms.keys.offset.unwrap())
|
let b = C::hash_to_F(&b);
|
||||||
} 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")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
let view = ¶ms.view;
|
let view = ¶ms.view;
|
||||||
|
for l in ¶ms.view.included {
|
||||||
params.algorithm.process_addendum(
|
params.algorithm.process_addendum(
|
||||||
view,
|
view,
|
||||||
*l,
|
*l,
|
||||||
B[*l].as_ref().unwrap(),
|
B[*l].as_ref().unwrap(),
|
||||||
&p[p.len() - 1],
|
&b,
|
||||||
if *l == multisig_params.i {
|
if *l == multisig_params.i {
|
||||||
pi = p[p.len() - 1];
|
|
||||||
&our_preprocess.serialized[commitments_len .. our_preprocess.serialized.len()]
|
&our_preprocess.serialized[commitments_len .. our_preprocess.serialized.len()]
|
||||||
} else {
|
} 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() {
|
for i in 0 .. params.view.included.len() {
|
||||||
let commitments = B[params.view.included[i]].unwrap();
|
let commitments = B[params.view.included[i]].unwrap();
|
||||||
#[allow(non_snake_case)]
|
#[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);
|
Ris.push(this_R);
|
||||||
R += this_R;
|
R += this_R;
|
||||||
}
|
}
|
||||||
@@ -297,7 +280,7 @@ fn sign_with_share<C: Curve, A: Algorithm<C>>(
|
|||||||
let share = params.algorithm.sign_share(
|
let share = params.algorithm.sign_share(
|
||||||
view,
|
view,
|
||||||
R,
|
R,
|
||||||
our_preprocess.nonces[0] + (our_preprocess.nonces[1] * pi),
|
our_preprocess.nonces[0] + (our_preprocess.nonces[1] * b),
|
||||||
msg
|
msg
|
||||||
);
|
);
|
||||||
Ok((Package { Ris, R, share }, C::F_to_le_bytes(&share)))
|
Ok((Package { Ris, R, share }, C::F_to_le_bytes(&share)))
|
||||||
|
|||||||
@@ -1,19 +1,28 @@
|
|||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
||||||
use group::{Group, GroupEncoding};
|
use digest::Digest;
|
||||||
|
use ff::PrimeField;
|
||||||
|
use group::GroupEncoding;
|
||||||
|
|
||||||
use jubjub::{Fr, SubgroupPoint};
|
use sha2::{Sha256, Sha512};
|
||||||
use frost::{CurveError, Curve, multiexp_vartime};
|
|
||||||
|
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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub struct Jubjub;
|
pub struct Secp256k1;
|
||||||
impl Curve for Jubjub {
|
impl Curve for Secp256k1 {
|
||||||
type F = Fr;
|
type F = Scalar;
|
||||||
type G = SubgroupPoint;
|
type G = ProjectivePoint;
|
||||||
type T = SubgroupPoint;
|
type T = ProjectivePoint;
|
||||||
|
|
||||||
fn id() -> String {
|
fn id() -> String {
|
||||||
"Jubjub".to_string()
|
"secp256k1".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id_len() -> u8 {
|
fn id_len() -> u8 {
|
||||||
@@ -21,15 +30,28 @@ impl Curve for Jubjub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generator() -> Self::G {
|
fn generator() -> Self::G {
|
||||||
Self::G::generator()
|
Self::G::GENERATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generator_table() -> Self::T {
|
fn generator_table() -> Self::T {
|
||||||
Self::G::generator()
|
Self::G::GENERATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiexp_vartime(scalars: &[Self::F], points: &[Self::G]) -> Self::G {
|
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 {
|
fn F_len() -> usize {
|
||||||
@@ -37,46 +59,54 @@ impl Curve for Jubjub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn G_len() -> usize {
|
fn G_len() -> usize {
|
||||||
32
|
33
|
||||||
}
|
}
|
||||||
|
|
||||||
fn F_from_le_slice(slice: &[u8]) -> Result<Self::F, CurveError> {
|
fn F_from_le_slice(slice: &[u8]) -> Result<Self::F, CurveError> {
|
||||||
let scalar = Self::F::from_bytes(
|
let mut bytes: [u8; 32] = slice.try_into().map_err(
|
||||||
&slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
|_| CurveError::InvalidLength(32, slice.len())
|
||||||
);
|
)?;
|
||||||
if scalar.is_some().into() {
|
bytes.reverse();
|
||||||
Ok(scalar.unwrap())
|
let scalar = Scalar::from_repr(bytes.into());
|
||||||
} else {
|
if scalar.is_none().unwrap_u8() == 1 {
|
||||||
Err(CurveError::InvalidScalar(hex::encode(slice)))
|
Err(CurveError::InvalidScalar)?;
|
||||||
}
|
}
|
||||||
}
|
Ok(scalar.unwrap())
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn G_from_slice(slice: &[u8]) -> Result<Self::G, CurveError> {
|
fn G_from_slice(slice: &[u8]) -> Result<Self::G, CurveError> {
|
||||||
let point = Self::G::from_bytes(
|
let point = ProjectivePoint::from_bytes(GenericArray::from_slice(slice));
|
||||||
&slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
if point.is_none().unwrap_u8() == 1 {
|
||||||
);
|
Err(CurveError::InvalidScalar)?;
|
||||||
if point.is_some().into() {
|
|
||||||
Ok(point.unwrap())
|
|
||||||
} else {
|
|
||||||
Err(CurveError::InvalidPoint(hex::encode(slice)))?
|
|
||||||
}
|
}
|
||||||
|
Ok(point.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn F_to_le_bytes(f: &Self::F) -> Vec<u8> {
|
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> {
|
fn G_to_bytes(g: &Self::G) -> Vec<u8> {
|
||||||
g.to_bytes().to_vec()
|
(&g.to_bytes()).to_vec()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fn F_from_bytes_wide(bytes: [u8; 64]) -> Self::F {
|
|
||||||
Self::F::from_bytes_wide(&bytes)
|
#[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 rand::{RngCore, rngs::OsRng};
|
||||||
|
|
||||||
|
use digest::Digest;
|
||||||
|
use sha2::Sha256;
|
||||||
|
|
||||||
use frost::{
|
use frost::{
|
||||||
Curve,
|
Curve,
|
||||||
MultisigParams, MultisigKeys,
|
MultisigParams, MultisigKeys,
|
||||||
key_gen,
|
key_gen,
|
||||||
algorithm::{Algorithm, Schnorr, Blake2bHram, SchnorrSignature},
|
algorithm::{Algorithm, Schnorr, SchnorrSignature},
|
||||||
sign
|
sign
|
||||||
};
|
};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
use common::Jubjub;
|
use common::{Secp256k1, TestHram};
|
||||||
|
|
||||||
const PARTICIPANTS: usize = 8;
|
const PARTICIPANTS: usize = 8;
|
||||||
|
|
||||||
@@ -81,7 +84,7 @@ fn key_gen_and_sign() {
|
|||||||
).unwrap()
|
).unwrap()
|
||||||
);
|
);
|
||||||
machines.push(
|
machines.push(
|
||||||
key_gen::StateMachine::<Jubjub>::new(
|
key_gen::StateMachine::<Secp256k1>::new(
|
||||||
params[i - 1],
|
params[i - 1],
|
||||||
"FF/Group Rust key_gen test".to_string()
|
"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();
|
let these_keys = machines[i - 1].complete(our_secret_shares).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
MultisigKeys::<Jubjub>::deserialize(&these_keys.serialize()).unwrap(),
|
MultisigKeys::<Secp256k1>::deserialize(&these_keys.serialize()).unwrap(),
|
||||||
these_keys
|
these_keys
|
||||||
);
|
);
|
||||||
keys.push(Rc::new(these_keys.clone()));
|
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());
|
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];
|
let mut randomization = [0; 64];
|
||||||
(&mut OsRng).fill_bytes(&mut randomization);
|
(&mut OsRng).fill_bytes(&mut randomization);
|
||||||
sign(
|
sign(
|
||||||
Schnorr::<Jubjub, Blake2bHram>::new(),
|
Schnorr::<Secp256k1, TestHram>::new(),
|
||||||
keys.iter().map(
|
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()
|
).collect()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
4
sign/monero/.gitignore
vendored
4
sign/monero/.gitignore
vendored
@@ -1,3 +1 @@
|
|||||||
Cargo.lock
|
c/.build
|
||||||
|
|
||||||
.build
|
|
||||||
|
|||||||
@@ -12,16 +12,13 @@ thiserror = "1"
|
|||||||
|
|
||||||
rand_core = "0.6"
|
rand_core = "0.6"
|
||||||
|
|
||||||
hex = "0.4"
|
|
||||||
|
|
||||||
digest = "0.9"
|
|
||||||
tiny-keccak = { version = "2.0", features = ["keccak"] }
|
tiny-keccak = { version = "2.0", features = ["keccak"] }
|
||||||
blake2 = "0.9"
|
blake2 = "0.10"
|
||||||
|
|
||||||
curve25519-dalek = { version = "3.2", features = ["std", "simd_backend"] }
|
curve25519-dalek = { version = "3.2", features = ["std", "simd_backend"] }
|
||||||
|
|
||||||
ff = { version = "0.10", optional = true }
|
ff = { version = "0.11", optional = true }
|
||||||
group = { version = "0.10", optional = true }
|
group = { version = "0.11", optional = true }
|
||||||
dalek-ff-group = { path = "../dalek-ff-group", optional = true }
|
dalek-ff-group = { path = "../dalek-ff-group", optional = true }
|
||||||
frost = { path = "../frost", optional = true }
|
frost = { path = "../frost", optional = true }
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
use digest::Digest;
|
use blake2::{Digest, Blake2b512};
|
||||||
use blake2::Blake2b;
|
|
||||||
|
|
||||||
use curve25519_dalek::{
|
use curve25519_dalek::{
|
||||||
constants::ED25519_BASEPOINT_TABLE,
|
constants::ED25519_BASEPOINT_TABLE,
|
||||||
@@ -82,10 +81,10 @@ pub(crate) fn sign_core(
|
|||||||
let z;
|
let z;
|
||||||
|
|
||||||
let mut next_rand = rand_source;
|
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);
|
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);
|
C_out = commitment(&a, ssr.amount);
|
||||||
|
|
||||||
for member in &ssr.ring {
|
for member in &ssr.ring {
|
||||||
@@ -149,7 +148,7 @@ pub(crate) fn sign_core(
|
|||||||
s.resize(n, Scalar::zero());
|
s.resize(n, Scalar::zero());
|
||||||
while j != i {
|
while j != i {
|
||||||
s[j] = Scalar::from_bytes_mod_order_wide(&next_rand);
|
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_p = mu_P * c;
|
||||||
let c_c = mu_C * c;
|
let c_c = mu_C * c;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
use digest::Digest;
|
use blake2::{Digest, Blake2b512};
|
||||||
use blake2::Blake2b;
|
|
||||||
|
|
||||||
use curve25519_dalek::{
|
use curve25519_dalek::{
|
||||||
constants::ED25519_BASEPOINT_TABLE,
|
constants::ED25519_BASEPOINT_TABLE,
|
||||||
@@ -11,7 +10,7 @@ use curve25519_dalek::{
|
|||||||
|
|
||||||
use dalek_ff_group as dfg;
|
use dalek_ff_group as dfg;
|
||||||
use group::Group;
|
use group::Group;
|
||||||
use frost::{Curve, FrostError, algorithm::Algorithm};
|
use frost::{Curve, FrostError, algorithm::Algorithm, sign::ParamsView};
|
||||||
|
|
||||||
use monero::util::ringct::{Key, Clsag};
|
use monero::util::ringct::{Key, Clsag};
|
||||||
|
|
||||||
@@ -94,11 +93,11 @@ impl Algorithm<Ed25519> for Multisig {
|
|||||||
|
|
||||||
fn preprocess_addendum<R: RngCore + CryptoRng>(
|
fn preprocess_addendum<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
group_key: &dfg::EdwardsPoint,
|
view: &ParamsView<Ed25519>,
|
||||||
nonces: &[dfg::Scalar; 2]
|
nonces: &[dfg::Scalar; 2]
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
#[allow(non_snake_case)]
|
#[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 h0 = nonces[0].0 * H;
|
||||||
let h1 = nonces[1].0 * H;
|
let h1 = nonces[1].0 * H;
|
||||||
// 32 + 32 + 64 + 64
|
// 32 + 32 + 64 + 64
|
||||||
@@ -112,6 +111,7 @@ impl Algorithm<Ed25519> for Multisig {
|
|||||||
|
|
||||||
fn process_addendum(
|
fn process_addendum(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_: &ParamsView<Ed25519>,
|
||||||
l: usize,
|
l: usize,
|
||||||
commitments: &[dfg::EdwardsPoint; 2],
|
commitments: &[dfg::EdwardsPoint; 2],
|
||||||
p: &dfg::Scalar,
|
p: &dfg::Scalar,
|
||||||
@@ -147,19 +147,32 @@ impl Algorithm<Ed25519> for Multisig {
|
|||||||
|
|
||||||
fn sign_share(
|
fn sign_share(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: dfg::EdwardsPoint,
|
view: &ParamsView<Ed25519>,
|
||||||
secret: dfg::Scalar,
|
|
||||||
nonce: dfg::Scalar,
|
|
||||||
nonce_sum: dfg::EdwardsPoint,
|
nonce_sum: dfg::EdwardsPoint,
|
||||||
_: &[u8],
|
nonce: dfg::Scalar,
|
||||||
|
_: &[u8]
|
||||||
) -> dfg::Scalar {
|
) -> dfg::Scalar {
|
||||||
// Use everyone's commitments to derive a random source all signers can agree upon
|
// 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
|
// 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();
|
let rand_source = Keccak::v512()
|
||||||
#[allow(non_snake_case)]
|
.chain("Clsag_randomness")
|
||||||
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);
|
.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 });
|
self.interim = Some(ClsagSignInterim { c, mu_C, z, mu_P, clsag, C_out });
|
||||||
share
|
share
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ use core::convert::TryInto;
|
|||||||
|
|
||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
use digest::Digest;
|
use blake2::{Digest, Blake2b512};
|
||||||
use blake2::Blake2b;
|
|
||||||
|
|
||||||
use curve25519_dalek::{
|
use curve25519_dalek::{
|
||||||
constants::ED25519_BASEPOINT_TABLE as DTable,
|
constants::ED25519_BASEPOINT_TABLE as DTable,
|
||||||
@@ -49,6 +48,14 @@ impl Curve for Ed25519 {
|
|||||||
EdwardsPoint(DPoint::vartime_multiscalar_mul(scalars, points))
|
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 {
|
fn F_len() -> usize {
|
||||||
32
|
32
|
||||||
}
|
}
|
||||||
@@ -61,19 +68,13 @@ impl Curve for Ed25519 {
|
|||||||
let scalar = Self::F::from_repr(
|
let scalar = Self::F::from_repr(
|
||||||
slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
||||||
);
|
);
|
||||||
if scalar.is_some() {
|
if scalar.is_some().unwrap_u8() == 1 {
|
||||||
Ok(scalar.unwrap())
|
Ok(scalar.unwrap())
|
||||||
} else {
|
} 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> {
|
fn G_from_slice(slice: &[u8]) -> Result<Self::G, CurveError> {
|
||||||
let point = dfg::CompressedEdwardsY::new(
|
let point = dfg::CompressedEdwardsY::new(
|
||||||
slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
slice.try_into().map_err(|_| CurveError::InvalidLength(32, slice.len()))?
|
||||||
@@ -83,11 +84,11 @@ impl Curve for Ed25519 {
|
|||||||
let point = point.unwrap();
|
let point = point.unwrap();
|
||||||
// Ban torsioned points
|
// Ban torsioned points
|
||||||
if !point.is_torsion_free() {
|
if !point.is_torsion_free() {
|
||||||
Err(CurveError::InvalidPoint(hex::encode(slice)))?
|
Err(CurveError::InvalidPoint)?
|
||||||
}
|
}
|
||||||
Ok(point)
|
Ok(point)
|
||||||
} else {
|
} 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> {
|
fn G_to_bytes(g: &Self::G) -> Vec<u8> {
|
||||||
g.compress().to_bytes().to_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
|
// Used to prove legitimacy in several locations
|
||||||
@@ -124,7 +121,7 @@ impl DLEqProof {
|
|||||||
let R2 = r * H;
|
let R2 = r * H;
|
||||||
|
|
||||||
let c = DScalar::from_hash(
|
let c = DScalar::from_hash(
|
||||||
Blake2b::new()
|
Blake2b512::new()
|
||||||
.chain(R1.compress().to_bytes())
|
.chain(R1.compress().to_bytes())
|
||||||
.chain(R2.compress().to_bytes())
|
.chain(R2.compress().to_bytes())
|
||||||
.chain((secret * &DTable).compress().to_bytes())
|
.chain((secret * &DTable).compress().to_bytes())
|
||||||
@@ -148,7 +145,7 @@ impl DLEqProof {
|
|||||||
let R2 = (s * H) - (c * alt);
|
let R2 = (s * H) - (c * alt);
|
||||||
|
|
||||||
let expected_c = DScalar::from_hash(
|
let expected_c = DScalar::from_hash(
|
||||||
Blake2b::new()
|
Blake2b512::new()
|
||||||
.chain(R1.compress().to_bytes())
|
.chain(R1.compress().to_bytes())
|
||||||
.chain(R2.compress().to_bytes())
|
.chain(R2.compress().to_bytes())
|
||||||
.chain(primary.compress().to_bytes())
|
.chain(primary.compress().to_bytes())
|
||||||
|
|||||||
Reference in New Issue
Block a user