diff --git a/Cargo.Bazel.Fuzzing.json.lock b/Cargo.Bazel.Fuzzing.json.lock index f54fa3d1c78..da09e658f0b 100644 --- a/Cargo.Bazel.Fuzzing.json.lock +++ b/Cargo.Bazel.Fuzzing.json.lock @@ -1,5 +1,5 @@ { - "checksum": "2e6dd631446f29468708df393b8e43a519cc338d285a461b44eeb87500cbe6dd", + "checksum": "02e2f699be2cc70dc5070791f0185afdba301bdf9f548bdda55bbf4ca4433a88", "crates": { "abnf 0.12.0": { "name": "abnf", @@ -13529,6 +13529,168 @@ }, "license": "BSD-3-Clause" }, + "curve25519-dalek 4.1.2": { + "name": "curve25519-dalek", + "version": "4.1.2", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/curve25519-dalek/4.1.2/download", + "sha256": "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" + } + }, + "targets": [ + { + "Library": { + "crate_name": "curve25519_dalek", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "curve25519_dalek", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "digest", + "precomputed-tables", + "zeroize" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "cfg-if 1.0.0", + "target": "cfg_if" + }, + { + "id": "curve25519-dalek 4.1.2", + "target": "build_script_build" + }, + { + "id": "digest 0.10.7", + "target": "digest" + }, + { + "id": "subtle 2.5.0", + "target": "subtle" + }, + { + "id": "zeroize 1.7.0", + "target": "zeroize" + } + ], + "selects": { + "cfg(curve25519_dalek_backend = \"fiat\")": [ + { + "id": "fiat-crypto 0.2.6", + "target": "fiat_crypto" + } + ], + "cfg(target_arch = \"x86_64\")": [ + { + "id": "cpufeatures 0.2.9", + "target": "cpufeatures" + } + ] + } + }, + "edition": "2021", + "proc_macro_deps": { + "common": [], + "selects": { + "cfg(all(not(curve25519_dalek_backend = \"fiat\"), not(curve25519_dalek_backend = \"serial\"), target_arch = \"x86_64\"))": [ + { + "id": "curve25519-dalek-derive 0.1.1", + "target": "curve25519_dalek_derive" + } + ] + } + }, + "version": "4.1.2" + }, + "build_script_attrs": { + "data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "platforms 3.3.0", + "target": "platforms" + }, + { + "id": "rustc_version 0.4.0", + "target": "rustc_version" + } + ], + "selects": {} + } + }, + "license": "BSD-3-Clause" + }, + "curve25519-dalek-derive 0.1.1": { + "name": "curve25519-dalek-derive", + "version": "0.1.1", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/curve25519-dalek-derive/0.1.1/download", + "sha256": "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" + } + }, + "targets": [ + { + "ProcMacro": { + "crate_name": "curve25519_dalek_derive", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "curve25519_dalek_derive", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "proc-macro2 1.0.76", + "target": "proc_macro2" + }, + { + "id": "quote 1.0.35", + "target": "quote" + }, + { + "id": "syn 2.0.48", + "target": "syn" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.1.1" + }, + "license": "MIT/Apache-2.0" + }, "curve25519-dalek-ng 4.1.1": { "name": "curve25519-dalek-ng", "version": "4.1.1", @@ -15351,6 +15513,10 @@ "id": "ed25519-consensus 2.1.0", "target": "ed25519_consensus" }, + { + "id": "ed25519-dalek 2.1.1", + "target": "ed25519_dalek" + }, { "id": "either 1.9.0", "target": "either" @@ -17146,6 +17312,58 @@ }, "license": "Apache-2.0 OR MIT" }, + "ed25519 2.2.3": { + "name": "ed25519", + "version": "2.2.3", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/ed25519/2.2.3/download", + "sha256": "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" + } + }, + "targets": [ + { + "Library": { + "crate_name": "ed25519", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "ed25519", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "pem", + "pkcs8", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "pkcs8 0.10.2", + "target": "pkcs8" + }, + { + "id": "signature 2.1.0", + "target": "signature" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "2.2.3" + }, + "license": "Apache-2.0 OR MIT" + }, "ed25519-consensus 2.1.0": { "name": "ed25519-consensus", "version": "2.1.0", @@ -17219,6 +17437,90 @@ }, "license": "MIT OR Apache-2.0" }, + "ed25519-dalek 2.1.1": { + "name": "ed25519-dalek", + "version": "2.1.1", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/ed25519-dalek/2.1.1/download", + "sha256": "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" + } + }, + "targets": [ + { + "Library": { + "crate_name": "ed25519_dalek", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "ed25519_dalek", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "batch", + "default", + "digest", + "fast", + "merlin", + "pem", + "pkcs8", + "rand_core", + "signature", + "std", + "zeroize" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "curve25519-dalek 4.1.2", + "target": "curve25519_dalek" + }, + { + "id": "ed25519 2.2.3", + "target": "ed25519" + }, + { + "id": "merlin 3.0.0", + "target": "merlin" + }, + { + "id": "rand_core 0.6.4", + "target": "rand_core" + }, + { + "id": "sha2 0.10.8", + "target": "sha2" + }, + { + "id": "signature 2.1.0", + "target": "signature" + }, + { + "id": "subtle 2.5.0", + "target": "subtle" + }, + { + "id": "zeroize 1.7.0", + "target": "zeroize" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "2.1.1" + }, + "license": "BSD-3-Clause" + }, "educe 0.4.23": { "name": "educe", "version": "0.4.23", @@ -19125,6 +19427,36 @@ }, "license": "MIT/Apache-2.0" }, + "fiat-crypto 0.2.6": { + "name": "fiat-crypto", + "version": "0.2.6", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/fiat-crypto/0.2.6/download", + "sha256": "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" + } + }, + "targets": [ + { + "Library": { + "crate_name": "fiat_crypto", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "fiat_crypto", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2018", + "version": "0.2.6" + }, + "license": "MIT OR Apache-2.0 OR BSD-1-Clause" + }, "filetime 0.2.22": { "name": "filetime", "version": "0.2.22", @@ -32681,6 +33013,57 @@ }, "license": "MPL-2.0" }, + "merlin 3.0.0": { + "name": "merlin", + "version": "3.0.0", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/merlin/3.0.0/download", + "sha256": "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" + } + }, + "targets": [ + { + "Library": { + "crate_name": "merlin", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "merlin", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "byteorder 1.5.0", + "target": "byteorder" + }, + { + "id": "keccak 0.1.4", + "target": "keccak" + }, + { + "id": "rand_core 0.6.4", + "target": "rand_core" + }, + { + "id": "zeroize 1.7.0", + "target": "zeroize" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "3.0.0" + }, + "license": "MIT" + }, "metrics-proxy 0.1.0": { "name": "metrics-proxy", "version": "0.1.0", @@ -39754,6 +40137,43 @@ }, "license": "MIT OR Apache-2.0" }, + "platforms 3.3.0": { + "name": "platforms", + "version": "3.3.0", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/platforms/3.3.0/download", + "sha256": "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + } + }, + "targets": [ + { + "Library": { + "crate_name": "platforms", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "platforms", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, + "edition": "2018", + "version": "3.3.0" + }, + "license": "Apache-2.0 OR MIT" + }, "plotters 0.3.5": { "name": "plotters", "version": "0.3.5", @@ -65457,6 +65877,16 @@ "armv7-linux-androideabi", "armv7-unknown-linux-gnueabi" ], + "cfg(all(not(curve25519_dalek_backend = \"fiat\"), not(curve25519_dalek_backend = \"serial\"), target_arch = \"x86_64\"))": [ + "x86_64-apple-darwin", + "x86_64-apple-ios", + "x86_64-fuchsia", + "x86_64-linux-android", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-none" + ], "cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))": [ "aarch64-unknown-linux-gnu", "arm-unknown-linux-gnueabi", @@ -65944,6 +66374,7 @@ "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu" ], + "cfg(curve25519_dalek_backend = \"fiat\")": [], "cfg(not(all(target_arch = \"arm\", target_os = \"none\")))": [ "aarch64-apple-darwin", "aarch64-apple-ios", diff --git a/Cargo.Bazel.Fuzzing.toml.lock b/Cargo.Bazel.Fuzzing.toml.lock index b41cbb51a4e..dd4cc65d14a 100644 --- a/Cargo.Bazel.Fuzzing.toml.lock +++ b/Cargo.Bazel.Fuzzing.toml.lock @@ -2655,6 +2655,34 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2 1.0.76", + "quote 1.0.35", + "syn 2.0.48", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -3024,13 +3052,14 @@ dependencies = [ "crossbeam", "crossbeam-channel", "csv", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "cvt", "dashmap", "derive_more 0.99.8-alpha.0", "digest 0.9.0", "dyn-clone", "ed25519-consensus", + "ed25519-dalek", "educe", "either", "erased-serde", @@ -3440,6 +3469,16 @@ dependencies = [ "spki", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + [[package]] name = "ed25519-consensus" version = "2.1.0" @@ -3455,6 +3494,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek 4.1.2", + "ed25519", + "merlin", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "signature", + "subtle", + "zeroize", +] + [[package]] name = "educe" version = "0.4.23" @@ -3817,6 +3873,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" + [[package]] name = "filetime" version = "0.2.22" @@ -6474,6 +6536,18 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "metrics-proxy" version = "0.1.0" @@ -7798,6 +7872,12 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + [[package]] name = "plotters" version = "0.3.5" diff --git a/Cargo.Bazel.json.lock b/Cargo.Bazel.json.lock index d5fa1cb17d1..b6d66358f18 100644 --- a/Cargo.Bazel.json.lock +++ b/Cargo.Bazel.json.lock @@ -1,5 +1,5 @@ { - "checksum": "acdc090cda67bd362da49a5cd15b49b6f6cbeb1d245c711570e70e21742a0ff5", + "checksum": "6f2aec0deec306e633aaa10980f3e9b4f82184462f73c8e72e28ecff9b834bed", "crates": { "abnf 0.12.0": { "name": "abnf", @@ -13405,6 +13405,168 @@ }, "license": "BSD-3-Clause" }, + "curve25519-dalek 4.1.2": { + "name": "curve25519-dalek", + "version": "4.1.2", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/curve25519-dalek/4.1.2/download", + "sha256": "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" + } + }, + "targets": [ + { + "Library": { + "crate_name": "curve25519_dalek", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "curve25519_dalek", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "digest", + "precomputed-tables", + "zeroize" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "cfg-if 1.0.0", + "target": "cfg_if" + }, + { + "id": "curve25519-dalek 4.1.2", + "target": "build_script_build" + }, + { + "id": "digest 0.10.7", + "target": "digest" + }, + { + "id": "subtle 2.5.0", + "target": "subtle" + }, + { + "id": "zeroize 1.7.0", + "target": "zeroize" + } + ], + "selects": { + "cfg(curve25519_dalek_backend = \"fiat\")": [ + { + "id": "fiat-crypto 0.2.6", + "target": "fiat_crypto" + } + ], + "cfg(target_arch = \"x86_64\")": [ + { + "id": "cpufeatures 0.2.9", + "target": "cpufeatures" + } + ] + } + }, + "edition": "2021", + "proc_macro_deps": { + "common": [], + "selects": { + "cfg(all(not(curve25519_dalek_backend = \"fiat\"), not(curve25519_dalek_backend = \"serial\"), target_arch = \"x86_64\"))": [ + { + "id": "curve25519-dalek-derive 0.1.1", + "target": "curve25519_dalek_derive" + } + ] + } + }, + "version": "4.1.2" + }, + "build_script_attrs": { + "data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "platforms 3.3.0", + "target": "platforms" + }, + { + "id": "rustc_version 0.4.0", + "target": "rustc_version" + } + ], + "selects": {} + } + }, + "license": "BSD-3-Clause" + }, + "curve25519-dalek-derive 0.1.1": { + "name": "curve25519-dalek-derive", + "version": "0.1.1", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/curve25519-dalek-derive/0.1.1/download", + "sha256": "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" + } + }, + "targets": [ + { + "ProcMacro": { + "crate_name": "curve25519_dalek_derive", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "curve25519_dalek_derive", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "proc-macro2 1.0.76", + "target": "proc_macro2" + }, + { + "id": "quote 1.0.35", + "target": "quote" + }, + { + "id": "syn 2.0.48", + "target": "syn" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.1.1" + }, + "license": "MIT/Apache-2.0" + }, "curve25519-dalek-ng 4.1.1": { "name": "curve25519-dalek-ng", "version": "4.1.1", @@ -15227,6 +15389,10 @@ "id": "ed25519-consensus 2.1.0", "target": "ed25519_consensus" }, + { + "id": "ed25519-dalek 2.1.1", + "target": "ed25519_dalek" + }, { "id": "either 1.8.1", "target": "either" @@ -17022,6 +17188,58 @@ }, "license": "Apache-2.0 OR MIT" }, + "ed25519 2.2.3": { + "name": "ed25519", + "version": "2.2.3", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/ed25519/2.2.3/download", + "sha256": "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" + } + }, + "targets": [ + { + "Library": { + "crate_name": "ed25519", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "ed25519", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "pem", + "pkcs8", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "pkcs8 0.10.2", + "target": "pkcs8" + }, + { + "id": "signature 2.1.0", + "target": "signature" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "2.2.3" + }, + "license": "Apache-2.0 OR MIT" + }, "ed25519-consensus 2.1.0": { "name": "ed25519-consensus", "version": "2.1.0", @@ -17095,6 +17313,90 @@ }, "license": "MIT OR Apache-2.0" }, + "ed25519-dalek 2.1.1": { + "name": "ed25519-dalek", + "version": "2.1.1", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/ed25519-dalek/2.1.1/download", + "sha256": "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" + } + }, + "targets": [ + { + "Library": { + "crate_name": "ed25519_dalek", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "ed25519_dalek", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "batch", + "default", + "digest", + "fast", + "merlin", + "pem", + "pkcs8", + "rand_core", + "signature", + "std", + "zeroize" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "curve25519-dalek 4.1.2", + "target": "curve25519_dalek" + }, + { + "id": "ed25519 2.2.3", + "target": "ed25519" + }, + { + "id": "merlin 3.0.0", + "target": "merlin" + }, + { + "id": "rand_core 0.6.4", + "target": "rand_core" + }, + { + "id": "sha2 0.10.8", + "target": "sha2" + }, + { + "id": "signature 2.1.0", + "target": "signature" + }, + { + "id": "subtle 2.5.0", + "target": "subtle" + }, + { + "id": "zeroize 1.7.0", + "target": "zeroize" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "2.1.1" + }, + "license": "BSD-3-Clause" + }, "educe 0.4.22": { "name": "educe", "version": "0.4.22", @@ -19098,6 +19400,36 @@ }, "license": "MIT/Apache-2.0" }, + "fiat-crypto 0.2.6": { + "name": "fiat-crypto", + "version": "0.2.6", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/fiat-crypto/0.2.6/download", + "sha256": "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" + } + }, + "targets": [ + { + "Library": { + "crate_name": "fiat_crypto", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "fiat_crypto", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "edition": "2018", + "version": "0.2.6" + }, + "license": "MIT OR Apache-2.0 OR BSD-1-Clause" + }, "filetime 0.2.21": { "name": "filetime", "version": "0.2.21", @@ -32708,6 +33040,57 @@ }, "license": "MPL-2.0" }, + "merlin 3.0.0": { + "name": "merlin", + "version": "3.0.0", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/merlin/3.0.0/download", + "sha256": "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" + } + }, + "targets": [ + { + "Library": { + "crate_name": "merlin", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "merlin", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "byteorder 1.5.0", + "target": "byteorder" + }, + { + "id": "keccak 0.1.4", + "target": "keccak" + }, + { + "id": "rand_core 0.6.4", + "target": "rand_core" + }, + { + "id": "zeroize 1.7.0", + "target": "zeroize" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "3.0.0" + }, + "license": "MIT" + }, "metrics-proxy 0.1.0": { "name": "metrics-proxy", "version": "0.1.0", @@ -39717,6 +40100,43 @@ }, "license": "MIT OR Apache-2.0" }, + "platforms 3.3.0": { + "name": "platforms", + "version": "3.3.0", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/platforms/3.3.0/download", + "sha256": "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + } + }, + "targets": [ + { + "Library": { + "crate_name": "platforms", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "platforms", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, + "edition": "2018", + "version": "3.3.0" + }, + "license": "Apache-2.0 OR MIT" + }, "plotters 0.3.5": { "name": "plotters", "version": "0.3.5", @@ -65429,6 +65849,16 @@ "armv7-linux-androideabi", "armv7-unknown-linux-gnueabi" ], + "cfg(all(not(curve25519_dalek_backend = \"fiat\"), not(curve25519_dalek_backend = \"serial\"), target_arch = \"x86_64\"))": [ + "x86_64-apple-darwin", + "x86_64-apple-ios", + "x86_64-fuchsia", + "x86_64-linux-android", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-none" + ], "cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))": [ "aarch64-unknown-linux-gnu", "arm-unknown-linux-gnueabi", @@ -65875,6 +66305,7 @@ "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu" ], + "cfg(curve25519_dalek_backend = \"fiat\")": [], "cfg(not(all(target_arch = \"arm\", target_os = \"none\")))": [ "aarch64-apple-darwin", "aarch64-apple-ios", diff --git a/Cargo.Bazel.toml.lock b/Cargo.Bazel.toml.lock index 02e4f51a6fb..5c92be15468 100644 --- a/Cargo.Bazel.toml.lock +++ b/Cargo.Bazel.toml.lock @@ -2645,6 +2645,34 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2 1.0.76", + "quote 1.0.35", + "syn 2.0.48", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -3014,13 +3042,14 @@ dependencies = [ "crossbeam", "crossbeam-channel", "csv", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "cvt", "dashmap", "derive_more 0.99.8-alpha.0", "digest 0.9.0", "dyn-clone", "ed25519-consensus", + "ed25519-dalek", "educe", "either", "erased-serde", @@ -3430,6 +3459,16 @@ dependencies = [ "spki", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + [[package]] name = "ed25519-consensus" version = "2.1.0" @@ -3445,6 +3484,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek 4.1.2", + "ed25519", + "merlin", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "signature", + "subtle", + "zeroize", +] + [[package]] name = "educe" version = "0.4.22" @@ -3808,6 +3864,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" + [[package]] name = "filetime" version = "0.2.21" @@ -6473,6 +6535,18 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "metrics-proxy" version = "0.1.0" @@ -7805,6 +7879,12 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + [[package]] name = "plotters" version = "0.3.5" diff --git a/Cargo.lock b/Cargo.lock index a415c515fd3..92a93fbcd9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2371,9 +2371,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -2722,6 +2722,34 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2 1.0.75", + "quote 1.0.35", + "syn 2.0.48", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -3390,6 +3418,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + [[package]] name = "ed25519-consensus" version = "2.1.0" @@ -3405,6 +3443,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek 4.1.2", + "ed25519", + "merlin", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "signature", + "subtle", + "zeroize", +] + [[package]] name = "educe" version = "0.4.20" @@ -3825,6 +3880,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" + [[package]] name = "filetime" version = "0.2.20" @@ -6228,6 +6289,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ic-crypto-ed25519" +version = "0.9.0" +dependencies = [ + "ed25519-dalek", + "hex", + "hex-literal", + "rand 0.8.5", + "wycheproof", + "zeroize", +] + [[package]] name = "ic-crypto-extended-bip32" version = "0.9.0" @@ -6351,7 +6424,7 @@ version = "0.9.0" dependencies = [ "assert_matches", "base64 0.13.1", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "ed25519-consensus", "hex", "ic-crypto-internal-basic-sig-der-utils", @@ -6817,7 +6890,7 @@ name = "ic-crypto-node-key-validation" version = "0.9.0" dependencies = [ "assert_matches", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "hex", "ic-base-types", "ic-crypto-internal-basic-sig-ed25519", @@ -7149,7 +7222,7 @@ name = "ic-crypto-tls-cert-validation" version = "0.9.0" dependencies = [ "assert_matches", - "curve25519-dalek", + "curve25519-dalek 3.2.0", "hex", "ic-crypto-internal-basic-sig-ed25519", "ic-crypto-test-utils-keys", @@ -13579,6 +13652,18 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -14791,6 +14876,12 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "platforms" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" + [[package]] name = "plotters" version = "0.3.4" diff --git a/Cargo.toml b/Cargo.toml index d8681fa9b1e..4460dc02472 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ members = [ "rs/crypto", "rs/crypto/ecdsa_secp256k1", "rs/crypto/ecdsa_secp256r1", + "rs/crypto/ed25519", "rs/crypto/extended_bip32", "rs/crypto/for_verification_only", "rs/crypto/iccsa", diff --git a/bazel/external_crates.bzl b/bazel/external_crates.bzl index 1893fb2ab0b..1e7ea34c862 100644 --- a/bazel/external_crates.bzl +++ b/bazel/external_crates.bzl @@ -376,6 +376,10 @@ def external_crates_repository(name, cargo_lockfile, lockfile, sanitizers_enable "ed25519-consensus": crate.spec( version = "^2.0.1", ), + "ed25519-dalek": crate.spec( + version = "^2.1.1", + features = ["std", "zeroize", "digest", "batch", "pkcs8", "pem"], + ), "educe": crate.spec( version = "^0.4", ), diff --git a/rs/crypto/ed25519/BUILD.bazel b/rs/crypto/ed25519/BUILD.bazel new file mode 100644 index 00000000000..4d0ad0f49cd --- /dev/null +++ b/rs/crypto/ed25519/BUILD.bazel @@ -0,0 +1,52 @@ +load("@rules_rust//rust:defs.bzl", "rust_doc", "rust_library", "rust_test", "rust_test_suite") + +package(default_visibility = ["//visibility:public"]) + +DEPENDENCIES = [ + "@crate_index//:ed25519-dalek", + "@crate_index//:rand", + "@crate_index//:zeroize", +] + +MACRO_DEPENDENCIES = [] + +DEV_DEPENDENCIES = [ + "@crate_index//:hex", + "@crate_index//:hex-literal", + "@crate_index//:wycheproof", +] + +MACRO_DEV_DEPENDENCIES = [] + +ALIASES = {} + +rust_library( + name = "ed25519", + srcs = glob(["src/**"]), + aliases = ALIASES, + crate_name = "ic_crypto_ed25519", + proc_macro_deps = MACRO_DEPENDENCIES, + version = "0.9.0", + deps = DEPENDENCIES, +) + +rust_doc( + name = "ed25519_doc", + crate = ":ed25519", +) + +rust_test( + name = "ed25519_test", + aliases = ALIASES, + crate = ":ed25519", + proc_macro_deps = MACRO_DEPENDENCIES + MACRO_DEV_DEPENDENCIES, + deps = DEPENDENCIES + DEV_DEPENDENCIES, +) + +rust_test_suite( + name = "ed25519_integration", + srcs = glob(["tests/**/*.rs"]), + aliases = ALIASES, + proc_macro_deps = MACRO_DEPENDENCIES + MACRO_DEV_DEPENDENCIES, + deps = [":ed25519"] + DEPENDENCIES + DEV_DEPENDENCIES, +) diff --git a/rs/crypto/ed25519/Cargo.toml b/rs/crypto/ed25519/Cargo.toml new file mode 100644 index 00000000000..1e6f86263f6 --- /dev/null +++ b/rs/crypto/ed25519/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "ic-crypto-ed25519" +version.workspace = true +authors.workspace = true +edition.workspace = true +description.workspace = true +documentation.workspace = true + +[dependencies] +ed25519-dalek = { version = "2.1.1", features = ["zeroize", "digest", "batch", "pkcs8", "pem"] } +rand = "0.8" +zeroize = { version = "1.5", features = ["zeroize_derive"] } + +[dev-dependencies] +hex = "0.4" +hex-literal = "0.4" +wycheproof = "0.5" diff --git a/rs/crypto/ed25519/src/lib.rs b/rs/crypto/ed25519/src/lib.rs new file mode 100644 index 00000000000..ecdd21958c4 --- /dev/null +++ b/rs/crypto/ed25519/src/lib.rs @@ -0,0 +1,233 @@ +use ed25519_dalek::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey}; +use ed25519_dalek::{verify_batch, Signature, Signer, SigningKey, VerifyingKey}; +use rand::{CryptoRng, Rng}; +use zeroize::ZeroizeOnDrop; + +#[derive(Copy, Clone, Debug)] +pub enum SecretKeyDecodingError { + IncorrectLength, + InvalidKeyEncoding, +} + +/// An Ed25519 secret key +#[derive(Clone, ZeroizeOnDrop, Eq, PartialEq)] +pub struct SecretKey { + sk: SigningKey, +} + +impl std::fmt::Debug for SecretKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SecretKey") + .field("public_key", &self.public_key().serialize_raw()) + .finish_non_exhaustive() // avoids printing secret information + } +} + +impl SecretKey { + /// The length in bytes of the raw private key + pub const BYTES: usize = 32; + + /// Create a new random secret Ed25519 key + pub fn generate_key(rng: &mut R) -> Self { + let sk = SigningKey::generate(rng); + Self { sk } + } + + /// Deserialize an Ed25519 key from raw format + /// + /// This is just the plain 32 byte random seed from which the + /// internal key material is derived + /// + /// This corresponds with the format used by SecretKey::serialize + pub fn deserialize_raw(bytes: &[u8]) -> Result { + let bytes = <[u8; Self::BYTES]>::try_from(bytes) + .map_err(|_| SecretKeyDecodingError::IncorrectLength)?; + let sk = SigningKey::from_bytes(&bytes); + Ok(Self { sk }) + } + + /// Deserialize an Ed25519 key from PKCS8 format + /// + /// This corresponds with the format used by SecretKey::serialize_pkcs8 + pub fn deserialize_pkcs8(bytes: &[u8]) -> Result { + let sk = SigningKey::from_pkcs8_der(bytes) + .map_err(|_| SecretKeyDecodingError::InvalidKeyEncoding)?; + Ok(Self { sk }) + } + + /// Deserialize an Ed25519 key from PKCS8 PEM format + /// + /// This corresponds with the format used by SecretKey::serialize_pkcs8 + pub fn deserialize_pkcs8_pem(pem: &str) -> Result { + let sk = SigningKey::from_pkcs8_pem(pem) + .map_err(|_| SecretKeyDecodingError::InvalidKeyEncoding)?; + Ok(Self { sk }) + } + + /// Sign a message and return a signature + /// + /// This is the non-prehashed variant of Ed25519 + pub fn sign_message(&self, msg: &[u8]) -> Vec { + self.sk.sign(msg).to_vec() + } + + /// Return the public key associated with this secret key + pub fn public_key(&self) -> PublicKey { + let pk = self.sk.verifying_key(); + PublicKey { pk } + } + + /// Serialize the Ed25519 secret key + /// + /// This returns the 32-byte encoding of the seed value + /// which is used to derive the secret scalar + pub fn serialize_raw(&self) -> [u8; Self::BYTES] { + self.sk.to_bytes() + } + + /// Serialize the Ed25519 secret key in PKCS8 format + /// + /// This is the "v2" PKCS8 format which includes the public key + pub fn serialize_pkcs8(&self) -> Vec { + self.sk + .to_pkcs8_der() + .expect("Failed to encode key as PKCS8") + .to_bytes() + .to_vec() + } + + /// Serialize the Ed25519 secret key in PKCS8 format with PEM encoding + pub fn serialize_pkcs8_pem(&self) -> String { + self.sk + .to_pkcs8_pem(Default::default()) + .expect("Failed to encode key as PKCS8") + .to_string() + } +} + +#[derive(Copy, Clone, Debug)] +pub enum PublicKeyDecodingError { + InvalidLength, + InvalidPublicKey, + KeyNotTorsionFree, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[repr(transparent)] +pub struct PublicKey { + pk: VerifyingKey, +} + +#[derive(Copy, Clone, Debug)] +pub enum SignatureError { + InvalidLength, + InvalidBatch, + InvalidSignature, +} + +impl PublicKey { + pub const BYTES: usize = 32; + + /// Internal constructor + /// + /// Checks the point for validity before returning + fn new(pk: VerifyingKey) -> Result { + // TODO(CRP-2412) This can be changed to `to_edwards().is_torsion_free()` once + // https://github.com/dalek-cryptography/curve25519-dalek/issues/624 + // makes it into a release + if !pk.to_montgomery().to_edwards(0).unwrap().is_torsion_free() { + return Err(PublicKeyDecodingError::KeyNotTorsionFree)?; + } + + // We don't need to call is_weak here since that is subsumed by the + // test that the point is torsion free - is_weak just checks if the + // point is within the size-8 cofactor group. + + Ok(Self { pk }) + } + + /// Deserialize a public key in raw format + /// + /// This is just the 32 byte encoding of the public point + pub fn deserialize_raw(bytes: &[u8]) -> Result { + let bytes = <[u8; Self::BYTES]>::try_from(bytes) + .map_err(|_| PublicKeyDecodingError::InvalidLength)?; + let pk = VerifyingKey::from_bytes(&bytes) + .map_err(|_| PublicKeyDecodingError::InvalidPublicKey)?; + + Self::new(pk) + } + + /// Serialize this public key in raw format + /// + /// This is just the 32 byte encoding of the public point + pub fn serialize_raw(&self) -> [u8; Self::BYTES] { + *self.pk.as_bytes() + } + + /// Serialize this public key as a DER encoded structure + /// + /// See RFC 8410 for details on the format + pub fn serialize_rfc8410_der(&self) -> Vec { + self.pk + .to_public_key_der() + .expect("Encoding public key as DER failed") + .as_bytes() + .to_vec() + } + + /// Serialize this public key as a DER encoded structure + /// + /// See RFC 8410 for details on the format + pub fn deserialize_rfc8410_der(bytes: &[u8]) -> Result { + let pk = VerifyingKey::from_public_key_der(bytes) + .map_err(|_| PublicKeyDecodingError::InvalidPublicKey)?; + Self::new(pk) + } + + /// Verify a Ed25519 signature + /// + /// Returns Ok if the signature is valid, or Err otherwise + pub fn verify_signature(&self, msg: &[u8], signature: &[u8]) -> Result<(), SignatureError> { + let signature = + Signature::from_slice(signature).map_err(|_| SignatureError::InvalidLength)?; + + // We use the batch verification API also for single signatures to ensure + // there is no discrepency between batch and single signature verification; + // Ed25519 generally has problems with this; see + // https://hdevalence.ca/blog/2020-10-04-its-25519am + verify_batch(&[msg], &[signature], &[self.pk]).map_err(|_| SignatureError::InvalidSignature) + } + + /// Verify a batch of signatures + /// + /// Returns Ok if the signatures are all valid, or Err otherwise + /// + /// Note that this does not indicate which of the signature(s) are invalid; + /// if batch verification fails you must then test serially to find the + /// valid signatures (if any). + pub fn batch_verify( + messages: &[&[u8]], + signatures: &[&[u8]], + keys: &[Self], + ) -> Result<(), SignatureError> { + if messages.len() != signatures.len() || signatures.len() != keys.len() { + return Err(SignatureError::InvalidBatch); + } + + let signatures = signatures + .iter() + .map(|s| Signature::from_slice(s)) + .collect::, _>>() + .map_err(|_| SignatureError::InvalidLength)?; + + // This is safe because Self is a repr(transparent) wrapper around VerifyingKey + // + // Alternate approach, at the cost of copying all of the keys + // let keys = keys.iter().map(|k| k.pk).collect::>(); + let keys = + unsafe { std::slice::from_raw_parts(keys.as_ptr() as *const VerifyingKey, keys.len()) }; + + verify_batch(messages, &signatures, keys).map_err(|_| SignatureError::InvalidSignature) + } +} diff --git a/rs/crypto/ed25519/tests/tests.rs b/rs/crypto/ed25519/tests/tests.rs new file mode 100644 index 00000000000..4d25f6585c6 --- /dev/null +++ b/rs/crypto/ed25519/tests/tests.rs @@ -0,0 +1,209 @@ +use hex_literal::hex; +use ic_crypto_ed25519::*; +use rand::Rng; + +#[test] +fn secret_key_serialization_round_trips() { + let mut rng = &mut rand::thread_rng(); + for _ in 0..100 { + let key = SecretKey::generate_key(&mut rng); + + let via_raw = SecretKey::deserialize_raw(&key.serialize_raw()).unwrap(); + assert_eq!(key, via_raw); + + let via_pkcs8 = SecretKey::deserialize_pkcs8(&key.serialize_pkcs8()).unwrap(); + assert_eq!(key, via_pkcs8); + + let via_pem = SecretKey::deserialize_pkcs8_pem(&key.serialize_pkcs8_pem()).unwrap(); + assert_eq!(key, via_pem); + } +} + +#[test] +fn pkcs8_rep_includes_the_public_key() { + let mut rng = &mut rand::thread_rng(); + let sk = SecretKey::generate_key(&mut rng); + let pk = sk.public_key().serialize_raw(); + + let sk_pkcs8 = sk.serialize_pkcs8(); + + let pk_offset = sk_pkcs8.len() - pk.len(); + + assert_eq!(hex::encode(pk), hex::encode(&sk_pkcs8[pk_offset..])); +} + +#[test] +fn signatures_we_generate_will_verify() { + let mut rng = &mut rand::thread_rng(); + for _ in 0..100 { + let sk = SecretKey::generate_key(&mut rng); + let pk = sk.public_key(); + + let msg = rng.gen::<[u8; 32]>(); + + let sig = sk.sign_message(&msg); + assert_eq!(sig.len(), 64); + + assert!(pk.verify_signature(&msg, &sig).is_ok()); + } +} + +#[test] +fn public_key_deserialization_rejects_key_not_on_curve() { + let invalid_pk = hex!("0200000000000000000000000000000000000000000000000000000000000000"); + assert!(PublicKey::deserialize_raw(&invalid_pk).is_err()); +} + +#[test] +fn public_key_deserialization_rejects_keys_of_incorrect_length() { + for len in 0..128 { + if len == PublicKey::BYTES { + continue; + } + + let buf = vec![2; len]; + + assert!(PublicKey::deserialize_raw(&buf).is_err()); + } +} + +#[test] +fn batch_verification_works() { + fn batch_verifies(msg: &[[u8; 32]], sigs: &[Vec], keys: &[PublicKey]) -> bool { + let msg_ref = msg.iter().map(|m| m.as_ref()).collect::>(); + let sig_ref = sigs.iter().map(|s| s.as_ref()).collect::>(); + PublicKey::batch_verify(&msg_ref, &sig_ref, keys).is_ok() + } + + // Return two distinct positions in [0..max) + fn two_positions(max: usize, rng: &mut R) -> (usize, usize) { + assert!(max > 1); + + let pos0 = rng.gen::() % max; + + loop { + let pos1 = rng.gen::() % max; + if pos0 != pos1 { + return (pos0, pos1); + } + } + } + + let mut rng = &mut rand::thread_rng(); + + for batch_size in 1..15 { + let sk = (0..batch_size) + .map(|_| SecretKey::generate_key(&mut rng)) + .collect::>(); + let mut pk = sk.iter().map(|k| k.public_key()).collect::>(); + + let mut msg = (0..batch_size) + .map(|_| rng.gen::<[u8; 32]>()) + .collect::>(); + let mut sigs = (0..batch_size) + .map(|i| sk[i].sign_message(&msg[i])) + .collect::>(); + + assert!(batch_verifies(&msg, &sigs, &pk)); + + // Corrupt a random signature and check that the batch fails: + let corrupted_sig_idx = rng.gen::() % batch_size; + let corrupted_sig_byte = rng.gen::() % 64; + let corrupted_sig_mask = std::cmp::max(1, rng.gen::()); + sigs[corrupted_sig_idx][corrupted_sig_byte] ^= corrupted_sig_mask; + assert!(!batch_verifies(&msg, &sigs, &pk)); + + // Uncorrupt the signature, then corrupt a random message, verify it fails: + sigs[corrupted_sig_idx][corrupted_sig_byte] ^= corrupted_sig_mask; + // We fixed the signature so the batch should verify again: + debug_assert!(batch_verifies(&msg, &sigs, &pk)); + + let corrupted_msg_idx = rng.gen::() % batch_size; + let corrupted_msg_byte = rng.gen::() % 32; + let corrupted_msg_mask = std::cmp::max(1, rng.gen::()); + msg[corrupted_msg_idx][corrupted_msg_byte] ^= corrupted_msg_mask; + assert!(!batch_verifies(&msg, &sigs, &pk)); + + // Fix the corrupted message + msg[corrupted_msg_idx][corrupted_msg_byte] ^= corrupted_msg_mask; + + if batch_size > 1 { + // Swapping a key causes batch verification to fail: + let (swap0, swap1) = two_positions(batch_size, rng); + pk.swap(swap0, swap1); + assert!(!batch_verifies(&msg, &sigs, &pk)); + + // If we swap (also) the message, verification still fails: + msg.swap(swap0, swap1); + assert!(!batch_verifies(&msg, &sigs, &pk)); + + // If we swap the signature so it is consistent, batch is accepted: + sigs.swap(swap0, swap1); + assert!(batch_verifies(&msg, &sigs, &pk)); + } + } +} + +#[test] +fn test_der_public_key_conversions() { + let test_data = [ + (hex!("b3997656ba51ff6da37b61d8d549ec80717266ecf48fb5da52b654412634844c"), + hex!("302a300506032b6570032100b3997656ba51ff6da37b61d8d549ec80717266ecf48fb5da52b654412634844c")), + (hex!("a5afb5feb6dfb6ddf5dd6563856fff5484f5fe304391d9ed06697861f220c610"), + hex!("302a300506032b6570032100a5afb5feb6dfb6ddf5dd6563856fff5484f5fe304391d9ed06697861f220c610")), + ]; + + for (raw, der) in &test_data { + let pk_raw = PublicKey::deserialize_raw(raw).unwrap(); + + let pk_der = PublicKey::deserialize_rfc8410_der(der).unwrap(); + + assert_eq!(pk_raw, pk_der); + assert_eq!(pk_raw.serialize_rfc8410_der(), der); + assert_eq!(pk_der.serialize_raw(), *raw); + } +} + +#[test] +fn can_parse_pkcs8_v1_der_secret_key() { + let pkcs8_v1 = hex!("302e020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842"); + let sk = SecretKey::deserialize_pkcs8(&pkcs8_v1).unwrap(); + + assert_eq!( + hex::encode(sk.serialize_raw()), + "d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842" + ); +} + +#[test] +fn can_parse_pkcs8_v2_der_secret_key() { + // From ring test data + let pkcs8_v2 = hex!("3051020101300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f4475584281210019bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1"); + + let sk = SecretKey::deserialize_pkcs8(&pkcs8_v2).unwrap(); + + assert_eq!( + hex::encode(sk.serialize_raw()), + "d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842" + ); +} + +#[test] +fn should_pass_wycheproof_test_vectors() { + let test_set = wycheproof::eddsa::TestSet::load(wycheproof::eddsa::TestName::Ed25519) + .expect("Unable to load tests"); + + for test_group in test_set.test_groups { + let pk = PublicKey::deserialize_raw(&test_group.key.pk).unwrap(); + + for test in test_group.tests { + let accept = pk.verify_signature(&test.msg, &test.sig).is_ok(); + + if test.result == wycheproof::TestResult::Valid { + assert!(accept); + } else { + assert!(!accept); + } + } + } +}