From 241cb415592f935d3a27b0bf9e955756d55b7bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 16 Feb 2022 16:32:31 +0100 Subject: [PATCH 01/56] Add IETF-compatible hasher --- ec/Cargo.toml | 11 +- ec/src/hashing/field_hashers/expander/mod.rs | 117 ++++++++++++++++ .../expand_message_xmd_SHA256_256.json | 78 +++++++++++ .../expand_message_xmd_SHA256_38.json | 78 +++++++++++ .../expand_message_xmd_SHA512_38.json | 78 +++++++++++ .../expand_message_xof_SHAKE128_256.json | 78 +++++++++++ .../expand_message_xof_SHAKE128_36.json | 78 +++++++++++ .../expand_message_xof_SHAKE256_36.json | 78 +++++++++++ .../hashing/field_hashers/expander/tests.rs | 132 ++++++++++++++++++ ec/src/hashing/field_hashers/ietf_hasher.rs | 76 ++++++++++ ec/src/hashing/field_hashers/mod.rs | 105 +++----------- ec/src/hashing/map_to_curve_hasher.rs | 8 +- ec/src/hashing/tests.rs | 13 +- 13 files changed, 828 insertions(+), 102 deletions(-) create mode 100644 ec/src/hashing/field_hashers/expander/mod.rs create mode 100644 ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json create mode 100644 ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json create mode 100644 ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json create mode 100644 ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json create mode 100644 ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json create mode 100644 ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json create mode 100644 ec/src/hashing/field_hashers/expander/tests.rs create mode 100644 ec/src/hashing/field_hashers/ietf_hasher.rs diff --git a/ec/Cargo.toml b/ec/Cargo.toml index 88acfe498..fbbb1dd12 100644 --- a/ec/Cargo.toml +++ b/ec/Cargo.toml @@ -23,11 +23,18 @@ digest = { version = "0.10", default-features = false } num-traits = { version = "0.2", default-features = false } rayon = { version = "1", optional = true } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } +lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] } [dev-dependencies] hashbrown = { version = "0.11.1" } -blake2 = { version = "0.10", default-features = false } -ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = ["bls12_381_curve"] } +ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = [ "bls12_381_curve"] } +sha3 = "0.10" +sha2 = "0.10" +libtest-mimic = "0.3.0" +serde = "1.0.110" +serde_json = "1.0.53" +serde_derive = "1.0.110" +hex = "0.4" [features] default = [] diff --git a/ec/src/hashing/field_hashers/expander/mod.rs b/ec/src/hashing/field_hashers/expander/mod.rs new file mode 100644 index 000000000..988e8a62e --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/mod.rs @@ -0,0 +1,117 @@ +// The below implementation is a rework of https://github.com/armfazh/h2c-rust-ref +// With some optimisations; + +use ark_std::vec::Vec; +use digest::{DynDigest, ExtendableOutput, Update}; +use lazy_static::lazy_static; +pub trait Expander { + fn construct_dst_prime(&self) -> Vec; + fn expand(&self, msg: &[u8], length: usize) -> Vec; +} +const MAX_DST_LENGTH: usize = 255; + +lazy_static! { +static ref LONG_DST_PREFIX: Vec = vec![ + //'H', '2', 'C', '-', 'O', 'V', 'E', 'R', 'S', 'I', 'Z', 'E', '-', 'D', 'S', 'T', '-', + 0x48, 0x32, 0x43, 0x2d, 0x4f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x5a, 0x45, 0x2d, 0x44, 0x53, 0x54, 0x2d, +]; +} + +pub(super) struct ExpanderXof { + pub(super) xofer: T, + pub(super) dst: Vec, + pub(super) k: usize, +} + +impl Expander for ExpanderXof { + fn construct_dst_prime(&self) -> Vec { + let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { + let mut xofer = self.xofer.clone(); + xofer.update(&LONG_DST_PREFIX.clone()); + xofer.update(&self.dst); + xofer.finalize_boxed((2 * self.k + 7) >> 3).to_vec() + } else { + self.dst.clone() + }; + dst_prime.push(dst_prime.len() as u8); + dst_prime + } + fn expand(&self, msg: &[u8], n: usize) -> Vec { + let dst_prime = self.construct_dst_prime(); + let lib_str = &[((n >> 8) & 0xFF) as u8, (n & 0xFF) as u8]; + + let mut xofer = self.xofer.clone(); + xofer.update(msg); + xofer.update(lib_str); + xofer.update(&dst_prime); + xofer.finalize_boxed(n).to_vec() + } +} + +pub(super) struct ExpanderXmd { + pub(super) hasher: T, + pub(super) dst: Vec, + pub(super) block_size: usize, +} + +impl Expander for ExpanderXmd { + fn construct_dst_prime(&self) -> Vec { + let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { + let mut hasher = self.hasher.clone(); + hasher.update(&LONG_DST_PREFIX); + hasher.update(&self.dst); + hasher.finalize_reset().to_vec() + } else { + self.dst.clone() + }; + dst_prime.push(dst_prime.len() as u8); + dst_prime + } + fn expand(&self, msg: &[u8], n: usize) -> Vec { + let mut hasher = self.hasher.clone(); + // output size of the hash function, e.g. 32 bytes = 256 bits for sha2::Sha256 + let b_len = hasher.output_size(); + let ell = (n + (b_len - 1)) / b_len; + assert!( + ell <= 255, + "The ratio of desired output to the output size of hash function is too large!" + ); + + let dst_prime = self.construct_dst_prime(); + let z_pad: Vec = vec![0; self.block_size]; + // // Represent `len_in_bytes` as a 2-byte array. + // // As per I2OSP method outlined in https://tools.ietf.org/pdf/rfc8017.pdf, + // // The program should abort if integer that we're trying to convert is too large. + assert!(n < (1 << 16), "Length should be smaller than 2^16"); + let lib_str: [u8; 2] = (n as u16).to_be_bytes(); + + hasher.update(&z_pad); + hasher.update(msg); + hasher.update(&lib_str); + hasher.update(&[0u8]); + hasher.update(&dst_prime); + let b0 = hasher.finalize_reset(); + + hasher.update(&b0); + hasher.update(&[1u8]); + hasher.update(&dst_prime); + let mut bi = hasher.finalize_reset(); + + let mut uniform_bytes: Vec = Vec::with_capacity(n); + uniform_bytes.extend_from_slice(&bi); + for i in 2..=ell { + // update the hasher with xor of b_0 and b_i elements + for (l, r) in b0.iter().zip(bi.iter()) { + hasher.update(&[*l ^ *r]); + } + hasher.update(&[i as u8]); + hasher.update(&dst_prime); + bi = hasher.finalize_reset(); + uniform_bytes.extend_from_slice(&bi); + } + uniform_bytes[0..n].to_vec() + } +} + +#[cfg(all(test, feature = "std"))] +mod tests; diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json new file mode 100644 index 000000000..b5e2aa3f4 --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json @@ -0,0 +1,78 @@ +{ + "DST": "QUUX-V01-CS02-with-expander-SHA256-128-long-DST-1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "hash": "SHA256", + "k": 128, + "name": "expand_message_xmd", + "tests": [ + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x20", + "msg": "", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "e8dc0c8b686b7ef2074086fbdd2f30e3f8bfbd3bdf177f73f04b97ce618a3ed3" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x20", + "msg": "abc", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "52dbf4f36cf560fca57dedec2ad924ee9c266341d8f3d6afe5171733b16bbb12" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x20", + "msg": "abcdef0123456789", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "35387dcf22618f3728e6c686490f8b431f76550b0b2c61cbc1ce7001536f4521" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x20", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "01b637612bb18e840028be900a833a74414140dde0c4754c198532c3a0ba42bc" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x20", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "20cce7033cabc5460743180be6fa8aac5a103f56d481cf369a8accc0c374431b" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x80", + "msg": "", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "14604d85432c68b757e485c8894db3117992fc57e0e136f71ad987f789a0abc287c47876978e2388a02af86b1e8d1342e5ce4f7aaa07a87321e691f6fba7e0072eecc1218aebb89fb14a0662322d5edbd873f0eb35260145cd4e64f748c5dfe60567e126604bcab1a3ee2dc0778102ae8a5cfd1429ebc0fa6bf1a53c36f55dfc" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x80", + "msg": "abc", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "1a30a5e36fbdb87077552b9d18b9f0aee16e80181d5b951d0471d55b66684914aef87dbb3626eaabf5ded8cd0686567e503853e5c84c259ba0efc37f71c839da2129fe81afdaec7fbdc0ccd4c794727a17c0d20ff0ea55e1389d6982d1241cb8d165762dbc39fb0cee4474d2cbbd468a835ae5b2f20e4f959f56ab24cd6fe267" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x80", + "msg": "abcdef0123456789", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "d2ecef3635d2397f34a9f86438d772db19ffe9924e28a1caf6f1c8f15603d4028f40891044e5c7e39ebb9b31339979ff33a4249206f67d4a1e7c765410bcd249ad78d407e303675918f20f26ce6d7027ed3774512ef5b00d816e51bfcc96c3539601fa48ef1c07e494bdc37054ba96ecb9dbd666417e3de289d4f424f502a982" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x80", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "ed6e8c036df90111410431431a232d41a32c86e296c05d426e5f44e75b9a50d335b2412bc6c91e0a6dc131de09c43110d9180d0a70f0d6289cb4e43b05f7ee5e9b3f42a1fad0f31bac6a625b3b5c50e3a83316783b649e5ecc9d3b1d9471cb5024b7ccf40d41d1751a04ca0356548bc6e703fca02ab521b505e8e45600508d32" + }, + { + "DST_prime": "412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "len_in_bytes": "0x80", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620", + "uniform_bytes": "78b53f2413f3c688f07732c10e5ced29a17c6a16f717179ffbe38d92d6c9ec296502eb9889af83a1928cd162e845b0d3c5424e83280fed3d10cffb2f8431f14e7a23f4c68819d40617589e4c41169d0b56e0e3535be1fd71fbb08bb70c5b5ffed953d6c14bf7618b35fc1f4c4b30538236b4b08c9fbf90462447a8ada60be495" + } + ] +} diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json new file mode 100644 index 000000000..e6a8c7481 --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json @@ -0,0 +1,78 @@ +{ + "DST": "QUUX-V01-CS02-with-expander-SHA256-128", + "hash": "SHA256", + "k": 128, + "name": "expand_message_xmd", + "tests": [ + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x20", + "msg": "", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "68a985b87eb6b46952128911f2a4412bbc302a9d759667f87f7a21d803f07235" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x20", + "msg": "abc", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "d8ccab23b5985ccea865c6c97b6e5b8350e794e603b4b97902f53a8a0d605615" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x20", + "msg": "abcdef0123456789", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "eff31487c770a893cfb36f912fbfcbff40d5661771ca4b2cb4eafe524333f5c1" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x20", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "b23a1d2b4d97b2ef7785562a7e8bac7eed54ed6e97e29aa51bfe3f12ddad1ff9" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x20", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "4623227bcc01293b8c130bf771da8c298dede7383243dc0993d2d94823958c4c" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x80", + "msg": "", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "af84c27ccfd45d41914fdff5df25293e221afc53d8ad2ac06d5e3e29485dadbee0d121587713a3e0dd4d5e69e93eb7cd4f5df4cd103e188cf60cb02edc3edf18eda8576c412b18ffb658e3dd6ec849469b979d444cf7b26911a08e63cf31f9dcc541708d3491184472c2c29bb749d4286b004ceb5ee6b9a7fa5b646c993f0ced" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x80", + "msg": "abc", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "abba86a6129e366fc877aab32fc4ffc70120d8996c88aee2fe4b32d6c7b6437a647e6c3163d40b76a73cf6a5674ef1d890f95b664ee0afa5359a5c4e07985635bbecbac65d747d3d2da7ec2b8221b17b0ca9dc8a1ac1c07ea6a1e60583e2cb00058e77b7b72a298425cd1b941ad4ec65e8afc50303a22c0f99b0509b4c895f40" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x80", + "msg": "abcdef0123456789", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "ef904a29bffc4cf9ee82832451c946ac3c8f8058ae97d8d629831a74c6572bd9ebd0df635cd1f208e2038e760c4994984ce73f0d55ea9f22af83ba4734569d4bc95e18350f740c07eef653cbb9f87910d833751825f0ebefa1abe5420bb52be14cf489b37fe1a72f7de2d10be453b2c9d9eb20c7e3f6edc5a60629178d9478df" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x80", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "80be107d0884f0d881bb460322f0443d38bd222db8bd0b0a5312a6fedb49c1bbd88fd75d8b9a09486c60123dfa1d73c1cc3169761b17476d3c6b7cbbd727acd0e2c942f4dd96ae3da5de368d26b32286e32de7e5a8cb2949f866a0b80c58116b29fa7fabb3ea7d520ee603e0c25bcaf0b9a5e92ec6a1fe4e0391d1cdbce8c68a" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "len_in_bytes": "0x80", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", + "uniform_bytes": "546aff5444b5b79aa6148bd81728704c32decb73a3ba76e9e75885cad9def1d06d6792f8a7d12794e90efed817d96920d728896a4510864370c207f99bd4a608ea121700ef01ed879745ee3e4ceef777eda6d9e5e38b90c86ea6fb0b36504ba4a45d22e86f6db5dd43d98a294bebb9125d5b794e9d2a81181066eb954966a487" + } + ] +} diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json new file mode 100644 index 000000000..18dadd1b5 --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json @@ -0,0 +1,78 @@ +{ + "DST": "QUUX-V01-CS02-with-expander-SHA512-256", + "hash": "SHA512", + "k": 256, + "name": "expand_message_xmd", + "tests": [ + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x20", + "msg": "", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "6b9a7312411d92f921c6f68ca0b6380730a1a4d982c507211a90964c394179ba" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x20", + "msg": "abc", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "0da749f12fbe5483eb066a5f595055679b976e93abe9be6f0f6318bce7aca8dc" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x20", + "msg": "abcdef0123456789", + "msg_prime": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "087e45a86e2939ee8b91100af1583c4938e0f5fc6c9db4b107b83346bc967f58" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x20", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "7336234ee9983902440f6bc35b348352013becd88938d2afec44311caf8356b3" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x20", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "57b5f7e766d5be68a6bfe1768e3c2b7f1228b3e4b3134956dd73a59b954c66f4" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x80", + "msg": "", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "41b037d1734a5f8df225dd8c7de38f851efdb45c372887be655212d07251b921b052b62eaed99b46f72f2ef4cc96bfaf254ebbbec091e1a3b9e4fb5e5b619d2e0c5414800a1d882b62bb5cd1778f098b8eb6cb399d5d9d18f5d5842cf5d13d7eb00a7cff859b605da678b318bd0e65ebff70bec88c753b159a805d2c89c55961" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x80", + "msg": "abc", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "7f1dddd13c08b543f2e2037b14cefb255b44c83cc397c1786d975653e36a6b11bdd7732d8b38adb4a0edc26a0cef4bb45217135456e58fbca1703cd6032cb1347ee720b87972d63fbf232587043ed2901bce7f22610c0419751c065922b488431851041310ad659e4b23520e1772ab29dcdeb2002222a363f0c2b1c972b3efe1" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x80", + "msg": "abcdef0123456789", + "msg_prime": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "3f721f208e6199fe903545abc26c837ce59ac6fa45733f1baaf0222f8b7acb0424814fcb5eecf6c1d38f06e9d0a6ccfbf85ae612ab8735dfdf9ce84c372a77c8f9e1c1e952c3a61b7567dd0693016af51d2745822663d0c2367e3f4f0bed827feecc2aaf98c949b5ed0d35c3f1023d64ad1407924288d366ea159f46287e61ac" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x80", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "b799b045a58c8d2b4334cf54b78260b45eec544f9f2fb5bd12fb603eaee70db7317bf807c406e26373922b7b8920fa29142703dd52bdf280084fb7ef69da78afdf80b3586395b433dc66cde048a258e476a561e9deba7060af40adf30c64249ca7ddea79806ee5beb9a1422949471d267b21bc88e688e4014087a0b592b695ed" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "len_in_bytes": "0x80", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626", + "uniform_bytes": "05b0bfef265dcee87654372777b7c44177e2ae4c13a27f103340d9cd11c86cb2426ffcad5bd964080c2aee97f03be1ca18e30a1f14e27bc11ebbd650f305269cc9fb1db08bf90bfc79b42a952b46daf810359e7bc36452684784a64952c343c52e5124cd1f71d474d5197fefc571a92929c9084ffe1112cf5eea5192ebff330b" + } + ] +} diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json new file mode 100644 index 000000000..e750a8053 --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json @@ -0,0 +1,78 @@ +{ + "DST": "QUUX-V01-CS02-with-expander-SHAKE128-long-DST-111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "hash": "SHAKE128", + "k": 128, + "name": "expand_message_xof", + "tests": [ + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x20", + "msg": "", + "msg_prime": "0020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "827c6216330a122352312bccc0c8d6e7a146c5257a776dbd9ad9d75cd880fc53" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x20", + "msg": "abc", + "msg_prime": "6162630020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "690c8d82c7213b4282c6cb41c00e31ea1d3e2005f93ad19bbf6da40f15790c5c" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x20", + "msg": "abcdef0123456789", + "msg_prime": "616263646566303132333435363738390020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "979e3a15064afbbcf99f62cc09fa9c85028afcf3f825eb0711894dcfc2f57057" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x20", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "c5a9220962d9edc212c063f4f65b609755a1ed96e62f9db5d1fd6adb5a8dc52b" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x20", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "f7b96a5901af5d78ce1d071d9c383cac66a1dfadb508300ec6aeaea0d62d5d62" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x80", + "msg": "", + "msg_prime": "0080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "3890dbab00a2830be398524b71c2713bbef5f4884ac2e6f070b092effdb19208c7df943dc5dcbaee3094a78c267ef276632ee2c8ea0c05363c94b6348500fae4208345dd3475fe0c834c2beac7fa7bc181692fb728c0a53d809fc8111495222ce0f38468b11becb15b32060218e285c57a60162c2c8bb5b6bded13973cd41819" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x80", + "msg": "abc", + "msg_prime": "6162630080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "41b7ffa7a301b5c1441495ebb9774e2a53dbbf4e54b9a1af6a20fd41eafd69ef7b9418599c5545b1ee422f363642b01d4a53449313f68da3e49dddb9cd25b97465170537d45dcbdf92391b5bdff344db4bd06311a05bca7dcd360b6caec849c299133e5c9194f4e15e3e23cfaab4003fab776f6ac0bfae9144c6e2e1c62e7d57" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x80", + "msg": "abcdef0123456789", + "msg_prime": "616263646566303132333435363738390080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "55317e4a21318472cd2290c3082957e1242241d9e0d04f47026f03401643131401071f01aa03038b2783e795bdfa8a3541c194ad5de7cb9c225133e24af6c86e748deb52e560569bd54ef4dac03465111a3a44b0ea490fb36777ff8ea9f1a8a3e8e0de3cf0880b4b2f8dd37d3a85a8b82375aee4fa0e909f9763319b55778e71" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x80", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "19fdd2639f082e31c77717ac9bb032a22ff0958382b2dbb39020cdc78f0da43305414806abf9a561cb2d0067eb2f7bc544482f75623438ed4b4e39dd9e6e2909dd858bd8f1d57cd0fce2d3150d90aa67b4498bdf2df98c0100dd1a173436ba5d0df6be1defb0b2ce55ccd2f4fc05eb7cb2c019c35d5398b85adc676da4238bc7" + }, + { + "DST_prime": "acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "len_in_bytes": "0x80", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20", + "uniform_bytes": "945373f0b3431a103333ba6a0a34f1efab2702efde41754c4cb1d5216d5b0a92a67458d968562bde7fa6310a83f53dda1383680a276a283438d58ceebfa7ab7ba72499d4a3eddc860595f63c93b1c5e823ea41fc490d938398a26db28f61857698553e93f0574eb8c5017bfed6249491f9976aaa8d23d9485339cc85ca329308" + } + ] +} diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json new file mode 100644 index 000000000..ee014c554 --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json @@ -0,0 +1,78 @@ +{ + "DST": "QUUX-V01-CS02-with-expander-SHAKE128", + "hash": "SHAKE128", + "k": 128, + "name": "expand_message_xof", + "tests": [ + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x20", + "msg": "", + "msg_prime": "0020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "86518c9cd86581486e9485aa74ab35ba150d1c75c88e26b7043e44e2acd735a2" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x20", + "msg": "abc", + "msg_prime": "6162630020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "8696af52a4d862417c0763556073f47bc9b9ba43c99b505305cb1ec04a9ab468" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x20", + "msg": "abcdef0123456789", + "msg_prime": "616263646566303132333435363738390020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "912c58deac4821c3509dbefa094df54b34b8f5d01a191d1d3108a2c89077acca" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x20", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "1adbcc448aef2a0cebc71dac9f756b22e51839d348e031e63b33ebb50faeaf3f" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x20", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "df3447cc5f3e9a77da10f819218ddf31342c310778e0e4ef72bbaecee786a4fe" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x80", + "msg": "", + "msg_prime": "0080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "7314ff1a155a2fb99a0171dc71b89ab6e3b2b7d59e38e64419b8b6294d03ffee42491f11370261f436220ef787f8f76f5b26bdcd850071920ce023f3ac46847744f4612b8714db8f5db83205b2e625d95afd7d7b4d3094d3bdde815f52850bb41ead9822e08f22cf41d615a303b0d9dde73263c049a7b9898208003a739a2e57" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x80", + "msg": "abc", + "msg_prime": "6162630080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "c952f0c8e529ca8824acc6a4cab0e782fc3648c563ddb00da7399f2ae35654f4860ec671db2356ba7baa55a34a9d7f79197b60ddae6e64768a37d699a78323496db3878c8d64d909d0f8a7de4927dcab0d3dbbc26cb20a49eceb0530b431cdf47bc8c0fa3e0d88f53b318b6739fbed7d7634974f1b5c386d6230c76260d5337a" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x80", + "msg": "abcdef0123456789", + "msg_prime": "616263646566303132333435363738390080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "19b65ee7afec6ac06a144f2d6134f08eeec185f1a890fe34e68f0e377b7d0312883c048d9b8a1d6ecc3b541cb4987c26f45e0c82691ea299b5e6889bbfe589153016d8131717ba26f07c3c14ffbef1f3eff9752e5b6183f43871a78219a75e7000fbac6a7072e2b83c790a3a5aecd9d14be79f9fd4fb180960a3772e08680495" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x80", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "ca1b56861482b16eae0f4a26212112362fcc2d76dcc80c93c4182ed66c5113fe41733ed68be2942a3487394317f3379856f4822a611735e50528a60e7ade8ec8c71670fec6661e2c59a09ed36386513221688b35dc47e3c3111ee8c67ff49579089d661caa29db1ef10eb6eace575bf3dc9806e7c4016bd50f3c0e2a6481ee6d" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "len_in_bytes": "0x80", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824", + "uniform_bytes": "9d763a5ce58f65c91531b4100c7266d479a5d9777ba761693d052acd37d149e7ac91c796a10b919cd74a591a1e38719fb91b7203e2af31eac3bff7ead2c195af7d88b8bc0a8adf3d1e90ab9bed6ddc2b7f655dd86c730bdeaea884e73741097142c92f0e3fc1811b699ba593c7fbd81da288a29d423df831652e3a01a9374999" + } + ] +} diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json new file mode 100644 index 000000000..7714dd39a --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json @@ -0,0 +1,78 @@ +{ + "DST": "QUUX-V01-CS02-with-expander-SHAKE256", + "hash": "SHAKE256", + "k": 256, + "name": "expand_message_xof", + "tests": [ + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x20", + "msg": "", + "msg_prime": "0020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "2ffc05c48ed32b95d72e807f6eab9f7530dd1c2f013914c8fed38c5ccc15ad76" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x20", + "msg": "abc", + "msg_prime": "6162630020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "b39e493867e2767216792abce1f2676c197c0692aed061560ead251821808e07" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x20", + "msg": "abcdef0123456789", + "msg_prime": "616263646566303132333435363738390020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "245389cf44a13f0e70af8665fe5337ec2dcd138890bb7901c4ad9cfceb054b65" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x20", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "719b3911821e6428a5ed9b8e600f2866bcf23c8f0515e52d6c6c019a03f16f0e" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x20", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "9181ead5220b1963f1b5951f35547a5ea86a820562287d6ca4723633d17ccbbc" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x80", + "msg": "", + "msg_prime": "0080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "7a1361d2d7d82d79e035b8880c5a3c86c5afa719478c007d96e6c88737a3f631dd74a2c88df79a4cb5e5d9f7504957c70d669ec6bfedc31e01e2bacc4ff3fdf9b6a00b17cc18d9d72ace7d6b81c2e481b4f73f34f9a7505dccbe8f5485f3d20c5409b0310093d5d6492dea4e18aa6979c23c8ea5de01582e9689612afbb353df" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x80", + "msg": "abc", + "msg_prime": "6162630080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "a54303e6b172909783353ab05ef08dd435a558c3197db0c132134649708e0b9b4e34fb99b92a9e9e28fc1f1d8860d85897a8e021e6382f3eea10577f968ff6df6c45fe624ce65ca25932f679a42a404bc3681efe03fcd45ef73bb3a8f79ba784f80f55ea8a3c367408f30381299617f50c8cf8fbb21d0f1e1d70b0131a7b6fbe" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x80", + "msg": "abcdef0123456789", + "msg_prime": "616263646566303132333435363738390080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "e42e4d9538a189316e3154b821c1bafb390f78b2f010ea404e6ac063deb8c0852fcd412e098e231e43427bd2be1330bb47b4039ad57b30ae1fc94e34993b162ff4d695e42d59d9777ea18d3848d9d336c25d2acb93adcad009bcfb9cde12286df267ada283063de0bb1505565b2eb6c90e31c48798ecdc71a71756a9110ff373" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x80", + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "msg_prime": "713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "4ac054dda0a38a65d0ecf7afd3c2812300027c8789655e47aecf1ecc1a2426b17444c7482c99e5907afd9c25b991990490bb9c686f43e79b4471a23a703d4b02f23c669737a886a7ec28bddb92c3a98de63ebf878aa363a501a60055c048bea11840c4717beae7eee28c3cfa42857b3d130188571943a7bd747de831bd6444e0" + }, + { + "DST_prime": "515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "len_in_bytes": "0x80", + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "msg_prime": "613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624", + "uniform_bytes": "09afc76d51c2cccbc129c2315df66c2be7295a231203b8ab2dd7f95c2772c68e500bc72e20c602abc9964663b7a03a389be128c56971ce81001a0b875e7fd17822db9d69792ddf6a23a151bf470079c518279aef3e75611f8f828994a9988f4a8a256ddb8bae161e658d5a2a09bcfe839c6396dc06ee5c8ff3c22d3b1f9deb7e" + } + ] +} diff --git a/ec/src/hashing/field_hashers/expander/tests.rs b/ec/src/hashing/field_hashers/expander/tests.rs new file mode 100644 index 000000000..9ea003454 --- /dev/null +++ b/ec/src/hashing/field_hashers/expander/tests.rs @@ -0,0 +1,132 @@ +use libtest_mimic::{run_tests, Arguments, Outcome, Test}; + +use sha2::{Sha256, Sha384, Sha512}; +use sha3::{Shake128, Shake256}; +use std::fs::{read_dir, File}; +use std::io::BufReader; + +use super::{Expander, ExpanderXmd, ExpanderXof}; + +#[derive(Debug, serde_derive::Serialize, serde_derive::Deserialize)] +pub struct ExpanderVector { + #[serde(rename = "DST")] + pub dst: String, + pub k: usize, + pub hash: String, + pub name: String, + #[serde(rename = "tests")] + pub vectors: Vec, +} + +#[derive(Debug, serde_derive::Serialize, serde_derive:: Deserialize)] +pub struct TestExpander { + #[serde(rename = "DST_prime")] + pub dst_prime: String, + pub len_in_bytes: String, + pub msg: String, + pub msg_prime: String, + pub uniform_bytes: String, +} + +#[test] +fn expander() { + let args = Arguments::from_args(); + let mut tests = Vec::>::new(); + + for filename in read_dir("./src/hashing/field_hashers/expander/testdata").unwrap() { + let ff = filename.unwrap(); + let file = File::open(ff.path()).unwrap(); + let u: ExpanderVector = serde_json::from_reader(BufReader::new(file)).unwrap(); + + tests.push(Test { + name: ff.file_name().to_str().unwrap().to_string(), + data: u, + kind: String::default(), + is_ignored: false, + is_bench: false, + }); + } + + run_tests(&args, tests, do_test).exit_if_failed(); +} + +#[derive(Copy, Clone)] +pub enum ExpID { + XMD(HashID), + XOF(XofID), +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum HashID { + SHA256, + SHA384, + SHA512, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum XofID { + SHAKE128, + SHAKE256, +} + +fn do_test(Test { data, .. }: &Test) -> Outcome { + let exp_id = match data.hash.as_str() { + "SHA256" => ExpID::XMD(HashID::SHA256), + "SHA384" => ExpID::XMD(HashID::SHA384), + "SHA512" => ExpID::XMD(HashID::SHA512), + "SHAKE128" => ExpID::XOF(XofID::SHAKE128), + "SHAKE256" => ExpID::XOF(XofID::SHAKE256), + _ => unimplemented!(), + }; + let exp = get_expander(exp_id, data.dst.as_bytes(), data.k); + for v in data.vectors.iter() { + let len = usize::from_str_radix(v.len_in_bytes.trim_start_matches("0x"), 16).unwrap(); + let got = exp.expand(v.msg.as_bytes(), len); + let want = hex::decode(&v.uniform_bytes).unwrap(); + if got != want { + return Outcome::Failed { + msg: Some(format!( + "Expander: {}\nVector: {}\ngot: {:?}\nwant: {:?}", + data.hash, v.msg, got, want, + )), + }; + } + } + Outcome::Passed +} + +fn get_expander(id: ExpID, _dst: &[u8], k: usize) -> Box { + let dst = _dst.to_vec(); + + match id { + ExpID::XMD(h) => match h { + HashID::SHA256 => Box::new(ExpanderXmd { + hasher: Sha256::default(), + block_size: 64, + dst, + }), + HashID::SHA384 => Box::new(ExpanderXmd { + hasher: Sha384::default(), + block_size: 128, + dst, + }), + HashID::SHA512 => Box::new(ExpanderXmd { + hasher: Sha512::default(), + block_size: 128, + dst, + }), + }, + ExpID::XOF(x) => match x { + XofID::SHAKE128 => Box::new(ExpanderXof { + xofer: Shake128::default(), + k, + dst, + }), + XofID::SHAKE256 => Box::new(ExpanderXof { + xofer: Shake256::default(), + k, + dst, + }), + }, + } +} diff --git a/ec/src/hashing/field_hashers/ietf_hasher.rs b/ec/src/hashing/field_hashers/ietf_hasher.rs new file mode 100644 index 000000000..bd6009f8f --- /dev/null +++ b/ec/src/hashing/field_hashers/ietf_hasher.rs @@ -0,0 +1,76 @@ +use crate::hashing::*; +use crate::hashing::{field_hashers::expander::ExpanderXmd, map_to_curve_hasher::*}; +use ark_ff::{Field, PrimeField}; +use ark_std::vec::Vec; +use digest::DynDigest; + +use super::expander::Expander; +use super::get_len_per_elem; + +/// This field hasher constructs a Hash-To-Field based on a fixed-output hash function, +/// like SHA2, SHA3 or Blake2. +/// The implementation aims to follow the specification in [Hashing to Elliptic Curves (draft)](https://tools.ietf.org/pdf/draft-irtf-cfrg-hash-to-curve-13.pdf). +/// +/// # Examples +/// +/// ``` +/// use ark_test_curves::bls12_381::Fq; +/// use ark_ec::hashing::field_hashers::IETFHasher; +/// use sha2::Sha256; +/// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; +/// +/// let hasher = as HashToField>::new_hash_to_field(&[1, 2, 3]).unwrap(); +/// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); +/// +/// assert_eq!(field_elements.len(), 2); +/// ``` +pub struct IETFHasher { + expander: ExpanderXmd, + len_per_base_elem: usize, +} + +impl HashToField + for IETFHasher +{ + fn new_hash_to_field(dst: &[u8]) -> Result { + // The final output of `hash_to_field` will be an array of field + // elements from F::BaseField, each of size `len_per_elem`. + let len_per_base_elem = get_len_per_elem::(); + + let expander = ExpanderXmd { + hasher: H::default(), + dst: dst.to_vec(), + block_size: len_per_base_elem, + }; + + Ok(IETFHasher { + expander, + len_per_base_elem, + }) + } + + fn hash_to_field(&self, message: &[u8], count: usize) -> Result, HashToCurveError> { + let m = F::extension_degree() as usize; + + // The user imposes a `count` of elements of F_p^m to output per input msg, + // each field element comprising `m` BasePrimeField elements. + let len_in_bytes = count * m * self.len_per_base_elem; + let uniform_bytes = self.expander.expand(message, len_in_bytes); + + let mut output: Vec = Vec::with_capacity(count); + for i in 0..count { + let mut base_prime_field_elems: Vec = Vec::new(); + for j in 0..m { + let elm_offset = self.len_per_base_elem * (j + i * m); + let val: F::BasePrimeField = F::BasePrimeField::from_be_bytes_mod_order( + &uniform_bytes[elm_offset..elm_offset + self.len_per_base_elem], + ); + base_prime_field_elems.push(val); + } + let f: F = F::from_base_prime_field_elems(&base_prime_field_elems).unwrap(); + output.push(f); + } + + Ok(output) + } +} diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index 94165812c..a713fc73c 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -1,15 +1,13 @@ +mod ietf_hasher; +pub use ietf_hasher::IETFHasher; +mod expander; use ark_ff::{Field, PrimeField}; -use ark_std::vec::Vec; - -use crate::hashing::{map_to_curve_hasher::*, *}; -use ark_std::string::ToString; -use digest::{Update, VariableOutput}; // This function computes the length in bytes that a hash function should output // for hashing `count` field elements. // See section 5.1 and 5.3 of the // [IETF hash standardization draft](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10) -fn hash_len_in_bytes(count: usize) -> usize { +fn get_len_per_elem() -> usize { // ceil(log(p)) let base_field_size_in_bits = F::BasePrimeField::MODULUS_BIT_SIZE as usize; // ceil(log(p)) + security_parameter @@ -17,90 +15,19 @@ fn hash_len_in_bytes(count: usize) -> usize { // ceil( (ceil(log(p)) + security_parameter) / 8) let bytes_per_base_field_elem = ((base_field_size_with_security_padding_in_bits + 7) / 8) as u64; - let len_in_bytes = F::extension_degree() * (count as u64) * bytes_per_base_field_elem; - len_in_bytes as usize -} - -fn map_bytes_to_field_elem(bz: &[u8]) -> Option { - let d: usize = F::extension_degree() as usize; - let len_per_elem = bz.len() / d; - let mut base_field_elems = Vec::new(); - for i in 0..d { - let val = - F::BasePrimeField::from_be_bytes_mod_order(&bz[(i * len_per_elem)..][..len_per_elem]); - base_field_elems.push(val); - } - F::from_base_prime_field_elems(&base_field_elems) -} - -// This field hasher constructs a Hash to Field from a variable output hash -// function. It handles domains by hashing the input domain into 256 bits, and -// prefixes these bits to every message it computes the hash of. -// The state after prefixing the domain is cached. -pub struct DefaultFieldHasher { - // This hasher should already have the domain applied to it. - domain_seperated_hasher: H, - count: usize, + bytes_per_base_field_elem as usize } -// Implement HashToField from F and a variable output hash -impl HashToField - for DefaultFieldHasher -{ - fn new_hash_to_field(domain: &[u8], count: usize) -> Result { - // Hardcode security parameter - let bytes_per_base_field_elem = hash_len_in_bytes::(count); - // Create hasher and map the error type - let wrapped_hasher = H::new(bytes_per_base_field_elem); - let mut hasher = match wrapped_hasher { - Ok(hasher) => hasher, - Err(err) => return Err(HashToCurveError::DomainError(err.to_string())), - }; - - // DefaultFieldHasher handles domains by hashing them into 256 bits / 32 bytes - // using the same hasher. The hashed domain is then prefixed to all - // messages that get hashed. - let hashed_domain_length_in_bytes = 32; - let mut hashed_domain = [0u8; 32]; - // Create hasher and map the error type - let wrapped_domain_hasher = H::new(hashed_domain_length_in_bytes); - let mut domain_hasher = match wrapped_domain_hasher { - Ok(hasher) => hasher, - Err(err) => return Err(HashToCurveError::DomainError(err.to_string())), - }; - - domain_hasher.update(domain); - match domain_hasher.finalize_variable(&mut hashed_domain) { - Err(err) => return Err(HashToCurveError::DomainError(err.to_string())), - _ => (), - } - - // Prefix the 32 byte hashed domain to our hasher - hasher.update(&hashed_domain); - Ok(DefaultFieldHasher { - domain_seperated_hasher: hasher, - count, - }) - } - - fn hash_to_field(&self, msg: &[u8]) -> Result, HashToCurveError> { - // Clone the hasher, and hash our message - let mut cur_hasher = self.domain_seperated_hasher.clone(); - cur_hasher.update(msg); - let mut hashed_bytes = vec![0u8; cur_hasher.output_size()]; - match cur_hasher.finalize_variable(&mut hashed_bytes) { - Err(err) => return Err(HashToCurveError::DomainError(err.to_string())), - _ => (), - } - // Now separate the hashed bytes according to each field element. - let mut result = Vec::with_capacity(self.count); - let len_per_elem = hashed_bytes.len() / self.count; - for i in 0..self.count { - let bz_per_elem = &hashed_bytes[i * len_per_elem..][..len_per_elem]; - let val = map_bytes_to_field_elem::(bz_per_elem).unwrap(); - result.push(val); - } - - Ok(result) +#[cfg(test)] +mod hasher_tests { + use super::*; + use ark_test_curves::bls12_381::{Fq, Fq2}; + + #[test] + fn test_get_len_per_elem() { + let fq_len = get_len_per_elem::(); + let fq2_len = get_len_per_elem::(); + assert_eq!(fq_len, fq2_len); + assert_eq!(fq_len, 64); } } diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index 30bb135a8..88e52777d 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -20,10 +20,10 @@ pub trait HashToField: Sized { /// /// * `domain` - bytes that get concatenated with the `msg` during hashing, in order to separate potentially interfering instantiations of the hasher. /// * `count` - number of elements in field `F` to output. - fn new_hash_to_field(domain: &[u8], count: usize) -> Result; + fn new_hash_to_field(domain: &[u8]) -> Result; /// Hash an arbitrary `msg` to #`count` elements from field `F`. - fn hash_to_field(&self, msg: &[u8]) -> Result, HashToCurveError>; + fn hash_to_field(&self, msg: &[u8], count: usize) -> Result, HashToCurveError>; } /// Helper struct that can be used to construct elements on the elliptic curve @@ -47,7 +47,7 @@ where M2C: MapToCurve, { fn new(domain: &[u8]) -> Result { - let field_hasher = H2F::new_hash_to_field(domain, 2)?; + let field_hasher = H2F::new_hash_to_field(domain)?; let curve_mapper = M2C::new_map_to_curve()?; let _params_t = PhantomData; Ok(MapToCurveBasedHasher { @@ -71,7 +71,7 @@ where // 5. P = clear_cofactor(R) // 6. return P - let rand_field_elems = self.field_hasher.hash_to_field(msg)?; + let rand_field_elems = self.field_hasher.hash_to_field(msg, 2)?; let rand_curve_elem_0 = self.curve_mapper.map_to_curve(rand_field_elems[0])?; let rand_curve_elem_1 = self.curve_mapper.map_to_curve(rand_field_elems[1])?; diff --git a/ec/src/hashing/tests.rs b/ec/src/hashing/tests.rs index 1b41b42b9..d80b98d3d 100644 --- a/ec/src/hashing/tests.rs +++ b/ec/src/hashing/tests.rs @@ -1,12 +1,12 @@ +use crate::hashing::HashToCurve; use crate::{ hashing::{ curve_maps::{ swu::{parity, SWUMap, SWUParams}, wb::{WBMap, WBParams}, }, - field_hashers::DefaultFieldHasher, + field_hashers::IETFHasher, map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher}, - HashToCurve, }, models::SWModelParameters, short_weierstrass_jacobian::GroupAffine, @@ -120,11 +120,11 @@ fn checking_the_hashing_parameters() { /// simple hash #[test] fn hash_arbitary_string_to_curve_swu() { - use blake2::Blake2bVar; + use sha2::Sha256; let test_swu_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultFieldHasher, + IETFHasher, SWUMap, >::new(&[1]) .unwrap(); @@ -343,11 +343,10 @@ impl WBParams for TestWBF127MapToCurveParams { /// and make simple hash #[test] fn hash_arbitary_string_to_curve_wb() { - use blake2::Blake2bVar; - + use sha2::Sha256; let test_wb_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultFieldHasher, + IETFHasher, WBMap, >::new(&[1]) .unwrap(); From 6b39930444f4332f043b8909e7d15465cf713d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 10 Mar 2022 11:16:51 +0100 Subject: [PATCH 02/56] Add empty test suites --- ec/src/hashing/tests/json.rs | 40 ++++++ ec/src/hashing/{tests.rs => tests/mod.rs} | 0 ec/src/hashing/tests/suites.rs | 57 +++++++++ .../BLS12381G1_XMD-SHA-256_SSWU_RO_.json | 115 ++++++++++++++++++ .../BLS12381G2_XMD-SHA-256_SSWU_RO_.json | 115 ++++++++++++++++++ 5 files changed, 327 insertions(+) create mode 100644 ec/src/hashing/tests/json.rs rename ec/src/hashing/{tests.rs => tests/mod.rs} (100%) create mode 100644 ec/src/hashing/tests/suites.rs create mode 100644 ec/src/hashing/tests/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json create mode 100644 ec/src/hashing/tests/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json diff --git a/ec/src/hashing/tests/json.rs b/ec/src/hashing/tests/json.rs new file mode 100644 index 000000000..cd6e18c6c --- /dev/null +++ b/ec/src/hashing/tests/json.rs @@ -0,0 +1,40 @@ +#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SuiteVector { + pub ciphersuite: String, + pub curve: String, + pub dst: String, + pub field: Field, + pub hash: String, + pub map: Map, + pub random_oracle: bool, + pub vectors: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Field { + pub m: String, + pub p: String, +} + +#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Map { + pub name: String, +} + +#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Vector { + #[serde(rename = "P")] + pub p: P, + pub msg: String, +} + +#[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct P { + pub x: String, + pub y: String, +} diff --git a/ec/src/hashing/tests.rs b/ec/src/hashing/tests/mod.rs similarity index 100% rename from ec/src/hashing/tests.rs rename to ec/src/hashing/tests/mod.rs diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs new file mode 100644 index 000000000..c42fcd9e4 --- /dev/null +++ b/ec/src/hashing/tests/suites.rs @@ -0,0 +1,57 @@ +use std::fs::{read_dir, File}; +use std::io::BufReader; + +use super::json::SuiteVector; +use libtest_mimic::{run_tests, Arguments, Outcome, Test}; + +#[test] +fn suites() { + let args = Arguments::from_args(); + let mut tests_weierstrass = Vec::>::new(); + + for filename in read_dir("./src/hashing/tests/testdata").unwrap() { + let file = File::open(filename.unwrap().path()).unwrap(); + let u: SuiteVector = serde_json::from_reader(BufReader::new(file)).unwrap(); + let test = Test { + name: u.ciphersuite.clone(), + data: u, + kind: String::default(), + is_ignored: false, + is_bench: false, + }; + tests_weierstrass.push(test); + } + run_tests(&args, tests_weierstrass, run_test_w).exit_if_failed(); + + fn run_test_w(Test { data, .. }: &Test) -> Outcome { + tt(data) + } + + fn tt(u: &SuiteVector) -> Outcome { + match u.curve.as_str() { + "BLS12-381 G1" => { + assert_eq!(u.hash, "sha256"); + // let h2c = suite.get(u.dst.as_bytes()); + // let curve = h2c.get_curve(); + // let f = curve.get_field(); + for v in u.vectors.iter() { + // let got = h2c.hash(v.msg.as_bytes()); + // let x = f.from(&v.p.x); + // let y = f.from(&v.p.y); + // let want = curve.new_point(x, y); + // if got != want { + // return Outcome::Failed { + // msg: Some(format!( + // "Suite: {}\ngot: {}\nwant: {}", + // u.ciphersuite, got, want + // )), + // }; + // } + } + Outcome::Passed + }, + "BLS12-381 G2" => Outcome::Ignored, + _ => Outcome::Ignored, + } + } +} diff --git a/ec/src/hashing/tests/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json b/ec/src/hashing/tests/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json new file mode 100644 index 000000000..46c7574f0 --- /dev/null +++ b/ec/src/hashing/tests/testdata/BLS12381G1_XMD-SHA-256_SSWU_RO_.json @@ -0,0 +1,115 @@ +{ + "L": "0x40", + "Z": "0xb", + "ciphersuite": "BLS12381G1_XMD:SHA-256_SSWU_RO_", + "curve": "BLS12-381 G1", + "dst": "QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_", + "expand": "XMD", + "field": { + "m": "0x1", + "p": "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab" + }, + "hash": "sha256", + "k": "0x80", + "map": { + "name": "SSWU" + }, + "randomOracle": true, + "vectors": [ + { + "P": { + "x": "0x052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1", + "y": "0x08ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265" + }, + "Q0": { + "x": "0x11a3cce7e1d90975990066b2f2643b9540fa40d6137780df4e753a8054d07580db3b7f1f03396333d4a359d1fe3766fe", + "y": "0x0eeaf6d794e479e270da10fdaf768db4c96b650a74518fc67b04b03927754bac66f3ac720404f339ecdcc028afa091b7" + }, + "Q1": { + "x": "0x160003aaf1632b13396dbad518effa00fff532f604de1a7fc2082ff4cb0afa2d63b2c32da1bef2bf6c5ca62dc6b72f9c", + "y": "0x0d8bb2d14e20cf9f6036152ed386d79189415b6d015a20133acb4e019139b94e9c146aaad5817f866c95d609a361735e" + }, + "msg": "", + "u": [ + "0x0ba14bd907ad64a016293ee7c2d276b8eae71f25a4b941eece7b0d89f17f75cb3ae5438a614fb61d6835ad59f29c564f", + "0x019b9bd7979f12657976de2884c7cce192b82c177c80e0ec604436a7f538d231552f0d96d9f7babe5fa3b19b3ff25ac9" + ] + }, + { + "P": { + "x": "0x03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903", + "y": "0x0b9c15f3fe6e5cf4211f346271d7b01c8f3b28be689c8429c85b67af215533311f0b8dfaaa154fa6b88176c229f2885d" + }, + "Q0": { + "x": "0x125435adce8e1cbd1c803e7123f45392dc6e326d292499c2c45c5865985fd74fe8f042ecdeeec5ecac80680d04317d80", + "y": "0x0e8828948c989126595ee30e4f7c931cbd6f4570735624fd25aef2fa41d3f79cfb4b4ee7b7e55a8ce013af2a5ba20bf2" + }, + "Q1": { + "x": "0x11def93719829ecda3b46aa8c31fc3ac9c34b428982b898369608e4f042babee6c77ab9218aad5c87ba785481eff8ae4", + "y": "0x0007c9cef122ccf2efd233d6eb9bfc680aa276652b0661f4f820a653cec1db7ff69899f8e52b8e92b025a12c822a6ce6" + }, + "msg": "abc", + "u": [ + "0x0d921c33f2bad966478a03ca35d05719bdf92d347557ea166e5bba579eea9b83e9afa5c088573c2281410369fbd32951", + "0x003574a00b109ada2f26a37a91f9d1e740dffd8d69ec0c35e1e9f4652c7dba61123e9dd2e76c655d956e2b3462611139" + ] + }, + { + "P": { + "x": "0x11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98", + "y": "0x03a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709" + }, + "Q0": { + "x": "0x08834484878c217682f6d09a4b51444802fdba3d7f2df9903a0ddadb92130ebbfa807fffa0eabf257d7b48272410afff", + "y": "0x0b318f7ecf77f45a0f038e62d7098221d2dbbca2a394164e2e3fe953dc714ac2cde412d8f2d7f0c03b259e6795a2508e" + }, + "Q1": { + "x": "0x158418ed6b27e2549f05531a8281b5822b31c3bf3144277fbb977f8d6e2694fedceb7011b3c2b192f23e2a44b2bd106e", + "y": "0x1879074f344471fac5f839e2b4920789643c075792bec5af4282c73f7941cda5aa77b00085eb10e206171b9787c4169f" + }, + "msg": "abcdef0123456789", + "u": [ + "0x062d1865eb80ebfa73dcfc45db1ad4266b9f3a93219976a3790ab8d52d3e5f1e62f3b01795e36834b17b70e7b76246d4", + "0x0cdc3e2f271f29c4ff75020857ce6c5d36008c9b48385ea2f2bf6f96f428a3deb798aa033cd482d1cdc8b30178b08e3a" + ] + }, + { + "P": { + "x": "0x15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488", + "y": "0x1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38" + }, + "Q0": { + "x": "0x0cbd7f84ad2c99643fea7a7ac8f52d63d66cefa06d9a56148e58b984b3dd25e1f41ff47154543343949c64f88d48a710", + "y": "0x052c00e4ed52d000d94881a5638ae9274d3efc8bc77bc0e5c650de04a000b2c334a9e80b85282a00f3148dfdface0865" + }, + "Q1": { + "x": "0x06493fb68f0d513af08be0372f849436a787e7b701ae31cb964d968021d6ba6bd7d26a38aaa5a68e8c21a6b17dc8b579", + "y": "0x02e98f2ccf5802b05ffaac7c20018bc0c0b2fd580216c4aa2275d2909dc0c92d0d0bdc979226adeb57a29933536b6bb4" + }, + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "u": [ + "0x010476f6a060453c0b1ad0b628f3e57c23039ee16eea5e71bb87c3b5419b1255dc0e5883322e563b84a29543823c0e86", + "0x0b1a912064fb0554b180e07af7e787f1f883a0470759c03c1b6509eb8ce980d1670305ae7b928226bb58fdc0a419f46e" + ] + }, + { + "P": { + "x": "0x082aabae8b7dedb0e78aeb619ad3bfd9277a2f77ba7fad20ef6aabdc6c31d19ba5a6d12283553294c1825c4b3ca2dcfe", + "y": "0x05b84ae5a942248eea39e1d91030458c40153f3b654ab7872d779ad1e942856a20c438e8d99bc8abfbf74729ce1f7ac8" + }, + "Q0": { + "x": "0x0cf97e6dbd0947857f3e578231d07b309c622ade08f2c08b32ff372bd90db19467b2563cc997d4407968d4ac80e154f8", + "y": "0x127f0cddf2613058101a5701f4cb9d0861fd6c2a1b8e0afe194fccf586a3201a53874a2761a9ab6d7220c68661a35ab3" + }, + "Q1": { + "x": "0x092f1acfa62b05f95884c6791fba989bbe58044ee6355d100973bf9553ade52b47929264e6ae770fb264582d8dce512a", + "y": "0x028e6d0169a72cfedb737be45db6c401d3adfb12c58c619c82b93a5dfcccef12290de530b0480575ddc8397cda0bbebf" + }, + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "u": [ + "0x0a8ffa7447f6be1c5a2ea4b959c9454b431e29ccc0802bc052413a9c5b4f9aac67a93431bd480d15be1e057c8a08e8c6", + "0x05d487032f602c90fa7625dbafe0f4a49ef4a6b0b33d7bb349ff4cf5410d297fd6241876e3e77b651cfc8191e40a68b7" + ] + } + ] +} diff --git a/ec/src/hashing/tests/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json b/ec/src/hashing/tests/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json new file mode 100644 index 000000000..5807ee6f6 --- /dev/null +++ b/ec/src/hashing/tests/testdata/BLS12381G2_XMD-SHA-256_SSWU_RO_.json @@ -0,0 +1,115 @@ +{ + "L": "0x40", + "Z": "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaa9,0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa", + "ciphersuite": "BLS12381G2_XMD:SHA-256_SSWU_RO_", + "curve": "BLS12-381 G2", + "dst": "QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_", + "expand": "XMD", + "field": { + "m": "0x2", + "p": "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab" + }, + "hash": "sha256", + "k": "0x80", + "map": { + "name": "SSWU" + }, + "randomOracle": true, + "vectors": [ + { + "P": { + "x": "0x0141ebfbdca40eb85b87142e130ab689c673cf60f1a3e98d69335266f30d9b8d4ac44c1038e9dcdd5393faf5c41fb78a,0x05cb8437535e20ecffaef7752baddf98034139c38452458baeefab379ba13dff5bf5dd71b72418717047f5b0f37da03d", + "y": "0x0503921d7f6a12805e72940b963c0cf3471c7b2a524950ca195d11062ee75ec076daf2d4bc358c4b190c0c98064fdd92,0x12424ac32561493f3fe3c260708a12b7c620e7be00099a974e259ddc7d1f6395c3c811cdd19f1e8dbf3e9ecfdcbab8d6" + }, + "Q0": { + "x": "0x019ad3fc9c72425a998d7ab1ea0e646a1f6093444fc6965f1cad5a3195a7b1e099c050d57f45e3fa191cc6d75ed7458c,0x171c88b0b0efb5eb2b88913a9e74fe111a4f68867b59db252ce5868af4d1254bfab77ebde5d61cd1a86fb2fe4a5a1c1d", + "y": "0x0ba10604e62bdd9eeeb4156652066167b72c8d743b050fb4c1016c31b505129374f76e03fa127d6a156213576910fef3,0x0eb22c7a543d3d376e9716a49b72e79a89c9bfe9feee8533ed931cbb5373dde1fbcd7411d8052e02693654f71e15410a" + }, + "Q1": { + "x": "0x113d2b9cd4bd98aee53470b27abc658d91b47a78a51584f3d4b950677cfb8a3e99c24222c406128c91296ef6b45608be,0x13855912321c5cb793e9d1e88f6f8d342d49c0b0dbac613ee9e17e3c0b3c97dfbb5a49cc3fb45102fdbaf65e0efe2632", + "y": "0x0fd3def0b7574a1d801be44fde617162aa2e89da47f464317d9bb5abc3a7071763ce74180883ad7ad9a723a9afafcdca,0x056f617902b3c0d0f78a9a8cbda43a26b65f602f8786540b9469b060db7b38417915b413ca65f875c130bebfaa59790c" + }, + "msg": "", + "u": [ + "0x03dbc2cce174e91ba93cbb08f26b917f98194a2ea08d1cce75b2b9cc9f21689d80bd79b594a613d0a68eb807dfdc1cf8,0x05a2acec64114845711a54199ea339abd125ba38253b70a92c876df10598bd1986b739cad67961eb94f7076511b3b39a", + "0x02f99798e8a5acdeed60d7e18e9120521ba1f47ec090984662846bc825de191b5b7641148c0dbc237726a334473eee94,0x145a81e418d4010cc027a68f14391b30074e89e60ee7a22f87217b2f6eb0c4b94c9115b436e6fa4607e95a98de30a435" + ] + }, + { + "P": { + "x": "0x02c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6,0x139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd8", + "y": "0x1787327b68159716a37440985269cf584bcb1e621d3a7202be6ea05c4cfe244aeb197642555a0645fb87bf7466b2ba48,0x00aa65dae3c8d732d10ecd2c50f8a1baf3001578f71c694e03866e9f3d49ac1e1ce70dd94a733534f106d4cec0eddd16" + }, + "Q0": { + "x": "0x12b2e525281b5f4d2276954e84ac4f42cf4e13b6ac4228624e17760faf94ce5706d53f0ca1952f1c5ef75239aeed55ad,0x05d8a724db78e570e34100c0bc4a5fa84ad5839359b40398151f37cff5a51de945c563463c9efbdda569850ee5a53e77", + "y": "0x02eacdc556d0bdb5d18d22f23dcb086dd106cad713777c7e6407943edbe0b3d1efe391eedf11e977fac55f9b94f2489c,0x04bbe48bfd5814648d0b9e30f0717b34015d45a861425fabc1ee06fdfce36384ae2c808185e693ae97dcde118f34de41" + }, + "Q1": { + "x": "0x19f18cc5ec0c2f055e47c802acc3b0e40c337256a208001dde14b25afced146f37ea3d3ce16834c78175b3ed61f3c537,0x15b0dadc256a258b4c68ea43605dffa6d312eef215c19e6474b3e101d33b661dfee43b51abbf96fee68fc6043ac56a58", + "y": "0x05e47c1781286e61c7ade887512bd9c2cb9f640d3be9cf87ea0bad24bd0ebfe946497b48a581ab6c7d4ca74b5147287f,0x19f98db2f4a1fcdf56a9ced7b320ea9deecf57c8e59236b0dc21f6ee7229aa9705ce9ac7fe7a31c72edca0d92370c096" + }, + "msg": "abc", + "u": [ + "0x15f7c0aa8f6b296ab5ff9c2c7581ade64f4ee6f1bf18f55179ff44a2cf355fa53dd2a2158c5ecb17d7c52f63e7195771,0x01c8067bf4c0ba709aa8b9abc3d1cef589a4758e09ef53732d670fd8739a7274e111ba2fcaa71b3d33df2a3a0c8529dd", + "0x187111d5e088b6b9acfdfad078c4dacf72dcd17ca17c82be35e79f8c372a693f60a033b461d81b025864a0ad051a06e4,0x08b852331c96ed983e497ebc6dee9b75e373d923b729194af8e72a051ea586f3538a6ebb1e80881a082fa2b24df9f566" + ] + }, + { + "P": { + "x": "0x121982811d2491fde9ba7ed31ef9ca474f0e1501297f68c298e9f4c0028add35aea8bb83d53c08cfc007c1e005723cd0,0x190d119345b94fbd15497bcba94ecf7db2cbfd1e1fe7da034d26cbba169fb3968288b3fafb265f9ebd380512a71c3f2c", + "y": "0x05571a0f8d3c08d094576981f4a3b8eda0a8e771fcdcc8ecceaf1356a6acf17574518acb506e435b639353c2e14827c8,0x0bb5e7572275c567462d91807de765611490205a941a5a6af3b1691bfe596c31225d3aabdf15faff860cb4ef17c7c3be" + }, + "Q0": { + "x": "0x0f48f1ea1318ddb713697708f7327781fb39718971d72a9245b9731faaca4dbaa7cca433d6c434a820c28b18e20ea208,0x06051467c8f85da5ba2540974758f7a1e0239a5981de441fdd87680a995649c211054869c50edbac1f3a86c561ba3162", + "y": "0x168b3d6df80069dbbedb714d41b32961ad064c227355e1ce5fac8e105de5e49d77f0c64867f3834848f152497eb76333,0x134e0e8331cee8cb12f9c2d0742714ed9eee78a84d634c9a95f6a7391b37125ed48bfc6e90bf3546e99930ff67cc97bc" + }, + "Q1": { + "x": "0x004fd03968cd1c99a0dd84551f44c206c84dcbdb78076c5bfee24e89a92c8508b52b88b68a92258403cbe1ea2da3495f,0x1674338ea298281b636b2eb0fe593008d03171195fd6dcd4531e8a1ed1f02a72da238a17a635de307d7d24aa2d969a47", + "y": "0x0dc7fa13fff6b12558419e0a1e94bfc3cfaf67238009991c5f24ee94b632c3d09e27eca329989aee348a67b50d5e236c,0x169585e164c131103d85324f2d7747b23b91d66ae5d947c449c8194a347969fc6bbd967729768da485ba71868df8aed2" + }, + "msg": "abcdef0123456789", + "u": [ + "0x0313d9325081b415bfd4e5364efaef392ecf69b087496973b229303e1816d2080971470f7da112c4eb43053130b785e1,0x062f84cb21ed89406890c051a0e8b9cf6c575cf6e8e18ecf63ba86826b0ae02548d83b483b79e48512b82a6c0686df8f", + "0x1739123845406baa7be5c5dc74492051b6d42504de008c635f3535bb831d478a341420e67dcc7b46b2e8cba5379cca97,0x01897665d9cb5db16a27657760bbea7951f67ad68f8d55f7113f24ba6ddd82caef240a9bfa627972279974894701d975" + ] + }, + { + "P": { + "x": "0x19a84dd7248a1066f737cc34502ee5555bd3c19f2ecdb3c7d9e24dc65d4e25e50d83f0f77105e955d78f4762d33c17da,0x0934aba516a52d8ae479939a91998299c76d39cc0c035cd18813bec433f587e2d7a4fef038260eef0cef4d02aae3eb91", + "y": "0x14f81cd421617428bc3b9fe25afbb751d934a00493524bc4e065635b0555084dd54679df1536101b2c979c0152d09192,0x09bcccfa036b4847c9950780733633f13619994394c23ff0b32fa6b795844f4a0673e20282d07bc69641cee04f5e5662" + }, + "Q0": { + "x": "0x09eccbc53df677f0e5814e3f86e41e146422834854a224bf5a83a50e4cc0a77bfc56718e8166ad180f53526ea9194b57,0x0c3633943f91daee715277bd644fba585168a72f96ded64fc5a384cce4ec884a4c3c30f08e09cd2129335dc8f67840ec", + "y": "0x0eb6186a0457d5b12d132902d4468bfeb7315d83320b6c32f1c875f344efcba979952b4aa418589cb01af712f98cc555,0x119e3cf167e69eb16c1c7830e8df88856d48be12e3ff0a40791a5cd2f7221311d4bf13b1847f371f467357b3f3c0b4c7" + }, + "Q1": { + "x": "0x0eb3aabc1ddfce17ff18455fcc7167d15ce6b60ddc9eb9b59f8d40ab49420d35558686293d046fc1e42f864b7f60e381,0x198bdfb19d7441ebcca61e8ff774b29d17da16547d2c10c273227a635cacea3f16826322ae85717630f0867539b5ed8b", + "y": "0x0aaf1dee3adf3ed4c80e481c09b57ea4c705e1b8d25b897f0ceeec3990748716575f92abff22a1c8f4582aff7b872d52,0x0d058d9061ed27d4259848a06c96c5ca68921a5d269b078650c882cb3c2bd424a8702b7a6ee4e0ead9982baf6843e924" + }, + "msg": "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + "u": [ + "0x025820cefc7d06fd38de7d8e370e0da8a52498be9b53cba9927b2ef5c6de1e12e12f188bbc7bc923864883c57e49e253,0x034147b77ce337a52e5948f66db0bab47a8d038e712123bb381899b6ab5ad20f02805601e6104c29df18c254b8618c7b", + "0x0930315cae1f9a6017c3f0c8f2314baa130e1cf13f6532bff0a8a1790cd70af918088c3db94bda214e896e1543629795,0x10c4df2cacf67ea3cb3108b00d4cbd0b3968031ebc8eac4b1ebcefe84d6b715fde66bef0219951ece29d1facc8a520ef" + ] + }, + { + "P": { + "x": "0x01a6ba2f9a11fa5598b2d8ace0fbe0a0eacb65deceb476fbbcb64fd24557c2f4b18ecfc5663e54ae16a84f5ab7f62534,0x11fca2ff525572795a801eed17eb12785887c7b63fb77a42be46ce4a34131d71f7a73e95fee3f812aea3de78b4d01569", + "y": "0x0b6798718c8aed24bc19cb27f866f1c9effcdbf92397ad6448b5c9db90d2b9da6cbabf48adc1adf59a1a28344e79d57e,0x03a47f8e6d1763ba0cad63d6114c0accbef65707825a511b251a660a9b3994249ae4e63fac38b23da0c398689ee2ab52" + }, + "Q0": { + "x": "0x17cadf8d04a1a170f8347d42856526a24cc466cb2ddfd506cff01191666b7f944e31244d662c904de5440516a2b09004,0x0d13ba91f2a8b0051cf3279ea0ee63a9f19bc9cb8bfcc7d78b3cbd8cc4fc43ba726774b28038213acf2b0095391c523e", + "y": "0x17ef19497d6d9246fa94d35575c0f8d06ee02f21a284dbeaa78768cb1e25abd564e3381de87bda26acd04f41181610c5,0x12c3c913ba4ed03c24f0721a81a6be7430f2971ffca8fd1729aafe496bb725807531b44b34b59b3ae5495e5a2dcbd5c8" + }, + "Q1": { + "x": "0x16ec57b7fe04c71dfe34fb5ad84dbce5a2dbbd6ee085f1d8cd17f45e8868976fc3c51ad9eeda682c7869024d24579bfd,0x13103f7aace1ae1420d208a537f7d3a9679c287208026e4e3439ab8cd534c12856284d95e27f5e1f33eec2ce656533b0", + "y": "0x0958b2c4c2c10fcef5a6c59b9e92c4a67b0fae3e2e0f1b6b5edad9c940b8f3524ba9ebbc3f2ceb3cfe377655b3163bd7,0x0ccb594ed8bd14ca64ed9cb4e0aba221be540f25dd0d6ba15a4a4be5d67bcf35df7853b2d8dad3ba245f1ea3697f66aa" + }, + "msg": "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "u": [ + "0x190b513da3e66fc9a3587b78c76d1d132b1152174d0b83e3c1114066392579a45824c5fa17649ab89299ddd4bda54935,0x12ab625b0fe0ebd1367fe9fac57bb1168891846039b4216b9d94007b674de2d79126870e88aeef54b2ec717a887dcf39", + "0x0e6a42010cf435fb5bacc156a585e1ea3294cc81d0ceb81924d95040298380b164f702275892cedd81b62de3aba3f6b5,0x117d9a0defc57a33ed208428cb84e54c85a6840e7648480ae428838989d25d97a0af8e3255be62b25c2a85630d2dddd8" + ] + } + ] +} From 72b67a6af9a1b0ba0fa3301408797737af568848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 10 Mar 2022 11:17:07 +0100 Subject: [PATCH 03/56] Include the suites in testing --- ec/src/hashing/tests/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index d80b98d3d..1fb31ef85 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -19,6 +19,11 @@ use ark_std::vec::Vec; use ark_test_curves::bls12_381::{Fq, Fq2, Fq6}; use hashbrown::HashMap; +#[cfg(all(test, feature = "std"))] +mod json; +#[cfg(all(test, feature = "std"))] +mod suites; + pub struct F127Config; pub type F127 = Fp64>; From 5f1ece7b74cbe763292d6186115404ce7200924e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 10 Mar 2022 16:13:34 +0100 Subject: [PATCH 04/56] Complete the hash-to-field suites Hashing to correct field in either G1 or G2. Tests don't pass yet --- ec/src/hashing/tests/json.rs | 1 + ec/src/hashing/tests/suites.rs | 55 +++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/ec/src/hashing/tests/json.rs b/ec/src/hashing/tests/json.rs index cd6e18c6c..8f2694db1 100644 --- a/ec/src/hashing/tests/json.rs +++ b/ec/src/hashing/tests/json.rs @@ -30,6 +30,7 @@ pub struct Vector { #[serde(rename = "P")] pub p: P, pub msg: String, + pub u: Vec, } #[derive(Default, Debug, Clone, PartialEq, serde_derive::Serialize, serde_derive::Deserialize)] diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index c42fcd9e4..1b0d635b0 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -4,6 +4,13 @@ use std::io::BufReader; use super::json::SuiteVector; use libtest_mimic::{run_tests, Arguments, Outcome, Test}; +use crate::hashing::map_to_curve_hasher::HashToField; +use crate::hashing::tests::IETFHasher; +use ark_ff::PrimeField; +use ark_test_curves::bls12_381::Fq; +use ark_test_curves::bls12_381::Fq2; +use sha2::Sha256; + #[test] fn suites() { let args = Arguments::from_args(); @@ -28,30 +35,36 @@ fn suites() { } fn tt(u: &SuiteVector) -> Outcome { + assert_eq!(u.hash, "sha256"); + let dst = u.dst.as_bytes(); + let hasher; match u.curve.as_str() { + "BLS12-381 G2" => { + hasher = + as HashToField>::new_hash_to_field(dst).unwrap(); + }, "BLS12-381 G1" => { - assert_eq!(u.hash, "sha256"); - // let h2c = suite.get(u.dst.as_bytes()); - // let curve = h2c.get_curve(); - // let f = curve.get_field(); - for v in u.vectors.iter() { - // let got = h2c.hash(v.msg.as_bytes()); - // let x = f.from(&v.p.x); - // let y = f.from(&v.p.y); - // let want = curve.new_point(x, y); - // if got != want { - // return Outcome::Failed { - // msg: Some(format!( - // "Suite: {}\ngot: {}\nwant: {}", - // u.ciphersuite, got, want - // )), - // }; - // } - } - Outcome::Passed + hasher = + as HashToField>::new_hash_to_field(dst).unwrap(); }, - "BLS12-381 G2" => Outcome::Ignored, - _ => Outcome::Ignored, + _ => return Outcome::Ignored, + } + + for v in u.vectors.iter() { + let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2).unwrap(); + let want: Vec = (&v.u) + .into_iter() + .map(|x| Fq::from_be_bytes_mod_order(x.as_bytes())) + .collect(); + if got != want { + return Outcome::Failed { + msg: Some(format!( + "Suite: {:?}\ngot: {:?}\nwant: {:?}", + u.ciphersuite, got, want + )), + }; + } } + Outcome::Passed } } From 25a435d416ae98e98ffe8463c5632b4a38be419a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 10 Mar 2022 16:57:59 +0100 Subject: [PATCH 05/56] swap g1 > g2 --- ec/src/hashing/tests/suites.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 1b0d635b0..2246792e0 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -39,11 +39,11 @@ fn suites() { let dst = u.dst.as_bytes(); let hasher; match u.curve.as_str() { - "BLS12-381 G2" => { + "BLS12-381 G1" => { hasher = as HashToField>::new_hash_to_field(dst).unwrap(); }, - "BLS12-381 G1" => { + "BLS12-381 G2" => { hasher = as HashToField>::new_hash_to_field(dst).unwrap(); }, From 21d1f9d5c2d95607474da014053fae7dfba02737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 10 Mar 2022 17:08:10 +0100 Subject: [PATCH 06/56] Rename IETFHasher back to DefaultHasher --- ec/src/hashing/field_hashers/ietf_hasher.rs | 76 -------------------- ec/src/hashing/field_hashers/mod.rs | 77 ++++++++++++++++++++- ec/src/hashing/tests/mod.rs | 6 +- ec/src/hashing/tests/suites.rs | 10 +-- 4 files changed, 83 insertions(+), 86 deletions(-) delete mode 100644 ec/src/hashing/field_hashers/ietf_hasher.rs diff --git a/ec/src/hashing/field_hashers/ietf_hasher.rs b/ec/src/hashing/field_hashers/ietf_hasher.rs deleted file mode 100644 index bd6009f8f..000000000 --- a/ec/src/hashing/field_hashers/ietf_hasher.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::hashing::*; -use crate::hashing::{field_hashers::expander::ExpanderXmd, map_to_curve_hasher::*}; -use ark_ff::{Field, PrimeField}; -use ark_std::vec::Vec; -use digest::DynDigest; - -use super::expander::Expander; -use super::get_len_per_elem; - -/// This field hasher constructs a Hash-To-Field based on a fixed-output hash function, -/// like SHA2, SHA3 or Blake2. -/// The implementation aims to follow the specification in [Hashing to Elliptic Curves (draft)](https://tools.ietf.org/pdf/draft-irtf-cfrg-hash-to-curve-13.pdf). -/// -/// # Examples -/// -/// ``` -/// use ark_test_curves::bls12_381::Fq; -/// use ark_ec::hashing::field_hashers::IETFHasher; -/// use sha2::Sha256; -/// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; -/// -/// let hasher = as HashToField>::new_hash_to_field(&[1, 2, 3]).unwrap(); -/// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); -/// -/// assert_eq!(field_elements.len(), 2); -/// ``` -pub struct IETFHasher { - expander: ExpanderXmd, - len_per_base_elem: usize, -} - -impl HashToField - for IETFHasher -{ - fn new_hash_to_field(dst: &[u8]) -> Result { - // The final output of `hash_to_field` will be an array of field - // elements from F::BaseField, each of size `len_per_elem`. - let len_per_base_elem = get_len_per_elem::(); - - let expander = ExpanderXmd { - hasher: H::default(), - dst: dst.to_vec(), - block_size: len_per_base_elem, - }; - - Ok(IETFHasher { - expander, - len_per_base_elem, - }) - } - - fn hash_to_field(&self, message: &[u8], count: usize) -> Result, HashToCurveError> { - let m = F::extension_degree() as usize; - - // The user imposes a `count` of elements of F_p^m to output per input msg, - // each field element comprising `m` BasePrimeField elements. - let len_in_bytes = count * m * self.len_per_base_elem; - let uniform_bytes = self.expander.expand(message, len_in_bytes); - - let mut output: Vec = Vec::with_capacity(count); - for i in 0..count { - let mut base_prime_field_elems: Vec = Vec::new(); - for j in 0..m { - let elm_offset = self.len_per_base_elem * (j + i * m); - let val: F::BasePrimeField = F::BasePrimeField::from_be_bytes_mod_order( - &uniform_bytes[elm_offset..elm_offset + self.len_per_base_elem], - ); - base_prime_field_elems.push(val); - } - let f: F = F::from_base_prime_field_elems(&base_prime_field_elems).unwrap(); - output.push(f); - } - - Ok(output) - } -} diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index a713fc73c..f8266b10a 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -1,8 +1,81 @@ -mod ietf_hasher; -pub use ietf_hasher::IETFHasher; mod expander; use ark_ff::{Field, PrimeField}; +use crate::hashing::{ + field_hashers::expander::ExpanderXmd, map_to_curve_hasher::*, HashToCurveError, +}; +use ark_std::vec::Vec; +use digest::DynDigest; +use expander::Expander; + +/// This field hasher constructs a Hash-To-Field based on a fixed-output hash function, +/// like SHA2, SHA3 or Blake2. +/// The implementation aims to follow the specification in [Hashing to Elliptic Curves (draft)](https://tools.ietf.org/pdf/draft-irtf-cfrg-hash-to-curve-13.pdf). +/// +/// # Examples +/// +/// ``` +/// use ark_test_curves::bls12_381::Fq; +/// use ark_ec::hashing::field_hashers::DefaultHasher; +/// use sha2::Sha256; +/// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; +/// +/// let hasher = as HashToField>::new_hash_to_field(&[1, 2, 3]).unwrap(); +/// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); +/// +/// assert_eq!(field_elements.len(), 2); +/// ``` +pub struct DefaultHasher { + expander: ExpanderXmd, + len_per_base_elem: usize, +} + +impl HashToField + for DefaultHasher +{ + fn new_hash_to_field(dst: &[u8]) -> Result { + // The final output of `hash_to_field` will be an array of field + // elements from F::BaseField, each of size `len_per_elem`. + let len_per_base_elem = get_len_per_elem::(); + + let expander = ExpanderXmd { + hasher: H::default(), + dst: dst.to_vec(), + block_size: len_per_base_elem, + }; + + Ok(DefaultHasher { + expander, + len_per_base_elem, + }) + } + + fn hash_to_field(&self, message: &[u8], count: usize) -> Result, HashToCurveError> { + let m = F::extension_degree() as usize; + + // The user imposes a `count` of elements of F_p^m to output per input msg, + // each field element comprising `m` BasePrimeField elements. + let len_in_bytes = count * m * self.len_per_base_elem; + let uniform_bytes = self.expander.expand(message, len_in_bytes); + + let mut output: Vec = Vec::with_capacity(count); + for i in 0..count { + let mut base_prime_field_elems: Vec = Vec::new(); + for j in 0..m { + let elm_offset = self.len_per_base_elem * (j + i * m); + let val: F::BasePrimeField = F::BasePrimeField::from_be_bytes_mod_order( + &uniform_bytes[elm_offset..elm_offset + self.len_per_base_elem], + ); + base_prime_field_elems.push(val); + } + let f: F = F::from_base_prime_field_elems(&base_prime_field_elems).unwrap(); + output.push(f); + } + + Ok(output) + } +} + // This function computes the length in bytes that a hash function should output // for hashing `count` field elements. // See section 5.1 and 5.3 of the diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 1fb31ef85..32f96e310 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -5,7 +5,7 @@ use crate::{ swu::{parity, SWUMap, SWUParams}, wb::{WBMap, WBParams}, }, - field_hashers::IETFHasher, + field_hashers::DefaultHasher, map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher}, }, models::SWModelParameters, @@ -129,7 +129,7 @@ fn hash_arbitary_string_to_curve_swu() { let test_swu_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - IETFHasher, + DefaultHasher, SWUMap, >::new(&[1]) .unwrap(); @@ -351,7 +351,7 @@ fn hash_arbitary_string_to_curve_wb() { use sha2::Sha256; let test_wb_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - IETFHasher, + DefaultHasher, WBMap, >::new(&[1]) .unwrap(); diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 2246792e0..4532860ff 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -5,7 +5,7 @@ use super::json::SuiteVector; use libtest_mimic::{run_tests, Arguments, Outcome, Test}; use crate::hashing::map_to_curve_hasher::HashToField; -use crate::hashing::tests::IETFHasher; +use crate::hashing::tests::DefaultHasher; use ark_ff::PrimeField; use ark_test_curves::bls12_381::Fq; use ark_test_curves::bls12_381::Fq2; @@ -40,12 +40,12 @@ fn suites() { let hasher; match u.curve.as_str() { "BLS12-381 G1" => { - hasher = - as HashToField>::new_hash_to_field(dst).unwrap(); + hasher = as HashToField>::new_hash_to_field(dst) + .unwrap(); }, "BLS12-381 G2" => { - hasher = - as HashToField>::new_hash_to_field(dst).unwrap(); + hasher = as HashToField>::new_hash_to_field(dst) + .unwrap(); }, _ => return Outcome::Ignored, } From 59daf69e8603c6efaeb51a49edc9b6c87d174df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 10 Mar 2022 22:15:55 +0100 Subject: [PATCH 07/56] Rename DefaultHasher -> DefaultFieldHasher --- ec/src/hashing/field_hashers/mod.rs | 10 +++++----- ec/src/hashing/tests/mod.rs | 6 +++--- ec/src/hashing/tests/suites.rs | 12 +++++++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index f8266b10a..b46c2cc14 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -16,22 +16,22 @@ use expander::Expander; /// /// ``` /// use ark_test_curves::bls12_381::Fq; -/// use ark_ec::hashing::field_hashers::DefaultHasher; +/// use ark_ec::hashing::field_hashers::DefaultFieldHasher; /// use sha2::Sha256; /// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; /// -/// let hasher = as HashToField>::new_hash_to_field(&[1, 2, 3]).unwrap(); +/// let hasher = as HashToField>::new_hash_to_field(&[1, 2, 3]).unwrap(); /// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); /// /// assert_eq!(field_elements.len(), 2); /// ``` -pub struct DefaultHasher { +pub struct DefaultFieldHasher { expander: ExpanderXmd, len_per_base_elem: usize, } impl HashToField - for DefaultHasher + for DefaultFieldHasher { fn new_hash_to_field(dst: &[u8]) -> Result { // The final output of `hash_to_field` will be an array of field @@ -44,7 +44,7 @@ impl HashToFie block_size: len_per_base_elem, }; - Ok(DefaultHasher { + Ok(DefaultFieldHasher { expander, len_per_base_elem, }) diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 32f96e310..2cc288686 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -5,7 +5,7 @@ use crate::{ swu::{parity, SWUMap, SWUParams}, wb::{WBMap, WBParams}, }, - field_hashers::DefaultHasher, + field_hashers::DefaultFieldHasher, map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher}, }, models::SWModelParameters, @@ -129,7 +129,7 @@ fn hash_arbitary_string_to_curve_swu() { let test_swu_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultHasher, + DefaultFieldHasher, SWUMap, >::new(&[1]) .unwrap(); @@ -351,7 +351,7 @@ fn hash_arbitary_string_to_curve_wb() { use sha2::Sha256; let test_wb_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultHasher, + DefaultFieldHasher, WBMap, >::new(&[1]) .unwrap(); diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 4532860ff..89d0f6d84 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -5,7 +5,7 @@ use super::json::SuiteVector; use libtest_mimic::{run_tests, Arguments, Outcome, Test}; use crate::hashing::map_to_curve_hasher::HashToField; -use crate::hashing::tests::DefaultHasher; +use crate::hashing::tests::DefaultFieldHasher; use ark_ff::PrimeField; use ark_test_curves::bls12_381::Fq; use ark_test_curves::bls12_381::Fq2; @@ -40,12 +40,14 @@ fn suites() { let hasher; match u.curve.as_str() { "BLS12-381 G1" => { - hasher = as HashToField>::new_hash_to_field(dst) - .unwrap(); + hasher = + as HashToField>::new_hash_to_field(dst) + .unwrap(); }, "BLS12-381 G2" => { - hasher = as HashToField>::new_hash_to_field(dst) - .unwrap(); + hasher = + as HashToField>::new_hash_to_field(dst) + .unwrap(); }, _ => return Outcome::Ignored, } From 278766743d85325b2b2b78272bb4972b3a04a331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Fri, 11 Mar 2022 14:08:54 +0100 Subject: [PATCH 08/56] Read the test vectors as hex, not as raw bytes --- ec/src/hashing/field_hashers/mod.rs | 2 +- ec/src/hashing/tests/suites.rs | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index b46c2cc14..e79687fda 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -64,7 +64,7 @@ impl HashToFie for j in 0..m { let elm_offset = self.len_per_base_elem * (j + i * m); let val: F::BasePrimeField = F::BasePrimeField::from_be_bytes_mod_order( - &uniform_bytes[elm_offset..elm_offset + self.len_per_base_elem], + &uniform_bytes[elm_offset..(elm_offset + self.len_per_base_elem)], ); base_prime_field_elems.push(val); } diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 89d0f6d84..70559cf38 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -38,13 +38,16 @@ fn suites() { assert_eq!(u.hash, "sha256"); let dst = u.dst.as_bytes(); let hasher; + let m; match u.curve.as_str() { "BLS12-381 G1" => { + m = 1; hasher = as HashToField>::new_hash_to_field(dst) .unwrap(); }, "BLS12-381 G2" => { + m = 2; hasher = as HashToField>::new_hash_to_field(dst) .unwrap(); @@ -53,16 +56,25 @@ fn suites() { } for v in u.vectors.iter() { - let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2).unwrap(); + let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m).unwrap(); let want: Vec = (&v.u) .into_iter() - .map(|x| Fq::from_be_bytes_mod_order(x.as_bytes())) + .map(|x| { + x.split(",").map(|f| { + Fq::from_be_bytes_mod_order( + &hex::decode(f.trim_start_matches("0x")).unwrap(), + ) + }) + }) + .flatten() .collect(); if got != want { return Outcome::Failed { msg: Some(format!( "Suite: {:?}\ngot: {:?}\nwant: {:?}", - u.ciphersuite, got, want + u.ciphersuite, + got[0].to_string(), + want[0].to_string() )), }; } From a3b5c69f8e50f8b8e2bfbb317401212edf15ab8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 24 Mar 2022 14:57:34 +0100 Subject: [PATCH 09/56] Simplify the structure of tests --- ec/src/hashing/tests/suites.rs | 84 +++++++++++++++------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 70559cf38..33be50f9b 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -29,56 +29,48 @@ fn suites() { tests_weierstrass.push(test); } run_tests(&args, tests_weierstrass, run_test_w).exit_if_failed(); +} - fn run_test_w(Test { data, .. }: &Test) -> Outcome { - tt(data) +fn run_test_w(Test { data, .. }: &Test) -> Outcome { + assert_eq!(data.hash, "sha256"); + let dst = data.dst.as_bytes(); + let hasher; + let m; + match data.curve.as_str() { + "BLS12-381 G1" => { + m = 1; + hasher = as HashToField>::new_hash_to_field(dst) + .unwrap(); + }, + "BLS12-381 G2" => { + m = 2; + hasher = as HashToField>::new_hash_to_field(dst) + .unwrap(); + }, + _ => return Outcome::Ignored, } - fn tt(u: &SuiteVector) -> Outcome { - assert_eq!(u.hash, "sha256"); - let dst = u.dst.as_bytes(); - let hasher; - let m; - match u.curve.as_str() { - "BLS12-381 G1" => { - m = 1; - hasher = - as HashToField>::new_hash_to_field(dst) - .unwrap(); - }, - "BLS12-381 G2" => { - m = 2; - hasher = - as HashToField>::new_hash_to_field(dst) - .unwrap(); - }, - _ => return Outcome::Ignored, - } - - for v in u.vectors.iter() { - let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m).unwrap(); - let want: Vec = (&v.u) - .into_iter() - .map(|x| { - x.split(",").map(|f| { - Fq::from_be_bytes_mod_order( - &hex::decode(f.trim_start_matches("0x")).unwrap(), - ) - }) + for v in data.vectors.iter() { + let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m).unwrap(); + let want: Vec = (&v.u) + .into_iter() + .map(|x| { + x.split(",").map(|f| { + Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap()) }) - .flatten() - .collect(); - if got != want { - return Outcome::Failed { - msg: Some(format!( - "Suite: {:?}\ngot: {:?}\nwant: {:?}", - u.ciphersuite, - got[0].to_string(), - want[0].to_string() - )), - }; - } + }) + .flatten() + .collect(); + if got != want { + return Outcome::Failed { + msg: Some(format!( + "Suite: {:?}\ngot: {:?}\nwant: {:?}", + data.ciphersuite, + got[0].to_string(), + want[0].to_string() + )), + }; } - Outcome::Passed } + Outcome::Passed } From 4cd918f58137314a697dbe600e225273fccdd6f0 Mon Sep 17 00:00:00 2001 From: Marcin Date: Thu, 24 Mar 2022 17:04:57 +0100 Subject: [PATCH 10/56] Update ec/Cargo.toml Co-authored-by: drskalman <35698397+drskalman@users.noreply.github.com> --- ec/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ec/Cargo.toml b/ec/Cargo.toml index fbbb1dd12..384715fc9 100644 --- a/ec/Cargo.toml +++ b/ec/Cargo.toml @@ -27,7 +27,7 @@ lazy_static = { version = "1.4.0", default-features = false, features = ["spin_n [dev-dependencies] hashbrown = { version = "0.11.1" } -ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = [ "bls12_381_curve"] } +ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = ["bls12_381_curve"] } sha3 = "0.10" sha2 = "0.10" libtest-mimic = "0.3.0" From 605b96b2943f92fb741566b05d7ebfc17a7d9385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 24 Mar 2022 17:14:16 +0100 Subject: [PATCH 11/56] Replace lazy_static by an array --- ec/Cargo.toml | 1 - ec/src/hashing/field_hashers/expander/mod.rs | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ec/Cargo.toml b/ec/Cargo.toml index fbbb1dd12..918895994 100644 --- a/ec/Cargo.toml +++ b/ec/Cargo.toml @@ -23,7 +23,6 @@ digest = { version = "0.10", default-features = false } num-traits = { version = "0.2", default-features = false } rayon = { version = "1", optional = true } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } -lazy_static = { version = "1.4.0", default-features = false, features = ["spin_no_std"] } [dev-dependencies] hashbrown = { version = "0.11.1" } diff --git a/ec/src/hashing/field_hashers/expander/mod.rs b/ec/src/hashing/field_hashers/expander/mod.rs index 988e8a62e..94e06dcc0 100644 --- a/ec/src/hashing/field_hashers/expander/mod.rs +++ b/ec/src/hashing/field_hashers/expander/mod.rs @@ -3,19 +3,17 @@ use ark_std::vec::Vec; use digest::{DynDigest, ExtendableOutput, Update}; -use lazy_static::lazy_static; pub trait Expander { fn construct_dst_prime(&self) -> Vec; fn expand(&self, msg: &[u8], length: usize) -> Vec; } const MAX_DST_LENGTH: usize = 255; -lazy_static! { -static ref LONG_DST_PREFIX: Vec = vec![ +const LONG_DST_PREFIX: [u8; 17] = [ //'H', '2', 'C', '-', 'O', 'V', 'E', 'R', 'S', 'I', 'Z', 'E', '-', 'D', 'S', 'T', '-', - 0x48, 0x32, 0x43, 0x2d, 0x4f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x5a, 0x45, 0x2d, 0x44, 0x53, 0x54, 0x2d, + 0x48, 0x32, 0x43, 0x2d, 0x4f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x5a, 0x45, 0x2d, 0x44, 0x53, 0x54, + 0x2d, ]; -} pub(super) struct ExpanderXof { pub(super) xofer: T, From 552ca7462c7ef5596f06ce347121f405720067b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 24 Mar 2022 17:26:03 +0100 Subject: [PATCH 12/56] Clean up a comment --- ec/src/hashing/field_hashers/expander/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ec/src/hashing/field_hashers/expander/mod.rs b/ec/src/hashing/field_hashers/expander/mod.rs index 94e06dcc0..4f927aa82 100644 --- a/ec/src/hashing/field_hashers/expander/mod.rs +++ b/ec/src/hashing/field_hashers/expander/mod.rs @@ -1,5 +1,5 @@ // The below implementation is a rework of https://github.com/armfazh/h2c-rust-ref -// With some optimisations; +// With some optimisations use ark_std::vec::Vec; use digest::{DynDigest, ExtendableOutput, Update}; From babfe6b45df4ec2b383bbc97a87eea2ed1ade3bc Mon Sep 17 00:00:00 2001 From: Skalman Date: Wed, 6 Apr 2022 18:26:39 -0400 Subject: [PATCH 13/56] disables default features in sha2 and sha3 and enabling alloc for digest in hope to resolve the std dependancy --- ec/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ec/Cargo.toml b/ec/Cargo.toml index 598e643a2..8103ad4c3 100644 --- a/ec/Cargo.toml +++ b/ec/Cargo.toml @@ -19,7 +19,7 @@ ark-serialize = { version = "^0.3.0", path = "../serialize", default-features = ark-ff = { version = "^0.3.0", path = "../ff", default-features = false } ark-poly = { version = "^0.3.0", path = "../poly", default-features = false } derivative = { version = "2", features = ["use_core"] } -digest = { version = "0.10", default-features = false } +digest = { version = "0.10", default-features = false , features = ["alloc"] } num-traits = { version = "0.2", default-features = false } rayon = { version = "1", optional = true } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } @@ -28,8 +28,8 @@ hashbrown = "0.11.2" [dev-dependencies] blake2 = { version = "0.10", default-features = false } ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = ["bls12_381_curve"] } -sha3 = "0.10" -sha2 = "0.10" +sha3 = { version = "0.10", default-features = false } +sha2 = { version = "0.10", default-features = false } libtest-mimic = "0.3.0" serde = "1.0.110" serde_json = "1.0.53" From 205625afbe86804786e29d963de9f86aef979d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 4 May 2022 14:13:19 +0200 Subject: [PATCH 14/56] Move WB tests to the curve_maps --- ec/src/hashing/curve_maps/wb/mod.rs | 221 +++++++++++++++++++++++++++ ec/src/hashing/tests/mod.rs | 225 +--------------------------- 2 files changed, 226 insertions(+), 220 deletions(-) diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index ff002a3b8..e8fae7e13 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -93,3 +93,224 @@ impl MapToCurve> for WBMap

{ P::isogeny_map(point_on_isogenious_curve) } } + +#[cfg(test)] +mod test { + use crate::hashing::HashToCurve; + use crate::{ + hashing::{ + curve_maps::{ + swu::SWUParams, + wb::{WBMap, WBParams}, + }, + field_hashers::DefaultFieldHasher, + map_to_curve_hasher::MapToCurveBasedHasher, + }, + models::SWModelParameters, + short_weierstrass_jacobian::GroupAffine, + ModelParameters, + }; + use ark_ff::{fields::Fp64, MontBackend, MontFp}; + + #[derive(ark_ff::MontConfig)] + #[modulus = "127"] + #[generator = "6"] + pub struct F127Config; + pub type F127 = Fp64>; + + const F127_ZERO: F127 = MontFp!(F127, "0"); + const F127_ONE: F127 = MontFp!(F127, "1"); + + /// The struct defining our parameters for the target curve of hashing + struct TestWBF127MapToCurveParams; + + impl ModelParameters for TestWBF127MapToCurveParams { + const COFACTOR: &'static [u64] = &[1]; + + #[rustfmt::skip] + const COFACTOR_INV: F127 = F127_ONE; + + type BaseField = F127; + type ScalarField = F127; + } + + /// E: Elliptic Curve defined by y^2 = x^3 + 3 over Finite + /// Field of size 127 + impl SWModelParameters for TestWBF127MapToCurveParams { + /// COEFF_A = 0 + const COEFF_A: F127 = F127_ZERO; + + /// COEFF_B = 3 + #[rustfmt::skip] + const COEFF_B: F127 = MontFp!(F127, "3"); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (MontFp!(F127, "62"), MontFp!(F127, "70")); + } + + /// Testing WB19 hashing on a small curve + /// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite + /// Field of size 127 + /// Isogenous to E : y^2 = x^3 + 3 + struct TestSWU127MapToIsogenousCurveParams; + + /// First we define the isogenous curve + /// sage: E_isogenous.order() + /// 127 + impl ModelParameters for TestSWU127MapToIsogenousCurveParams { + const COFACTOR: &'static [u64] = &[1]; + + #[rustfmt::skip] + const COFACTOR_INV: F127 = F127_ONE; + + type BaseField = F127; + type ScalarField = F127; + } + + /// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite + /// Field of size 127 + impl SWModelParameters for TestSWU127MapToIsogenousCurveParams { + /// COEFF_A = 109 + const COEFF_A: F127 = MontFp!(F127, "109"); + + /// COEFF_B = 124 + #[rustfmt::skip] + const COEFF_B: F127 = MontFp!(F127, "124"); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (MontFp!(F127, "84"), MontFp!(F127, "2")); + } + + /// SWU parameters for E_isogenous + impl SWUParams for TestSWU127MapToIsogenousCurveParams { + /// NON-SQUARE = - 1 + const XI: F127 = MontFp!(F127, "-1"); + /// A Primitive Root of unity = 3 + const ZETA: F127 = MontFp!(F127, "3"); + /// sqrt(Xi/Zeta) + const XI_ON_ZETA_SQRT: F127 = MontFp!(F127, "13"); + } + + /// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite + /// Field of size 127 + /// With psi: E_isogenous -> E + /// psi = (psi_x(x,y), psi_y(x,y)) + /// where + /// psi_x: (-57*x^13 - 21*x^12 + 10*x^11 + 34*x^10 + 40*x^9 - + /// 13*x^8 + 32*x^7 - 32*x^6 + 23*x^5 - 14*x^4 + 39*x^3 + 23*x^2 + 63*x + + /// 4)/(x^12 - 13*x^11 + 11*x^10 - 33*x^9 - 30*x^8 + 30*x^7 + 34*x^6 - 44*x^5 + + /// 63*x^4 - 20*x^3 - 10*x^2 + 31*x + 2) + /// + /// psi_y: (10*x^18*y + 59*x^17*y + 41*x^16*y + 48*x^15*y - 7*x^14*y + 6*x^13*y + + /// 5*x^12*y + 62*x^11*y + 12*x^10*y + 36*x^9*y - 49*x^8*y - 18*x^7*y - 63*x^6*y + /// - 43*x^5*y - 60*x^4*y - 18*x^3*y + 30*x^2*y - 57*x*y - 34*y)/(x^18 + 44*x^17 + /// - 63*x^16 + 52*x^15 + 3*x^14 + 38*x^13 - 30*x^12 + 11*x^11 - 42*x^10 - 13*x^9 + /// - 46*x^8 - 61*x^7 - 16*x^6 - 55*x^5 + 18*x^4 + 23*x^3 - 24*x^2 - 18*x + 32) + impl WBParams for TestWBF127MapToCurveParams { + type IsogenousCurve = TestSWU127MapToIsogenousCurveParams; + + const PHI_X_NOM: &'static [::BaseField] = &[ + MontFp!(F127, "4"), + MontFp!(F127, "63"), + MontFp!(F127, "23"), + MontFp!(F127, "39"), + MontFp!(F127, "-14"), + MontFp!(F127, "23"), + MontFp!(F127, "-32"), + MontFp!(F127, "32"), + MontFp!(F127, "-13"), + MontFp!(F127, "40"), + MontFp!(F127, "34"), + MontFp!(F127, "10"), + MontFp!(F127, "-21"), + MontFp!(F127, "-57"), + ]; + + const PHI_X_DEN: &'static [::BaseField] = &[ + MontFp!(F127, "2"), + MontFp!(F127, "31"), + MontFp!(F127, "-10"), + MontFp!(F127, "-20"), + MontFp!(F127, "63"), + MontFp!(F127, "-44"), + MontFp!(F127, "34"), + MontFp!(F127, "30"), + MontFp!(F127, "-30"), + MontFp!(F127, "-33"), + MontFp!(F127, "11"), + MontFp!(F127, "-13"), + MontFp!(F127, "1"), + ]; + + const PHI_Y_NOM: &'static [::BaseField] = &[ + MontFp!(F127, "-34"), + MontFp!(F127, "-57"), + MontFp!(F127, "30"), + MontFp!(F127, "-18"), + MontFp!(F127, "-60"), + MontFp!(F127, "-43"), + MontFp!(F127, "-63"), + MontFp!(F127, "-18"), + MontFp!(F127, "-49"), + MontFp!(F127, "36"), + MontFp!(F127, "12"), + MontFp!(F127, "62"), + MontFp!(F127, "5"), + MontFp!(F127, "6"), + MontFp!(F127, "-7"), + MontFp!(F127, "48"), + MontFp!(F127, "41"), + MontFp!(F127, "59"), + MontFp!(F127, "10"), + ]; + + const PHI_Y_DEN: &'static [::BaseField] = &[ + MontFp!(F127, "32"), + MontFp!(F127, "-18"), + MontFp!(F127, "-24"), + MontFp!(F127, "23"), + MontFp!(F127, "18"), + MontFp!(F127, "-55"), + MontFp!(F127, "-16"), + MontFp!(F127, "-61"), + MontFp!(F127, "-46"), + MontFp!(F127, "-13"), + MontFp!(F127, "-42"), + MontFp!(F127, "11"), + MontFp!(F127, "-30"), + MontFp!(F127, "38"), + MontFp!(F127, "3"), + MontFp!(F127, "52"), + MontFp!(F127, "-63"), + MontFp!(F127, "44"), + MontFp!(F127, "1"), + ]; + } + + /// The point of the test is to get a simple WB compatible curve + /// and make simple hash + #[test] + fn hash_arbitrary_string_to_curve_wb() { + use sha2::Sha256; + let test_wb_to_curve_hasher = MapToCurveBasedHasher::< + GroupAffine, + DefaultFieldHasher, + WBMap, + >::new(&[1]) + .unwrap(); + + let hash_result = test_wb_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); + + assert!( + hash_result.x != F127_ZERO && hash_result.y != F127_ZERO, + "we assume that not both a and b coefficienst are zero for the test curve" + ); + + assert!( + hash_result.is_on_curve(), + "hash results into a point off the curve" + ); + } +} diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 2cc288686..0ff1c8c38 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -1,10 +1,7 @@ use crate::hashing::HashToCurve; use crate::{ hashing::{ - curve_maps::{ - swu::{parity, SWUMap, SWUParams}, - wb::{WBMap, WBParams}, - }, + curve_maps::swu::{parity, SWUMap, SWUParams}, field_hashers::DefaultFieldHasher, map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher}, }, @@ -12,7 +9,7 @@ use crate::{ short_weierstrass_jacobian::GroupAffine, ModelParameters, }; -use ark_ff::{biginteger::BigInteger64, fields::Fp64, BigInt, MontBackend, MontFp}; +use ark_ff::{fields::Fp64, MontBackend, MontFp}; use ark_ff::SquareRootField; use ark_std::vec::Vec; @@ -24,31 +21,12 @@ mod json; #[cfg(all(test, feature = "std"))] mod suites; +#[derive(ark_ff::MontConfig)] +#[modulus = "127"] +#[generator = "6"] pub struct F127Config; pub type F127 = Fp64>; -impl ark_ff::MontConfig<1> for F127Config { - // sage: FF(3)^63 - // 126 - #[rustfmt::skip] - const TWO_ADIC_ROOT_OF_UNITY: F127 = MontFp!(F127, "126"); - - /// MODULUS = 127 - #[rustfmt::skip] - const MODULUS: BigInteger64 = BigInt!("127"); - - // sage: FF(3).multiplicative_order() - // 126 - // Montgomery conversion 3 * 2 = 6 % 127 - /// GENERATOR = 3 - #[rustfmt::skip] - const GENERATOR: F127 = MontFp!(F127, "6"); - - // T and T_MINUS_ONE_DIV_TWO, where MODULUS - 1 = 2^S * T - // For T coprime to 2 -} - -const F127_ZERO: F127 = MontFp!(F127, "0"); const F127_ONE: F127 = MontFp!(F127, "1"); struct TestSWUMapToCurveParams; @@ -176,199 +154,6 @@ fn map_field_to_curve_swu() { ); } -/// Testing WB19 hashing on a small curve -/// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite -/// Field of size 127 -/// Isogenous to E : y^2 = x^3 + 3 -struct TestSWU127MapToIsogenousCurveParams; - -/// First we define the isogenous curve -/// sage: E_isogenous.order() -/// 127 -impl ModelParameters for TestSWU127MapToIsogenousCurveParams { - const COFACTOR: &'static [u64] = &[1]; - - #[rustfmt::skip] - const COFACTOR_INV: F127 = F127_ONE; - - type BaseField = F127; - type ScalarField = F127; -} - -/// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite -/// Field of size 127 -impl SWModelParameters for TestSWU127MapToIsogenousCurveParams { - /// COEFF_A = 109 - const COEFF_A: F127 = MontFp!(F127, "109"); - - /// COEFF_B = 124 - #[rustfmt::skip] - const COEFF_B: F127 = MontFp!(F127, "124"); - - /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) - const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = - (MontFp!(F127, "84"), MontFp!(F127, "2")); -} - -/// SWU parameters for E_isogenous -impl SWUParams for TestSWU127MapToIsogenousCurveParams { - /// NON-SQUARE = - 1 - const XI: F127 = MontFp!(F127, "-1"); - /// A Primitive Root of unity = 3 - const ZETA: F127 = MontFp!(F127, "3"); - /// sqrt(Xi/Zeta) - const XI_ON_ZETA_SQRT: F127 = MontFp!(F127, "13"); -} - -/// The struct defining our parameters for the target curve of hashing -struct TestWBF127MapToCurveParams; - -impl ModelParameters for TestWBF127MapToCurveParams { - const COFACTOR: &'static [u64] = &[1]; - - #[rustfmt::skip] - const COFACTOR_INV: F127 = F127_ONE; - - type BaseField = F127; - type ScalarField = F127; -} - -/// E: Elliptic Curve defined by y^2 = x^3 + 3 over Finite -/// Field of size 127 -impl SWModelParameters for TestWBF127MapToCurveParams { - /// COEFF_A = 0 - const COEFF_A: F127 = F127_ZERO; - - /// COEFF_B = 3 - #[rustfmt::skip] - const COEFF_B: F127 = MontFp!(F127, "3"); - - /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) - const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = - (MontFp!(F127, "62"), MontFp!(F127, "70")); -} - -/// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite -/// Field of size 127 -/// With psi: E_isogenous -> E -/// psi = (psi_x(x,y), psi_y(x,y)) -/// where -/// psi_x: (-57*x^13 - 21*x^12 + 10*x^11 + 34*x^10 + 40*x^9 - -/// 13*x^8 + 32*x^7 - 32*x^6 + 23*x^5 - 14*x^4 + 39*x^3 + 23*x^2 + 63*x + -/// 4)/(x^12 - 13*x^11 + 11*x^10 - 33*x^9 - 30*x^8 + 30*x^7 + 34*x^6 - 44*x^5 + -/// 63*x^4 - 20*x^3 - 10*x^2 + 31*x + 2) -/// -/// psi_y: (10*x^18*y + 59*x^17*y + 41*x^16*y + 48*x^15*y - 7*x^14*y + 6*x^13*y + -/// 5*x^12*y + 62*x^11*y + 12*x^10*y + 36*x^9*y - 49*x^8*y - 18*x^7*y - 63*x^6*y -/// - 43*x^5*y - 60*x^4*y - 18*x^3*y + 30*x^2*y - 57*x*y - 34*y)/(x^18 + 44*x^17 -/// - 63*x^16 + 52*x^15 + 3*x^14 + 38*x^13 - 30*x^12 + 11*x^11 - 42*x^10 - 13*x^9 -/// - 46*x^8 - 61*x^7 - 16*x^6 - 55*x^5 + 18*x^4 + 23*x^3 - 24*x^2 - 18*x + 32) -impl WBParams for TestWBF127MapToCurveParams { - type IsogenousCurve = TestSWU127MapToIsogenousCurveParams; - - const PHI_X_NOM: &'static [::BaseField] = &[ - MontFp!(F127, "4"), - MontFp!(F127, "63"), - MontFp!(F127, "23"), - MontFp!(F127, "39"), - MontFp!(F127, "-14"), - MontFp!(F127, "23"), - MontFp!(F127, "-32"), - MontFp!(F127, "32"), - MontFp!(F127, "-13"), - MontFp!(F127, "40"), - MontFp!(F127, "34"), - MontFp!(F127, "10"), - MontFp!(F127, "-21"), - MontFp!(F127, "-57"), - ]; - - const PHI_X_DEN: &'static [::BaseField] = &[ - MontFp!(F127, "2"), - MontFp!(F127, "31"), - MontFp!(F127, "-10"), - MontFp!(F127, "-20"), - MontFp!(F127, "63"), - MontFp!(F127, "-44"), - MontFp!(F127, "34"), - MontFp!(F127, "30"), - MontFp!(F127, "-30"), - MontFp!(F127, "-33"), - MontFp!(F127, "11"), - MontFp!(F127, "-13"), - MontFp!(F127, "1"), - ]; - - const PHI_Y_NOM: &'static [::BaseField] = &[ - MontFp!(F127, "-34"), - MontFp!(F127, "-57"), - MontFp!(F127, "30"), - MontFp!(F127, "-18"), - MontFp!(F127, "-60"), - MontFp!(F127, "-43"), - MontFp!(F127, "-63"), - MontFp!(F127, "-18"), - MontFp!(F127, "-49"), - MontFp!(F127, "36"), - MontFp!(F127, "12"), - MontFp!(F127, "62"), - MontFp!(F127, "5"), - MontFp!(F127, "6"), - MontFp!(F127, "-7"), - MontFp!(F127, "48"), - MontFp!(F127, "41"), - MontFp!(F127, "59"), - MontFp!(F127, "10"), - ]; - - const PHI_Y_DEN: &'static [::BaseField] = &[ - MontFp!(F127, "32"), - MontFp!(F127, "-18"), - MontFp!(F127, "-24"), - MontFp!(F127, "23"), - MontFp!(F127, "18"), - MontFp!(F127, "-55"), - MontFp!(F127, "-16"), - MontFp!(F127, "-61"), - MontFp!(F127, "-46"), - MontFp!(F127, "-13"), - MontFp!(F127, "-42"), - MontFp!(F127, "11"), - MontFp!(F127, "-30"), - MontFp!(F127, "38"), - MontFp!(F127, "3"), - MontFp!(F127, "52"), - MontFp!(F127, "-63"), - MontFp!(F127, "44"), - MontFp!(F127, "1"), - ]; -} - -/// The point of the test is to get a simple WB compatible curve -/// and make simple hash -#[test] -fn hash_arbitary_string_to_curve_wb() { - use sha2::Sha256; - let test_wb_to_curve_hasher = MapToCurveBasedHasher::< - GroupAffine, - DefaultFieldHasher, - WBMap, - >::new(&[1]) - .unwrap(); - - let hash_result = test_wb_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); - - assert!( - hash_result.x != F127_ZERO && hash_result.y != F127_ZERO, - "we assume that not both a and b coefficienst are zero for the test curve" - ); - - assert!( - hash_result.is_on_curve(), - "hash results into a point off the curve" - ); -} - #[test] fn test_parity_of_prime_field_elements() { let a1 = Fq::from(0); From 8f7dce8f64ec0df32cd2d6cb8c1d25068a483ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 4 May 2022 15:43:47 +0200 Subject: [PATCH 15/56] Move small field SWU tests to curve_maps --- ec/src/hashing/curve_maps/swu/mod.rs | 146 ++++++++++++++++++++++++++ ec/src/hashing/tests/mod.rs | 149 +-------------------------- 2 files changed, 147 insertions(+), 148 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index f45e6ae56..dedbe3ecb 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -173,3 +173,149 @@ impl MapToCurve> for SWUMap

{ Ok(point_on_curve) } } + +#[cfg(test)] +mod test { + use crate::hashing::field_hashers::DefaultFieldHasher; + use crate::hashing::map_to_curve_hasher::MapToCurveBasedHasher; + use crate::hashing::HashToCurve; + use crate::ModelParameters; + use ark_std::vec::Vec; + + use super::*; + use ark_ff::SquareRootField; + use ark_ff::{fields::Fp64, MontBackend, MontFp}; + use hashbrown::HashMap; + use sha2::Sha256; + + #[derive(ark_ff::MontConfig)] + #[modulus = "127"] + #[generator = "6"] + pub struct F127Config; + pub type F127 = Fp64>; + + const F127_ONE: F127 = MontFp!(F127, "1"); + + struct TestSWUMapToCurveParams; + + impl ModelParameters for TestSWUMapToCurveParams { + const COFACTOR: &'static [u64] = &[1]; + + #[rustfmt::skip] + const COFACTOR_INV: F127 = F127_ONE; + + type BaseField = F127; + type ScalarField = F127; + } + /// just because not defining another field + /// + /// from itertools import product + /// p = 127 + /// FF = GF(p) + /// for a,b in product(range(0,p), range(0,p)): + /// try: + /// E = EllipticCurve([FF(a),FF(b)]) + /// if E.order() == p: + /// print(E) + /// except: + /// pass + /// + /// y^2 = x^3 + x + 63 + impl SWModelParameters for TestSWUMapToCurveParams { + /// COEFF_A = 1 + const COEFF_A: F127 = F127_ONE; + + /// COEFF_B = 1 + #[rustfmt::skip] + const COEFF_B: F127 = MontFp!(F127, "63"); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (MontFp!(F127, "62"), MontFp!(F127, "70")); + } + + impl SWUParams for TestSWUMapToCurveParams { + const XI: F127 = MontFp!(F127, "-1"); + const ZETA: F127 = MontFp!(F127, "3"); + const XI_ON_ZETA_SQRT: F127 = MontFp!(F127, "13"); + } + + /// test that MontFp make a none zero element out of 1 + #[test] + fn test_field_element_construction() { + let a1 = F127::from(1); + let a2 = F127::from(2); + let a3 = F127::from(125); + + assert!(F127::from(0) == a2 + a3); + assert!(F127::from(0) == a2 * a1 + a3); + } + + #[test] + fn test_field_division() { + let num = F127::from(0x3d); + let den = F127::from(0x7b); + let num_on_den = F127::from(0x50); + + assert!(num / den == num_on_den); + } + + /// Check that the hashing parameters are sane: zeta should be a non-square + #[test] + fn checking_the_hashing_parameters() { + assert!(SquareRootField::legendre(&TestSWUMapToCurveParams::ZETA).is_qr() == false); + } + + /// The point of the test is to get a simple SWU compatible curve and make + /// simple hash + #[test] + fn hash_arbitary_string_to_curve_swu() { + let test_swu_to_curve_hasher = MapToCurveBasedHasher::< + GroupAffine, + DefaultFieldHasher, + SWUMap, + >::new(&[1]) + .unwrap(); + + let hash_result = test_swu_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); + + assert!( + hash_result.is_on_curve(), + "hash results into a point off the curve" + ); + } + + /// Use a simple SWU compatible curve and map the whole field to it. We observe + /// the map behaviour. Specifically, the map should be non-constant, all + /// elements should be mapped to curve successfully. everything can be mapped + #[test] + fn map_field_to_curve_swu() { + let test_map_to_curve = SWUMap::::new_map_to_curve().unwrap(); + + let mut map_range: Vec> = vec![]; + for current_field_element in 0..127 { + map_range.push( + test_map_to_curve + .map_to_curve(F127::from(current_field_element as u64)) + .unwrap(), + ); + } + + let mut counts = HashMap::new(); + + let mode = map_range + .iter() + .copied() + .max_by_key(|&n| { + let count = counts.entry(n).or_insert(0); + *count += 1; + *count + }) + .unwrap(); + + assert!( + *counts.get(&mode).unwrap() != 127, + "a constant hash function is not good." + ); + } +} diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 0ff1c8c38..40f228325 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -1,159 +1,12 @@ -use crate::hashing::HashToCurve; -use crate::{ - hashing::{ - curve_maps::swu::{parity, SWUMap, SWUParams}, - field_hashers::DefaultFieldHasher, - map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher}, - }, - models::SWModelParameters, - short_weierstrass_jacobian::GroupAffine, - ModelParameters, -}; -use ark_ff::{fields::Fp64, MontBackend, MontFp}; +use crate::hashing::curve_maps::swu::parity; -use ark_ff::SquareRootField; -use ark_std::vec::Vec; use ark_test_curves::bls12_381::{Fq, Fq2, Fq6}; -use hashbrown::HashMap; #[cfg(all(test, feature = "std"))] mod json; #[cfg(all(test, feature = "std"))] mod suites; -#[derive(ark_ff::MontConfig)] -#[modulus = "127"] -#[generator = "6"] -pub struct F127Config; -pub type F127 = Fp64>; - -const F127_ONE: F127 = MontFp!(F127, "1"); - -struct TestSWUMapToCurveParams; - -impl ModelParameters for TestSWUMapToCurveParams { - const COFACTOR: &'static [u64] = &[1]; - - #[rustfmt::skip] - const COFACTOR_INV: F127 = F127_ONE; - - type BaseField = F127; - type ScalarField = F127; -} -/// just because not defining another field -/// -/// from itertools import product -/// p = 127 -/// FF = GF(p) -/// for a,b in product(range(0,p), range(0,p)): -/// try: -/// E = EllipticCurve([FF(a),FF(b)]) -/// if E.order() == p: -/// print(E) -/// except: -/// pass -/// -/// y^2 = x^3 + x + 63 -impl SWModelParameters for TestSWUMapToCurveParams { - /// COEFF_A = 1 - const COEFF_A: F127 = F127_ONE; - - /// COEFF_B = 1 - #[rustfmt::skip] - const COEFF_B: F127 = MontFp!(F127, "63"); - - /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) - const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = - (MontFp!(F127, "62"), MontFp!(F127, "70")); -} - -impl SWUParams for TestSWUMapToCurveParams { - const XI: F127 = MontFp!(F127, "-1"); - const ZETA: F127 = MontFp!(F127, "3"); - const XI_ON_ZETA_SQRT: F127 = MontFp!(F127, "13"); -} - -/// test that MontFp make a none zero element out of 1 -#[test] -fn test_field_element_construction() { - let a1 = F127::from(1); - let a2 = F127::from(2); - let a3 = F127::from(125); - - assert!(F127::from(0) == a2 + a3); - assert!(F127::from(0) == a2 * a1 + a3); -} - -#[test] -fn test_field_division() { - let num = F127::from(0x3d); - let den = F127::from(0x7b); - let num_on_den = F127::from(0x50); - - assert!(num / den == num_on_den); -} - -/// Check that the hashing parameters are sane: zeta should be a non-square -#[test] -fn checking_the_hashing_parameters() { - assert!(SquareRootField::legendre(&TestSWUMapToCurveParams::ZETA).is_qr() == false); -} - -/// The point of the test is to get a simple SWU compatible curve and make -/// simple hash -#[test] -fn hash_arbitary_string_to_curve_swu() { - use sha2::Sha256; - - let test_swu_to_curve_hasher = MapToCurveBasedHasher::< - GroupAffine, - DefaultFieldHasher, - SWUMap, - >::new(&[1]) - .unwrap(); - - let hash_result = test_swu_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); - - assert!( - hash_result.is_on_curve(), - "hash results into a point off the curve" - ); -} - -/// Use a simple SWU compatible curve and map the whole field to it. We observe -/// the map behaviour. Specifically, the map should be non-constant, all -/// elements should be mapped to curve successfully. everything can be mapped -#[test] -fn map_field_to_curve_swu() { - let test_map_to_curve = SWUMap::::new_map_to_curve().unwrap(); - - let mut map_range: Vec> = vec![]; - for current_field_element in 0..127 { - map_range.push( - test_map_to_curve - .map_to_curve(F127::from(current_field_element as u64)) - .unwrap(), - ); - } - - let mut counts = HashMap::new(); - - let mode = map_range - .iter() - .copied() - .max_by_key(|&n| { - let count = counts.entry(n).or_insert(0); - *count += 1; - *count - }) - .unwrap(); - - assert!( - *counts.get(&mode).unwrap() != 127, - "a constant hash function is not good." - ); -} - #[test] fn test_parity_of_prime_field_elements() { let a1 = Fq::from(0); From 09428602a15690d5f8a5cf53d49ade36afb2389f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 4 May 2022 16:39:13 +0200 Subject: [PATCH 16/56] Add test suites for g1_iso Not working yet - points not matching --- ec/src/hashing/tests/suites.rs | 48 +++++++++++++++-- test-curves/src/bls12_381/g1_swu_iso.rs | 71 +++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 test-curves/src/bls12_381/g1_swu_iso.rs diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 33be50f9b..1f0e37b41 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -4,11 +4,20 @@ use std::io::BufReader; use super::json::SuiteVector; use libtest_mimic::{run_tests, Arguments, Outcome, Test}; -use crate::hashing::map_to_curve_hasher::HashToField; -use crate::hashing::tests::DefaultFieldHasher; +use ark_test_curves::{ + hashing::{ + curve_maps::swu::{parity, SWUMap, SWUParams}, + field_hashers::DefaultFieldHasher, + map_to_curve_hasher::{HashToField, MapToCurve, MapToCurveBasedHasher}, + HashToCurve, + }, + short_weierstrass_jacobian::GroupAffine, + ModelParameters, SWModelParameters, +}; + use ark_ff::PrimeField; -use ark_test_curves::bls12_381::Fq; use ark_test_curves::bls12_381::Fq2; +use ark_test_curves::bls12_381::{Fq, SwuIsoParameters}; use sha2::Sha256; #[test] @@ -34,8 +43,16 @@ fn suites() { fn run_test_w(Test { data, .. }: &Test) -> Outcome { assert_eq!(data.hash, "sha256"); let dst = data.dst.as_bytes(); + let mapper; let hasher; let m; + // TODO: differentiate between G1 and G2 Params! + mapper = MapToCurveBasedHasher::< + GroupAffine, + DefaultFieldHasher, + SWUMap, + >::new(dst) + .unwrap(); match data.curve.as_str() { "BLS12-381 G1" => { m = 1; @@ -51,6 +68,7 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { } for v in data.vectors.iter() { + // first, test field elements let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m).unwrap(); let want: Vec = (&v.u) .into_iter() @@ -71,6 +89,30 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { )), }; } + // then, test curve points + let got: GroupAffine = mapper.hash(&v.msg.as_bytes()).unwrap(); + assert!(got.is_on_curve()); + let x: Vec = (&v.p.x) + .split(",") + .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) + .collect(); + let y: Vec = (&v.p.y) + .split(",") + .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) + .collect(); + let want: GroupAffine = + GroupAffine::::new(x[0], y[0], false); + assert!(want.is_on_curve()); + if got != want { + return Outcome::Failed { + msg: Some(format!( + "Suite: {:?}\ngot: {:?}\nwant: {:?}", + data.ciphersuite, + got.to_string(), + want.to_string() + )), + }; + } } Outcome::Passed } diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs new file mode 100644 index 000000000..c02fce5ed --- /dev/null +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -0,0 +1,71 @@ +use crate::bls12_381::*; +use ark_ec::hashing::curve_maps::swu::SWUParams; +use ark_ec::models::{ModelParameters, SWModelParameters}; +use ark_ff::MontFp; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct SwuIsoParameters; + +impl ModelParameters for SwuIsoParameters { + type BaseField = Fq; + type ScalarField = Fr; + + /// COFACTOR = (x - 1)^2 / 3 = 76329603384216526031706109802092473003 + const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156]; + + /// COFACTOR_INV = COFACTOR^{-1} mod r + /// = 52435875175126190458656871551744051925719901746859129887267498875565241663483 + #[rustfmt::skip] + const COFACTOR_INV: Fr = MontFp!(Fr, "52435875175126190458656871551744051925719901746859129887267498875565241663483"); +} + +// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/ +// Hashing to Elliptic Curves +// 8.8.1. BLS12-381 G1 +// BLS12381G1_XMD:SHA-256_SSWU_RO_ is defined as follows: +// * E': y'^2 = x'^3 + A' * x' + B', where +// - A' = 0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d +// - B' = 0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0 +// - A' = 12190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677 +// - B' = 2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280 +// * Z: 11 +impl SWModelParameters for SwuIsoParameters { + //const COEFF_A: Fq = MontFp!(Fq, "012190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677"); //sage doesn't approve of this + const COEFF_A: Fq = MontFp!(Fq, "2858613208430792460670318198342879349494999260436483523154854961351063857243634726019465176474256126859776719994977"); + + #[rustfmt::skip] + const COEFF_B: Fq = MontFp!(Fq, "2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280"); + + /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (G1_GENERATOR_X, G1_GENERATOR_Y); +} + +// sage: Fq = E1p.base_field() +// sage: Fq +// Finite Field of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 +// sage: Fq.primitive_element() +// 2 +// sage: (Fq(11)/Fq(2)).sqrt() +// 1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394 +impl SWUParams for SwuIsoParameters { + const XI: Fq = MontFp!(Fq, "11"); // a nonsquare in Fq ietf standard + const ZETA: Fq = MontFp!(Fq, "2"); // arbitatry primitive root of unity (element) + const XI_ON_ZETA_SQRT: Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=Xi/Zeta Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=Xi/Zeta +} + +// sage: E1p = g1_iso.domain() +// sage: gen_p = E1p.random_point() +// sage: gen_p = 76329603384216526031706109802092473003 * gen_p +// sage: gen_p +// (628127623378585612843095022119507708025289394540669560027004601611569871267541856210323712812047239723504248810248 : 344075650239127142968089520704786925624745533124141202280424406752399324209523628375922007963596482424831722220273 : 1) +// sage: gen_p * 52435875175126190479447740508185965837690552500527637822603658699938581184513 +// (0 : 1 : 0) + +/// G1_GENERATOR_X = +#[rustfmt::skip] +pub const G1_GENERATOR_X: Fq = MontFp!(Fq, "628127623378585612843095022119507708025289394540669560027004601611569871267541856210323712812047239723504248810248"); + +/// G1_GENERATOR_Y = +#[rustfmt::skip] +pub const G1_GENERATOR_Y: Fq = MontFp!(Fq, "344075650239127142968089520704786925624745533124141202280424406752399324209523628375922007963596482424831722220273"); From 1c1afccea2fc18d5fd52824b7aaa8e981409ee21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 5 May 2022 11:30:37 +0200 Subject: [PATCH 17/56] Read the serialised point as on the original curve instead of on the isogeny Unify SWU and WB maps Revert "Unify SWU and WB maps" This reverts commit e8a78fd02996713e18fe0e22d273612ef49546a8. Expose ec and g1_iso items --- ec/src/hashing/tests/suites.rs | 17 ++++---- test-curves/src/bls12_381/g1.rs | 72 ++++++++++++++++++++++++++++++++ test-curves/src/bls12_381/mod.rs | 4 +- test-curves/src/lib.rs | 3 ++ 4 files changed, 85 insertions(+), 11 deletions(-) diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 1f0e37b41..f660584be 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -6,18 +6,16 @@ use libtest_mimic::{run_tests, Arguments, Outcome, Test}; use ark_test_curves::{ hashing::{ - curve_maps::swu::{parity, SWUMap, SWUParams}, + curve_maps::wb::WBMap, field_hashers::DefaultFieldHasher, - map_to_curve_hasher::{HashToField, MapToCurve, MapToCurveBasedHasher}, + map_to_curve_hasher::{HashToField, MapToCurveBasedHasher}, HashToCurve, }, short_weierstrass_jacobian::GroupAffine, - ModelParameters, SWModelParameters, }; use ark_ff::PrimeField; -use ark_test_curves::bls12_381::Fq2; -use ark_test_curves::bls12_381::{Fq, SwuIsoParameters}; +use ark_test_curves::bls12_381::{Fq, Fq2, Parameters}; use sha2::Sha256; #[test] @@ -48,9 +46,9 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { let m; // TODO: differentiate between G1 and G2 Params! mapper = MapToCurveBasedHasher::< - GroupAffine, + GroupAffine, DefaultFieldHasher, - SWUMap, + WBMap, >::new(dst) .unwrap(); match data.curve.as_str() { @@ -90,7 +88,7 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { }; } // then, test curve points - let got: GroupAffine = mapper.hash(&v.msg.as_bytes()).unwrap(); + let got: GroupAffine = mapper.hash(&v.msg.as_bytes()).unwrap(); assert!(got.is_on_curve()); let x: Vec = (&v.p.x) .split(",") @@ -100,8 +98,7 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { .split(",") .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) .collect(); - let want: GroupAffine = - GroupAffine::::new(x[0], y[0], false); + let want: GroupAffine = GroupAffine::::new(x[0], y[0], false); assert!(want.is_on_curve()); if got != want { return Outcome::Failed { diff --git a/test-curves/src/bls12_381/g1.rs b/test-curves/src/bls12_381/g1.rs index 1ed997061..9d9c11135 100644 --- a/test-curves/src/bls12_381/g1.rs +++ b/test-curves/src/bls12_381/g1.rs @@ -1,5 +1,6 @@ use crate::bls12_381::*; use ark_ec::{ + hashing::curve_maps::wb::WBParams, models::{ModelParameters, SWModelParameters}, short_weierstrass_jacobian::*, }; @@ -42,6 +43,77 @@ impl SWModelParameters for Parameters { } } +impl WBParams for Parameters { + type IsogenousCurve = SwuIsoParameters; + + const PHI_X_NOM: &'static [::BaseField] = &[ + MontFp!(Fq, "3761822637321485742094536206199512035685972329360337092690555528605752326213440950527352563934445837165125977345128"), + MontFp!(Fq, "1582172990273894682725716146256297593851554078446457591584154223376480866715343525953458444978680215440412886996200"), + MontFp!(Fq, "2051387046688339481714726479723076305756384619135044672831882917686431912682625619320120082313093891743187631791280"), + MontFp!(Fq, "61316326124367244515865706164471217084261738749879925739220878889304439271692421994859529859373651892126645952478"), + MontFp!(Fq, "1424741831220874356476333227468129624471472782807764018784263716426284995285578915327628560152704910696985638070031"), + MontFp!(Fq, "3415427104483187489859740871640064348492611444552862448295571438270821994900526625562705192993481400731539293415811"), + MontFp!(Fq, "248188830067800966021611907001049410443171766148926993624301072093542166689921157756350157715209127315556469919811"), + MontFp!(Fq, "2458049485161426253398308320890830930555526088324701597510592431647721369610314802890725095474874074634194669518436"), + MontFp!(Fq, "1239271775787030039269460763652455868148971086016832054354147730155061349388626624328773377658494412538595239256855"), + MontFp!(Fq, "698396551686164607792478797181335970223204059946034999723234339823539961139901150842584755596191372859677741313422"), + MontFp!(Fq, "2756657124183929639940341559332863560985099912924783743137983687385942647530234634138642360072966950403354118194880"), + MontFp!(Fq, "1058488477413994682556770863004536636444795456512795473806825292198091015005841418695586811009326456605062948114985"), + ]; + + const PHI_X_DEN: &'static [::BaseField] = &[ + MontFp!(Fq, "3949438676361386880769263910006560135979986067074971624024178233787093666769860448538216069627988502376148329127381"), + MontFp!(Fq, "2822220997908397120956501031591772354860004534930174057793539372552395729721474912921980407622851861692773516917759"), + MontFp!(Fq, "610552060666338680048265043345785271200283516960578188721887711701602621050421759883463448407237338290466946893545"), + MontFp!(Fq, "2439329436782028399166625708751323253248871941520474623095864400521929929188290312899217468935910181179336068540275"), + MontFp!(Fq, "3025903087998593826923738290305187197829899948335370692927241015584233559365859980023579293766193297662657497834014"), + MontFp!(Fq, "2787329879967655380381218769366715121683732401785552165471280254930041329235866427760690206934082971711204373036769"), + MontFp!(Fq, "3729460208364303450659860043245117836792062818643913458168515950720008978604972045673944667221729675671707946923021"), + MontFp!(Fq, "3179090966864399634396993677377903383656908036827452986467581478509513058347781039562481806409014718357094150199902"), + MontFp!(Fq, "684141363729077267665842443966270070725528746651574246973574894998264196269884726340959705960779078660850485681497"), + MontFp!(Fq, "1355518942857092779104773143196445884975815408961178437135200875404433360418847982032652351120700883660623679118159"), + MontFp!(Fq, "1"), + ]; + + const PHI_Y_NOM: &'static [::BaseField] = &[ + MontFp!(Fq, "1393399195776646641963150658816615410692049723305861307490980409834842911816308830479576739332720113414154429643571"), + MontFp!(Fq, "1511190695657960398963160955727174407082178148587899660611396357887273149842318573217989398009716786569780748006283"), + MontFp!(Fq, "3614401657395238041642341964430562932885284129837437306094802414995585690467848276262207178353676484330879154111757"), + MontFp!(Fq, "303251954782077855462083823228569901064301365507057490567314302006681283228886645653148231378803311079384246777035"), + MontFp!(Fq, "3668073836642475590306080768959183669825119857553168245915502992504527111582288680993272182771099907781295865642364"), + MontFp!(Fq, "889147988023366972622306341891649433228352963186679791369365907311293432508530696403569262531255821940400079347315"), + MontFp!(Fq, "718493410301850496156792713845282235942975872282052335612908458061560958159410402177452633054233549648465863759602"), + MontFp!(Fq, "3406136881215263818934773248465685844790898101337646888092845387936582793628141067747381197872508534868489799639699"), + MontFp!(Fq, "331351138484847160772695176511692246547145983117580056167533060034011313825061073939286437522432693033324549699722"), + MontFp!(Fq, "2171468288973248519912068884667133903101171670397991979582205855298465414047741472281361964966463442016062407908400"), + MontFp!(Fq, "2092842804947501956457889650155528390118620253793900717919970123642236515732658355049092877407901587228724229223110"), + MontFp!(Fq, "3961890550435212003631878720741046102282781357458395684082291998816751808643768526367549852177588213715211235373916"), + MontFp!(Fq, "1707589313757812493102695021134258021969283151093981498394095062397393499601961942449581422761005023512037430861560"), + MontFp!(Fq, "1967501030954114997918812128990512798136077044765138085902549248681331523022349398587390395919802044865687181234417"), + MontFp!(Fq, "2922895688438869655803185556286420403397802691723657346548307498540648684066474272936979722182960006715481007746439"), + MontFp!(Fq, "3370924952219000111210625390420697640496067348723987858345031683392215988129398381698161406651860675722373763741188"), + ]; + + const PHI_Y_DEN: &'static [::BaseField] = &[ + MontFp!(Fq, "3396434800020507717552209507749485772788165484415495716688989613875369612529138640646200921379825018840894888371137"), + MontFp!(Fq, "3955937245707125245654875920344947126613343076099634862876498453376019064171085472617926084668015244086355452990926"), + MontFp!(Fq, "3115801080798375384198119675359305198682407447857559059827677597200837822471239996878963936531572341910295439078930"), + MontFp!(Fq, "3496628876382137961119423566187258795236027183112131017519536056628828830323846696121917502443333849318934945158166"), + MontFp!(Fq, "3819161294135653749488194485080848928281288158623143986707267064691105653307717275066596854814679462226419882338445"), + MontFp!(Fq, "3838344850882296394939911407571260624820518547352197287854517462270146783414326660145944161947898461843919024387456"), + MontFp!(Fq, "3443845896188810583748698342858554856823966611538932245284665132724280883115455093457486044009395063504744802318172"), + MontFp!(Fq, "1189518655724056699355159955938426141594501095232997073362878098547301776615800227099534760471261853454585261625212"), + MontFp!(Fq, "2309935917761931164183799788994195243166135866798971442738101234750394172839060646960604788222384454747599044244610"), + MontFp!(Fq, "3459661102222301807083870307127272890283709299202626530836335779816726101522661683404130556379097384249447658110805"), + MontFp!(Fq, "3898950452492751420431682235553362135160293985934212849206350896691847297403795877806915602445207834970900272834330"), + MontFp!(Fq, "2381968764806454673720955440620228057919683152985846777578004069901421179563597288802750793515266450448328892335136"), + MontFp!(Fq, "1668238650112823419388205992952852912407572045257706138925379268508860023191233729074751042562151098884528280913356"), + MontFp!(Fq, "939263815598411948154903329612610969504805630387130456691588334780964163089645546614263028349325528011160458395367"), + MontFp!(Fq, "32073636674805471948264801926716749185281703472263713036772245044634215382853040827634712116543493471988382397345"), + MontFp!(Fq, "1"), + ]; +} + /// G1_GENERATOR_X = /// 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 #[rustfmt::skip] diff --git a/test-curves/src/bls12_381/mod.rs b/test-curves/src/bls12_381/mod.rs index 9df3e8fd3..77da67848 100644 --- a/test-curves/src/bls12_381/mod.rs +++ b/test-curves/src/bls12_381/mod.rs @@ -9,8 +9,10 @@ pub mod fq2; pub mod fq6; #[cfg(feature = "bls12_381_curve")] pub mod g1; +#[cfg(feature = "bls12_381_curve")] +pub mod g1_swu_iso; #[cfg(feature = "bls12_381_curve")] -pub use {fq::*, fq2::*, fq6::*, g1::*}; +pub use {fq::*, fq2::*, fq6::*, g1::*, g1_swu_iso::*}; #[cfg(test)] mod tests; diff --git a/test-curves/src/lib.rs b/test-curves/src/lib.rs index 580c509b0..6d94490de 100644 --- a/test-curves/src/lib.rs +++ b/test-curves/src/lib.rs @@ -3,6 +3,9 @@ extern crate ark_ff; pub use ark_ff::*; +extern crate ark_ec; +pub use ark_ec::*; + #[cfg(any(feature = "bls12_381_scalar_field", feature = "bls12_381_curve"))] pub mod bls12_381; From 61e5d0d29dd82f50e801fff59b2e1c7033cc2beb Mon Sep 17 00:00:00 2001 From: Marcin Date: Fri, 6 May 2022 22:56:20 +0200 Subject: [PATCH 18/56] Apply suggestions from code review Co-authored-by: Pratyush Mishra --- ec/src/hashing/field_hashers/mod.rs | 11 ++++++----- ec/src/hashing/tests/mod.rs | 6 ++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index e79687fda..ec9accf5f 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -58,17 +58,18 @@ impl HashToFie let len_in_bytes = count * m * self.len_per_base_elem; let uniform_bytes = self.expander.expand(message, len_in_bytes); - let mut output: Vec = Vec::with_capacity(count); + let mut output = Vec::with_capacity(count); + let mut base_prime_field_elems = Vec::with_capacity(m); for i in 0..count { - let mut base_prime_field_elems: Vec = Vec::new(); + base_prime_field_elems.clear(); for j in 0..m { let elm_offset = self.len_per_base_elem * (j + i * m); - let val: F::BasePrimeField = F::BasePrimeField::from_be_bytes_mod_order( - &uniform_bytes[elm_offset..(elm_offset + self.len_per_base_elem)], + let val = F::BasePrimeField::from_be_bytes_mod_order( + &uniform_bytes[elm_offset..][..self.len_per_base_elem], ); base_prime_field_elems.push(val); } - let f: F = F::from_base_prime_field_elems(&base_prime_field_elems).unwrap(); + let f = F::from_base_prime_field_elems(&base_prime_field_elems).unwrap(); output.push(f); } diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 2cc288686..1b42de3cc 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -125,11 +125,10 @@ fn checking_the_hashing_parameters() { /// simple hash #[test] fn hash_arbitary_string_to_curve_swu() { - use sha2::Sha256; let test_swu_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultFieldHasher, + DefaultFieldHasher, SWUMap, >::new(&[1]) .unwrap(); @@ -348,10 +347,9 @@ impl WBParams for TestWBF127MapToCurveParams { /// and make simple hash #[test] fn hash_arbitary_string_to_curve_wb() { - use sha2::Sha256; let test_wb_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultFieldHasher, + DefaultFieldHasher, WBMap, >::new(&[1]) .unwrap(); From 37dae2e76fc8b18411af11bc5045cc2c03cc9015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Fri, 6 May 2022 23:02:39 +0200 Subject: [PATCH 19/56] import the correct crate: sha2 --- ec/src/hashing/tests/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 1b42de3cc..bc8f6c4c2 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -128,7 +128,7 @@ fn hash_arbitary_string_to_curve_swu() { let test_swu_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultFieldHasher, + DefaultFieldHasher, SWUMap, >::new(&[1]) .unwrap(); @@ -349,7 +349,7 @@ impl WBParams for TestWBF127MapToCurveParams { fn hash_arbitary_string_to_curve_wb() { let test_wb_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, - DefaultFieldHasher, + DefaultFieldHasher, WBMap, >::new(&[1]) .unwrap(); From efe7a10efea348d42d5a82243bef8b4a7c2694c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Fri, 6 May 2022 23:03:54 +0200 Subject: [PATCH 20/56] Rename hasher/mapper constructors to just `new` --- ec/src/hashing/curve_maps/swu/mod.rs | 2 +- ec/src/hashing/curve_maps/wb/mod.rs | 4 ++-- ec/src/hashing/field_hashers/mod.rs | 4 ++-- ec/src/hashing/map_to_curve_hasher.rs | 8 ++++---- ec/src/hashing/tests/mod.rs | 2 +- ec/src/hashing/tests/suites.rs | 6 ++---- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index f45e6ae56..78c886965 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -42,7 +42,7 @@ pub fn parity(element: &F) -> bool { impl MapToCurve> for SWUMap

{ /// Constructs a new map if `P` represents a valid map. - fn new_map_to_curve() -> Result { + fn new() -> Result { // Verifying that both XI and ZETA are non-squares if P::XI.legendre().is_qr() || P::ZETA.legendre().is_qr() { return Err(HashToCurveError::MapToCurveError( diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index ff002a3b8..77487ff3b 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -58,7 +58,7 @@ pub struct WBMap { impl MapToCurve> for WBMap

{ /// Constructs a new map if `P` represents a valid map. - fn new_map_to_curve() -> Result { + fn new() -> Result { // Verifying that the isogeny maps the generator of the SWU curve into us let isogenous_curve_generator = GroupAffine::::new( P::IsogenousCurve::AFFINE_GENERATOR_COEFFS.0, @@ -76,7 +76,7 @@ impl MapToCurve> for WBMap

{ } Ok(WBMap { - swu_field_curve_hasher: SWUMap::::new_map_to_curve().unwrap(), + swu_field_curve_hasher: SWUMap::::new().unwrap(), curve_params: PhantomData, }) } diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index ec9accf5f..2502c7639 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -20,7 +20,7 @@ use expander::Expander; /// use sha2::Sha256; /// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; /// -/// let hasher = as HashToField>::new_hash_to_field(&[1, 2, 3]).unwrap(); +/// let hasher = as HashToField>::new(&[1, 2, 3]).unwrap(); /// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); /// /// assert_eq!(field_elements.len(), 2); @@ -33,7 +33,7 @@ pub struct DefaultFieldHasher HashToField for DefaultFieldHasher { - fn new_hash_to_field(dst: &[u8]) -> Result { + fn new(dst: &[u8]) -> Result { // The final output of `hash_to_field` will be an array of field // elements from F::BaseField, each of size `len_per_elem`. let len_per_base_elem = get_len_per_elem::(); diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index 88e52777d..3a7ded633 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -5,7 +5,7 @@ use ark_std::{marker::PhantomData, vec::Vec}; /// Trait for mapping a random field element to a random curve point. pub trait MapToCurve { /// Constructs a new mapping. - fn new_map_to_curve() -> Result + fn new() -> Result where Self: Sized; /// Map an arbitary field element to a corresponding curve point. @@ -20,7 +20,7 @@ pub trait HashToField: Sized { /// /// * `domain` - bytes that get concatenated with the `msg` during hashing, in order to separate potentially interfering instantiations of the hasher. /// * `count` - number of elements in field `F` to output. - fn new_hash_to_field(domain: &[u8]) -> Result; + fn new(domain: &[u8]) -> Result; /// Hash an arbitrary `msg` to #`count` elements from field `F`. fn hash_to_field(&self, msg: &[u8], count: usize) -> Result, HashToCurveError>; @@ -47,8 +47,8 @@ where M2C: MapToCurve, { fn new(domain: &[u8]) -> Result { - let field_hasher = H2F::new_hash_to_field(domain)?; - let curve_mapper = M2C::new_map_to_curve()?; + let field_hasher = H2F::new(domain)?; + let curve_mapper = M2C::new()?; let _params_t = PhantomData; Ok(MapToCurveBasedHasher { field_hasher, diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index bc8f6c4c2..e1997a41a 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -146,7 +146,7 @@ fn hash_arbitary_string_to_curve_swu() { /// elements should be mapped to curve successfully. everything can be mapped #[test] fn map_field_to_curve_swu() { - let test_map_to_curve = SWUMap::::new_map_to_curve().unwrap(); + let test_map_to_curve = SWUMap::::new().unwrap(); let mut map_range: Vec> = vec![]; for current_field_element in 0..127 { diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 33be50f9b..7f087ce47 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -39,13 +39,11 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { match data.curve.as_str() { "BLS12-381 G1" => { m = 1; - hasher = as HashToField>::new_hash_to_field(dst) - .unwrap(); + hasher = as HashToField>::new(dst).unwrap(); }, "BLS12-381 G2" => { m = 2; - hasher = as HashToField>::new_hash_to_field(dst) - .unwrap(); + hasher = as HashToField>::new(dst).unwrap(); }, _ => return Outcome::Ignored, } From 833073e3fd11c0427af219c853697bd9d5672b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Fri, 6 May 2022 23:10:11 +0200 Subject: [PATCH 21/56] Add a default SEC_PARAM value of 128 --- ec/src/hashing/field_hashers/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ec/src/hashing/field_hashers/mod.rs b/ec/src/hashing/field_hashers/mod.rs index 2502c7639..86360e246 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ec/src/hashing/field_hashers/mod.rs @@ -20,12 +20,12 @@ use expander::Expander; /// use sha2::Sha256; /// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; /// -/// let hasher = as HashToField>::new(&[1, 2, 3]).unwrap(); +/// let hasher = as HashToField>::new(&[1, 2, 3]).unwrap(); /// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); /// /// assert_eq!(field_elements.len(), 2); /// ``` -pub struct DefaultFieldHasher { +pub struct DefaultFieldHasher { expander: ExpanderXmd, len_per_base_elem: usize, } From c2653d2a5f1f29bcb2a968803c4954bd17c8d9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Fri, 6 May 2022 23:17:29 +0200 Subject: [PATCH 22/56] Remove empty line --- ec/src/hashing/tests/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index e1997a41a..50d5c6f69 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -125,7 +125,6 @@ fn checking_the_hashing_parameters() { /// simple hash #[test] fn hash_arbitary_string_to_curve_swu() { - let test_swu_to_curve_hasher = MapToCurveBasedHasher::< GroupAffine, DefaultFieldHasher, From ac2aa67ebf17d12e8f5372c34d4cdce9c8b072da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Mon, 9 May 2022 11:28:42 +0200 Subject: [PATCH 23/56] Move hash_to_field into ff crate --- ec/src/hashing/map_to_curve_hasher.rs | 22 ++------- ec/src/hashing/mod.rs | 14 ------ ec/src/hashing/tests/mod.rs | 2 +- ec/src/hashing/tests/suites.rs | 9 ++-- ff/Cargo.toml | 9 ++++ ff/src/bytes.rs | 3 +- .../src/fields}/field_hashers/expander/mod.rs | 0 .../expand_message_xmd_SHA256_256.json | 0 .../expand_message_xmd_SHA256_38.json | 0 .../expand_message_xmd_SHA512_38.json | 0 .../expand_message_xof_SHAKE128_256.json | 0 .../expand_message_xof_SHAKE128_36.json | 0 .../expand_message_xof_SHAKE256_36.json | 0 .../fields}/field_hashers/expander/tests.rs | 2 +- .../src/fields}/field_hashers/mod.rs | 47 ++++++++++++------- ff/src/fields/mod.rs | 2 + 16 files changed, 53 insertions(+), 57 deletions(-) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/mod.rs (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json (100%) rename {ec/src/hashing => ff/src/fields}/field_hashers/expander/tests.rs (97%) rename {ec/src/hashing => ff/src/fields}/field_hashers/mod.rs (73%) diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index 3a7ded633..4e4d8e5dd 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -1,6 +1,6 @@ use crate::{hashing::*, AffineCurve}; -use ark_ff::Field; -use ark_std::{marker::PhantomData, vec::Vec}; +use ark_ff::field_hashers::HashToField; +use ark_std::marker::PhantomData; /// Trait for mapping a random field element to a random curve point. pub trait MapToCurve { @@ -12,20 +12,6 @@ pub trait MapToCurve { fn map_to_curve(&self, point: T::BaseField) -> Result; } -/// Trait for hashing messages to field elements. -pub trait HashToField: Sized { - /// Initialises a new hash-to-field helper struct. - /// - /// # Arguments - /// - /// * `domain` - bytes that get concatenated with the `msg` during hashing, in order to separate potentially interfering instantiations of the hasher. - /// * `count` - number of elements in field `F` to output. - fn new(domain: &[u8]) -> Result; - - /// Hash an arbitrary `msg` to #`count` elements from field `F`. - fn hash_to_field(&self, msg: &[u8], count: usize) -> Result, HashToCurveError>; -} - /// Helper struct that can be used to construct elements on the elliptic curve /// from arbitrary messages, by first hashing the message onto a field element /// and then mapping it to the elliptic curve defined over that field. @@ -47,7 +33,7 @@ where M2C: MapToCurve, { fn new(domain: &[u8]) -> Result { - let field_hasher = H2F::new(domain)?; + let field_hasher = H2F::new(domain); let curve_mapper = M2C::new()?; let _params_t = PhantomData; Ok(MapToCurveBasedHasher { @@ -71,7 +57,7 @@ where // 5. P = clear_cofactor(R) // 6. return P - let rand_field_elems = self.field_hasher.hash_to_field(msg, 2)?; + let rand_field_elems = self.field_hasher.hash_to_field(msg, 2); let rand_curve_elem_0 = self.curve_mapper.map_to_curve(rand_field_elems[0])?; let rand_curve_elem_1 = self.curve_mapper.map_to_curve(rand_field_elems[1])?; diff --git a/ec/src/hashing/mod.rs b/ec/src/hashing/mod.rs index d58dde632..23901ea39 100644 --- a/ec/src/hashing/mod.rs +++ b/ec/src/hashing/mod.rs @@ -5,8 +5,6 @@ use core::fmt; pub mod curve_maps; pub mod map_to_curve_hasher; -pub mod field_hashers; - /// Trait for hashing arbitrary data to a group element on an elliptic curve pub trait HashToCurve: Sized { /// Create a new hash to curve instance, with a given domain. @@ -24,17 +22,8 @@ pub enum HashToCurveError { /// Curve choice is unsupported by the given HashToCurve method. UnsupportedCurveError(String), - /// Error in domain choice - DomainError(String), - - /// Error while hashing - HashingError(String), - /// Error with map to curve MapToCurveError(String), - - /// Error with hash to field - HashToFieldError(String), } impl ark_std::error::Error for HashToCurveError {} @@ -42,11 +31,8 @@ impl ark_std::error::Error for HashToCurveError {} impl fmt::Display for HashToCurveError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match self { - HashToCurveError::DomainError(s) => write!(f, "{}", s), HashToCurveError::UnsupportedCurveError(s) => write!(f, "{}", s), - HashToCurveError::HashingError(s) => write!(f, "{}", s), HashToCurveError::MapToCurveError(s) => write!(f, "{}", s), - HashToCurveError::HashToFieldError(s) => write!(f, "{}", s), } } } diff --git a/ec/src/hashing/tests/mod.rs b/ec/src/hashing/tests/mod.rs index 50d5c6f69..8f9326daf 100644 --- a/ec/src/hashing/tests/mod.rs +++ b/ec/src/hashing/tests/mod.rs @@ -5,13 +5,13 @@ use crate::{ swu::{parity, SWUMap, SWUParams}, wb::{WBMap, WBParams}, }, - field_hashers::DefaultFieldHasher, map_to_curve_hasher::{MapToCurve, MapToCurveBasedHasher}, }, models::SWModelParameters, short_weierstrass_jacobian::GroupAffine, ModelParameters, }; +use ark_ff::field_hashers::DefaultFieldHasher; use ark_ff::{biginteger::BigInteger64, fields::Fp64, BigInt, MontBackend, MontFp}; use ark_ff::SquareRootField; diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 7f087ce47..a8ba59a66 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -2,10 +2,9 @@ use std::fs::{read_dir, File}; use std::io::BufReader; use super::json::SuiteVector; +use ark_ff::field_hashers::{DefaultFieldHasher, HashToField}; use libtest_mimic::{run_tests, Arguments, Outcome, Test}; -use crate::hashing::map_to_curve_hasher::HashToField; -use crate::hashing::tests::DefaultFieldHasher; use ark_ff::PrimeField; use ark_test_curves::bls12_381::Fq; use ark_test_curves::bls12_381::Fq2; @@ -39,17 +38,17 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { match data.curve.as_str() { "BLS12-381 G1" => { m = 1; - hasher = as HashToField>::new(dst).unwrap(); + hasher = as HashToField>::new(dst); }, "BLS12-381 G2" => { m = 2; - hasher = as HashToField>::new(dst).unwrap(); + hasher = as HashToField>::new(dst); }, _ => return Outcome::Ignored, } for v in data.vectors.iter() { - let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m).unwrap(); + let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m); let want: Vec = (&v.u) .into_iter() .map(|x| { diff --git a/ff/Cargo.toml b/ff/Cargo.toml index fe6f1e793..0500a1a0f 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -25,9 +25,18 @@ paste = "1.0" rayon = { version = "1", optional = true } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } num-bigint = { version = "0.4", default-features = false } +digest = { version = "0.10", default-features = false , features = ["alloc"] } [dev-dependencies] ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = [ "bls12_381_curve", "mnt6_753"] } +blake2 = { version = "0.10", default-features = false } +sha3 = { version = "0.10", default-features = false } +sha2 = { version = "0.10", default-features = false } +libtest-mimic = "0.3.0" +serde = "1.0.110" +serde_json = "1.0.53" +serde_derive = "1.0.110" +hex = "0.4" [build-dependencies] rustc_version = "0.4" diff --git a/ff/src/bytes.rs b/ff/src/bytes.rs index f96ce997a..1908598f4 100644 --- a/ff/src/bytes.rs +++ b/ff/src/bytes.rs @@ -314,11 +314,12 @@ impl FromBytes for Option { #[cfg(test)] mod test { use ark_std::vec::Vec; + #[test] fn test_macro_empty() { let array: Vec = vec![]; let bytes: Vec = to_bytes![array].unwrap(); - assert_eq!(&bytes, &[]); + assert_eq!(&bytes, (&[] as &[u8; 0])); assert_eq!(bytes.len(), 0); } diff --git a/ec/src/hashing/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs similarity index 100% rename from ec/src/hashing/field_hashers/expander/mod.rs rename to ff/src/fields/field_hashers/expander/mod.rs diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json b/ff/src/fields/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json similarity index 100% rename from ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json rename to ff/src/fields/field_hashers/expander/testdata/expand_message_xmd_SHA256_256.json diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json b/ff/src/fields/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json similarity index 100% rename from ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json rename to ff/src/fields/field_hashers/expander/testdata/expand_message_xmd_SHA256_38.json diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json b/ff/src/fields/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json similarity index 100% rename from ec/src/hashing/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json rename to ff/src/fields/field_hashers/expander/testdata/expand_message_xmd_SHA512_38.json diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json b/ff/src/fields/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json similarity index 100% rename from ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json rename to ff/src/fields/field_hashers/expander/testdata/expand_message_xof_SHAKE128_256.json diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json b/ff/src/fields/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json similarity index 100% rename from ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json rename to ff/src/fields/field_hashers/expander/testdata/expand_message_xof_SHAKE128_36.json diff --git a/ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json b/ff/src/fields/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json similarity index 100% rename from ec/src/hashing/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json rename to ff/src/fields/field_hashers/expander/testdata/expand_message_xof_SHAKE256_36.json diff --git a/ec/src/hashing/field_hashers/expander/tests.rs b/ff/src/fields/field_hashers/expander/tests.rs similarity index 97% rename from ec/src/hashing/field_hashers/expander/tests.rs rename to ff/src/fields/field_hashers/expander/tests.rs index 9ea003454..c8274f377 100644 --- a/ec/src/hashing/field_hashers/expander/tests.rs +++ b/ff/src/fields/field_hashers/expander/tests.rs @@ -33,7 +33,7 @@ fn expander() { let args = Arguments::from_args(); let mut tests = Vec::>::new(); - for filename in read_dir("./src/hashing/field_hashers/expander/testdata").unwrap() { + for filename in read_dir("./src/fields/field_hashers/expander/testdata").unwrap() { let ff = filename.unwrap(); let file = File::open(ff.path()).unwrap(); let u: ExpanderVector = serde_json::from_reader(BufReader::new(file)).unwrap(); diff --git a/ec/src/hashing/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs similarity index 73% rename from ec/src/hashing/field_hashers/mod.rs rename to ff/src/fields/field_hashers/mod.rs index 86360e246..46f080ad7 100644 --- a/ec/src/hashing/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -1,13 +1,27 @@ mod expander; -use ark_ff::{Field, PrimeField}; -use crate::hashing::{ - field_hashers::expander::ExpanderXmd, map_to_curve_hasher::*, HashToCurveError, -}; +use crate::{Field, PrimeField}; + use ark_std::vec::Vec; use digest::DynDigest; use expander::Expander; +use self::expander::ExpanderXmd; + +/// Trait for hashing messages to field elements. +pub trait HashToField: Sized { + /// Initialises a new hash-to-field helper struct. + /// + /// # Arguments + /// + /// * `domain` - bytes that get concatenated with the `msg` during hashing, in order to separate potentially interfering instantiations of the hasher. + /// * `count` - number of elements in field `F` to output. + fn new(domain: &[u8]) -> Self; + + /// Hash an arbitrary `msg` to #`count` elements from field `F`. + fn hash_to_field(&self, msg: &[u8], count: usize) -> Vec; +} + /// This field hasher constructs a Hash-To-Field based on a fixed-output hash function, /// like SHA2, SHA3 or Blake2. /// The implementation aims to follow the specification in [Hashing to Elliptic Curves (draft)](https://tools.ietf.org/pdf/draft-irtf-cfrg-hash-to-curve-13.pdf). @@ -16,12 +30,11 @@ use expander::Expander; /// /// ``` /// use ark_test_curves::bls12_381::Fq; -/// use ark_ec::hashing::field_hashers::DefaultFieldHasher; +/// use ark_ff::fields::field_hashers::{DefaultFieldHasher, HashToField}; /// use sha2::Sha256; -/// use crate::ark_ec::hashing::map_to_curve_hasher::HashToField; /// -/// let hasher = as HashToField>::new(&[1, 2, 3]).unwrap(); -/// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2).unwrap(); +/// let hasher = as HashToField>::new(&[1, 2, 3]); +/// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2); /// /// assert_eq!(field_elements.len(), 2); /// ``` @@ -33,7 +46,7 @@ pub struct DefaultFieldHasher HashToField for DefaultFieldHasher { - fn new(dst: &[u8]) -> Result { + fn new(dst: &[u8]) -> Self { // The final output of `hash_to_field` will be an array of field // elements from F::BaseField, each of size `len_per_elem`. let len_per_base_elem = get_len_per_elem::(); @@ -44,13 +57,13 @@ impl HashToFie block_size: len_per_base_elem, }; - Ok(DefaultFieldHasher { + DefaultFieldHasher { expander, len_per_base_elem, - }) + } } - fn hash_to_field(&self, message: &[u8], count: usize) -> Result, HashToCurveError> { + fn hash_to_field(&self, message: &[u8], count: usize) -> Vec { let m = F::extension_degree() as usize; // The user imposes a `count` of elements of F_p^m to output per input msg, @@ -73,14 +86,14 @@ impl HashToFie output.push(f); } - Ok(output) + output } } -// This function computes the length in bytes that a hash function should output -// for hashing `count` field elements. -// See section 5.1 and 5.3 of the -// [IETF hash standardization draft](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10) +/// This function computes the length in bytes that a hash function should output +/// for hashing `count` field elements. +/// See section 5.1 and 5.3 of the +/// [IETF hash standardization draft](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10) fn get_len_per_elem() -> usize { // ceil(log(p)) let base_field_size_in_bits = F::BasePrimeField::MODULUS_BIT_SIZE as usize; diff --git a/ff/src/fields/mod.rs b/ff/src/fields/mod.rs index b8fcd8293..e63bb9d14 100644 --- a/ff/src/fields/mod.rs +++ b/ff/src/fields/mod.rs @@ -26,6 +26,8 @@ pub mod arithmetic; pub mod models; pub use self::models::*; +pub mod field_hashers; + #[cfg(feature = "parallel")] use ark_std::cmp::max; #[cfg(feature = "parallel")] From dd494c6e83e267c8dd860ba61312de613320a7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Mon, 9 May 2022 11:48:19 +0200 Subject: [PATCH 24/56] Update doc comment for `get_len_per_elem` --- ff/src/fields/field_hashers/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index 46f080ad7..3e8a10312 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -91,9 +91,9 @@ impl HashToFie } /// This function computes the length in bytes that a hash function should output -/// for hashing `count` field elements. +/// for hashing an element of type `Field`. /// See section 5.1 and 5.3 of the -/// [IETF hash standardization draft](https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10) +/// [IETF hash standardization draft](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/) fn get_len_per_elem() -> usize { // ceil(log(p)) let base_field_size_in_bits = F::BasePrimeField::MODULUS_BIT_SIZE as usize; From e8f91d4e6b3a0421c0891e012e6ea5eecfd1597f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Mon, 9 May 2022 11:52:22 +0200 Subject: [PATCH 25/56] Remove gen_len_per_elem test --- ff/src/fields/field_hashers/mod.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index 3e8a10312..c4f005b5d 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -104,17 +104,3 @@ fn get_len_per_elem() -> usize { ((base_field_size_with_security_padding_in_bits + 7) / 8) as u64; bytes_per_base_field_elem as usize } - -#[cfg(test)] -mod hasher_tests { - use super::*; - use ark_test_curves::bls12_381::{Fq, Fq2}; - - #[test] - fn test_get_len_per_elem() { - let fq_len = get_len_per_elem::(); - let fq2_len = get_len_per_elem::(); - assert_eq!(fq_len, fq2_len); - assert_eq!(fq_len, 64); - } -} From ef5b411cd7eac26ed976145dc5ddf353168d8a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Mon, 9 May 2022 12:16:38 +0200 Subject: [PATCH 26/56] Remove unused imports from ec --- ec/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/ec/Cargo.toml b/ec/Cargo.toml index 8103ad4c3..de0197472 100644 --- a/ec/Cargo.toml +++ b/ec/Cargo.toml @@ -19,16 +19,13 @@ ark-serialize = { version = "^0.3.0", path = "../serialize", default-features = ark-ff = { version = "^0.3.0", path = "../ff", default-features = false } ark-poly = { version = "^0.3.0", path = "../poly", default-features = false } derivative = { version = "2", features = ["use_core"] } -digest = { version = "0.10", default-features = false , features = ["alloc"] } num-traits = { version = "0.2", default-features = false } rayon = { version = "1", optional = true } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } hashbrown = "0.11.2" [dev-dependencies] -blake2 = { version = "0.10", default-features = false } ark-test-curves = { version = "^0.3.0", path = "../test-curves", default-features = false, features = ["bls12_381_curve"] } -sha3 = { version = "0.10", default-features = false } sha2 = { version = "0.10", default-features = false } libtest-mimic = "0.3.0" serde = "1.0.110" From f618bc6da4ab7f724fdbea4bc87160b959d8436c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Tue, 10 May 2022 13:36:25 +0200 Subject: [PATCH 27/56] assert the iso generator is actually on curve --- ec/src/hashing/curve_maps/wb/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index 8fa8492b4..2098d025d 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -65,6 +65,10 @@ impl MapToCurve> for WBMap

{ P::IsogenousCurve::AFFINE_GENERATOR_COEFFS.1, false, ); + assert!( + isogenous_curve_generator.is_on_curve(), + "generator not on curve" + ); match P::isogeny_map(isogenous_curve_generator) { Ok(point_on_curve) => { From 52cd8986474cfed3df7f42405ec655bf4abf8c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Tue, 10 May 2022 13:57:38 +0200 Subject: [PATCH 28/56] Use a correct generator and curve params --- test-curves/src/bls12_381/g1_swu_iso.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs index c02fce5ed..75d2cd5fe 100644 --- a/test-curves/src/bls12_381/g1_swu_iso.rs +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -30,8 +30,7 @@ impl ModelParameters for SwuIsoParameters { // - B' = 2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280 // * Z: 11 impl SWModelParameters for SwuIsoParameters { - //const COEFF_A: Fq = MontFp!(Fq, "012190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677"); //sage doesn't approve of this - const COEFF_A: Fq = MontFp!(Fq, "2858613208430792460670318198342879349494999260436483523154854961351063857243634726019465176474256126859776719994977"); + const COEFF_A: Fq = MontFp!(Fq, "12190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677"); //sage doesn't approve of this #[rustfmt::skip] const COEFF_B: Fq = MontFp!(Fq, "2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280"); @@ -64,8 +63,8 @@ impl SWUParams for SwuIsoParameters { /// G1_GENERATOR_X = #[rustfmt::skip] -pub const G1_GENERATOR_X: Fq = MontFp!(Fq, "628127623378585612843095022119507708025289394540669560027004601611569871267541856210323712812047239723504248810248"); +pub const G1_GENERATOR_X: Fq = MontFp!(Fq, "1020232295111649411126762359530270833151925872915888263107080350435116244445972822132949957555221231229957568042978"); /// G1_GENERATOR_Y = #[rustfmt::skip] -pub const G1_GENERATOR_Y: Fq = MontFp!(Fq, "344075650239127142968089520704786925624745533124141202280424406752399324209523628375922007963596482424831722220273"); +pub const G1_GENERATOR_Y: Fq = MontFp!(Fq, "572738012940399893876716047881377207991025392386390068007901896139525257801331726850963609787517204283814804267188"); From 6e23a9989bf06855f6482517947e6f14de68db87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 10:40:25 +0200 Subject: [PATCH 29/56] Update the isogeny map params to match the draft --- test-curves/src/bls12_381/g1.rs | 102 ++++++++++++++++---------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/test-curves/src/bls12_381/g1.rs b/test-curves/src/bls12_381/g1.rs index 9d9c11135..f6523c3f4 100644 --- a/test-curves/src/bls12_381/g1.rs +++ b/test-curves/src/bls12_381/g1.rs @@ -47,69 +47,69 @@ impl WBParams for Parameters { type IsogenousCurve = SwuIsoParameters; const PHI_X_NOM: &'static [::BaseField] = &[ - MontFp!(Fq, "3761822637321485742094536206199512035685972329360337092690555528605752326213440950527352563934445837165125977345128"), - MontFp!(Fq, "1582172990273894682725716146256297593851554078446457591584154223376480866715343525953458444978680215440412886996200"), - MontFp!(Fq, "2051387046688339481714726479723076305756384619135044672831882917686431912682625619320120082313093891743187631791280"), - MontFp!(Fq, "61316326124367244515865706164471217084261738749879925739220878889304439271692421994859529859373651892126645952478"), - MontFp!(Fq, "1424741831220874356476333227468129624471472782807764018784263716426284995285578915327628560152704910696985638070031"), - MontFp!(Fq, "3415427104483187489859740871640064348492611444552862448295571438270821994900526625562705192993481400731539293415811"), - MontFp!(Fq, "248188830067800966021611907001049410443171766148926993624301072093542166689921157756350157715209127315556469919811"), - MontFp!(Fq, "2458049485161426253398308320890830930555526088324701597510592431647721369610314802890725095474874074634194669518436"), - MontFp!(Fq, "1239271775787030039269460763652455868148971086016832054354147730155061349388626624328773377658494412538595239256855"), - MontFp!(Fq, "698396551686164607792478797181335970223204059946034999723234339823539961139901150842584755596191372859677741313422"), - MontFp!(Fq, "2756657124183929639940341559332863560985099912924783743137983687385942647530234634138642360072966950403354118194880"), + MontFp!(Fq, "2712959285290305970661081772124144179193819192423276218370281158706191519995889425075952244140278856085036081760695"), + MontFp!(Fq, "3564859427549639835253027846704205725951033235539816243131874237388832081954622352624080767121604606753339903542203"), + MontFp!(Fq, "2051387046688339481714726479723076305756384619135044672831882917686431912682625619320120082313093891743187631791280"), + MontFp!(Fq, "3612713941521031012780325893181011392520079402153354595775735142359240110423346445050803899623018402874731133626465"), + MontFp!(Fq, "2247053637822768981792833880270996398470828564809439728372634811976089874056583714987807553397615562273407692740057"), + MontFp!(Fq, "3415427104483187489859740871640064348492611444552862448295571438270821994900526625562705192993481400731539293415811"), + MontFp!(Fq, "2067521456483432583860405634125513059912765526223015704616050604591207046392807563217109432457129564962571408764292"), + MontFp!(Fq, "3650721292069012982822225637849018828271936405382082649291891245623305084633066170122780668657208923883092359301262"), + MontFp!(Fq, "1239271775787030039269460763652455868148971086016832054354147730155061349388626624328773377658494412538595239256855"), + MontFp!(Fq, "3479374185711034293956731583912244564891370843071137483962415222733470401948838363051960066766720884717833231600798"), + MontFp!(Fq, "2492756312273161536685660027440158956721981129429869601638362407515627529461742974364729223659746272460004902959995"), MontFp!(Fq, "1058488477413994682556770863004536636444795456512795473806825292198091015005841418695586811009326456605062948114985"), ]; const PHI_X_DEN: &'static [::BaseField] = &[ - MontFp!(Fq, "3949438676361386880769263910006560135979986067074971624024178233787093666769860448538216069627988502376148329127381"), - MontFp!(Fq, "2822220997908397120956501031591772354860004534930174057793539372552395729721474912921980407622851861692773516917759"), - MontFp!(Fq, "610552060666338680048265043345785271200283516960578188721887711701602621050421759883463448407237338290466946893545"), - MontFp!(Fq, "2439329436782028399166625708751323253248871941520474623095864400521929929188290312899217468935910181179336068540275"), - MontFp!(Fq, "3025903087998593826923738290305187197829899948335370692927241015584233559365859980023579293766193297662657497834014"), - MontFp!(Fq, "2787329879967655380381218769366715121683732401785552165471280254930041329235866427760690206934082971711204373036769"), - MontFp!(Fq, "3729460208364303450659860043245117836792062818643913458168515950720008978604972045673944667221729675671707946923021"), - MontFp!(Fq, "3179090966864399634396993677377903383656908036827452986467581478509513058347781039562481806409014718357094150199902"), - MontFp!(Fq, "684141363729077267665842443966270070725528746651574246973574894998264196269884726340959705960779078660850485681497"), - MontFp!(Fq, "1355518942857092779104773143196445884975815408961178437135200875404433360418847982032652351120700883660623679118159"), + MontFp!(Fq, "1353092447850172218905095041059784486169131709710991428415161466575141675351394082965234118340787683181925558786844"), + MontFp!(Fq, "2822220997908397120956501031591772354860004534930174057793539372552395729721474912921980407622851861692773516917759"), + MontFp!(Fq, "1717937747208385987946072944131378949849282930538642983149296304709633281382731764122371874602115081850953846504985"), + MontFp!(Fq, "501624051089734157816582944025690868317536915684467868346388760435016044027032505306995281054569109955275640941784"), + MontFp!(Fq, "3025903087998593826923738290305187197829899948335370692927241015584233559365859980023579293766193297662657497834014"), + MontFp!(Fq, "2224140216975189437834161136818943039444741035168992629437640302964164227138031844090123490881551522278632040105125"), + MontFp!(Fq, "1146414465848284837484508420047674663876992808692209238763293935905506532411661921697047880549716175045414621825594"), + MontFp!(Fq, "3179090966864399634396993677377903383656908036827452986467581478509513058347781039562481806409014718357094150199902"), + MontFp!(Fq, "1549317016540628014674302140786462938410429359529923207442151939696344988707002602944342203885692366490121021806145"), + MontFp!(Fq, "1442797143427491432630626390066422021593505165588630398337491100088557278058060064930663878153124164818522816175370"), MontFp!(Fq, "1"), ]; const PHI_Y_NOM: &'static [::BaseField] = &[ - MontFp!(Fq, "1393399195776646641963150658816615410692049723305861307490980409834842911816308830479576739332720113414154429643571"), - MontFp!(Fq, "1511190695657960398963160955727174407082178148587899660611396357887273149842318573217989398009716786569780748006283"), - MontFp!(Fq, "3614401657395238041642341964430562932885284129837437306094802414995585690467848276262207178353676484330879154111757"), - MontFp!(Fq, "303251954782077855462083823228569901064301365507057490567314302006681283228886645653148231378803311079384246777035"), - MontFp!(Fq, "3668073836642475590306080768959183669825119857553168245915502992504527111582288680993272182771099907781295865642364"), - MontFp!(Fq, "889147988023366972622306341891649433228352963186679791369365907311293432508530696403569262531255821940400079347315"), - MontFp!(Fq, "718493410301850496156792713845282235942975872282052335612908458061560958159410402177452633054233549648465863759602"), - MontFp!(Fq, "3406136881215263818934773248465685844790898101337646888092845387936582793628141067747381197872508534868489799639699"), - MontFp!(Fq, "331351138484847160772695176511692246547145983117580056167533060034011313825061073939286437522432693033324549699722"), - MontFp!(Fq, "2171468288973248519912068884667133903101171670397991979582205855298465414047741472281361964966463442016062407908400"), - MontFp!(Fq, "2092842804947501956457889650155528390118620253793900717919970123642236515732658355049092877407901587228724229223110"), - MontFp!(Fq, "3961890550435212003631878720741046102282781357458395684082291998816751808643768526367549852177588213715211235373916"), - MontFp!(Fq, "1707589313757812493102695021134258021969283151093981498394095062397393499601961942449581422761005023512037430861560"), - MontFp!(Fq, "1967501030954114997918812128990512798136077044765138085902549248681331523022349398587390395919802044865687181234417"), - MontFp!(Fq, "2922895688438869655803185556286420403397802691723657346548307498540648684066474272936979722182960006715481007746439"), + MontFp!(Fq, "1393399195776646641963150658816615410692049723305861307490980409834842911816308830479576739332720113414154429643571"), + MontFp!(Fq, "2968610969752762946134106091152102846225411740689724909058016729455736597929366401532929068084731548131227395540630"), + MontFp!(Fq, "122933100683284845219599644396874530871261396084070222155796123161881094323788483360414289333111221370374027338230"), + MontFp!(Fq, "303251954782077855462083823228569901064301365507057490567314302006681283228886645653148231378803311079384246777035"), + MontFp!(Fq, "1353972356724735644398279028378555627591260676383150667237975415318226973994509601413730187583692624416197017403099"), + MontFp!(Fq, "3443977503653895028417260979421240655844034880950251104724609885224259484262346958661845148165419691583810082940400"), + MontFp!(Fq, "718493410301850496156792713845282235942975872282052335612908458061560958159410402177452633054233549648465863759602"), + MontFp!(Fq, "1466864076415884313141727877156167508644960317046160398342634861648153052436926062434809922037623519108138661903145"), + MontFp!(Fq, "1536886493137106337339531461344158973554574987550750910027365237255347020572858445054025958480906372033954157667719"), + MontFp!(Fq, "2171468288973248519912068884667133903101171670397991979582205855298465414047741472281361964966463442016062407908400"), + MontFp!(Fq, "3915937073730221072189646057898966011292434045388986394373682715266664498392389619761133407846638689998746172899634"), + MontFp!(Fq, "3802409194827407598156407709510350851173404795262202653149767739163117554648574333789388883640862266596657730112910"), + MontFp!(Fq, "1707589313757812493102695021134258021969283151093981498394095062397393499601961942449581422761005023512037430861560"), + MontFp!(Fq, "349697005987545415860583335313370109325490073856352967581197273584891698473628451945217286148025358795756956811571"), + MontFp!(Fq, "885704436476567581377743161796735879083481447641210566405057346859953524538988296201011389016649354976986251207243"), MontFp!(Fq, "3370924952219000111210625390420697640496067348723987858345031683392215988129398381698161406651860675722373763741188"), ]; const PHI_Y_DEN: &'static [::BaseField] = &[ - MontFp!(Fq, "3396434800020507717552209507749485772788165484415495716688989613875369612529138640646200921379825018840894888371137"), - MontFp!(Fq, "3955937245707125245654875920344947126613343076099634862876498453376019064171085472617926084668015244086355452990926"), - MontFp!(Fq, "3115801080798375384198119675359305198682407447857559059827677597200837822471239996878963936531572341910295439078930"), - MontFp!(Fq, "3496628876382137961119423566187258795236027183112131017519536056628828830323846696121917502443333849318934945158166"), - MontFp!(Fq, "3819161294135653749488194485080848928281288158623143986707267064691105653307717275066596854814679462226419882338445"), - MontFp!(Fq, "3838344850882296394939911407571260624820518547352197287854517462270146783414326660145944161947898461843919024387456"), - MontFp!(Fq, "3443845896188810583748698342858554856823966611538932245284665132724280883115455093457486044009395063504744802318172"), - MontFp!(Fq, "1189518655724056699355159955938426141594501095232997073362878098547301776615800227099534760471261853454585261625212"), - MontFp!(Fq, "2309935917761931164183799788994195243166135866798971442738101234750394172839060646960604788222384454747599044244610"), - MontFp!(Fq, "3459661102222301807083870307127272890283709299202626530836335779816726101522661683404130556379097384249447658110805"), - MontFp!(Fq, "3898950452492751420431682235553362135160293985934212849206350896691847297403795877806915602445207834970900272834330"), - MontFp!(Fq, "2381968764806454673720955440620228057919683152985846777578004069901421179563597288802750793515266450448328892335136"), - MontFp!(Fq, "1668238650112823419388205992952852912407572045257706138925379268508860023191233729074751042562151098884528280913356"), - MontFp!(Fq, "939263815598411948154903329612610969504805630387130456691588334780964163089645546614263028349325528011160458395367"), - MontFp!(Fq, "32073636674805471948264801926716749185281703472263713036772245044634215382853040827634712116543493471988382397345"), + MontFp!(Fq, "3396434800020507717552209507749485772788165484415495716688989613875369612529138640646200921379825018840894888371137"), + MontFp!(Fq, "3907278185868397906991868466757978732688957419873771881240086730384895060595583602347317992689443299391009456758845"), + MontFp!(Fq, "854914566454823955479427412036002165304466268547334760894270240966182605542146252771872707010378658178126128834546"), + MontFp!(Fq, "3496628876382137961119423566187258795236027183112131017519536056628828830323846696121917502443333849318934945158166"), + MontFp!(Fq, "1828256966233331991927609917644344011503610008134915752990581590799656305331275863706710232159635159092657073225757"), + MontFp!(Fq, "1362317127649143894542621413133849052553333099883364300946623208643344298804722863920546222860227051989127113848748"), + MontFp!(Fq, "3443845896188810583748698342858554856823966611538932245284665132724280883115455093457486044009395063504744802318172"), + MontFp!(Fq, "3484671274283470572728732863557945897902920439975203610275006103818288159899345245633896492713412187296754791689945"), + MontFp!(Fq, "3755735109429418587065437067067640634211015783636675372165599470771975919172394156249639331555277748466603540045130"), + MontFp!(Fq, "3459661102222301807083870307127272890283709299202626530836335779816726101522661683404130556379097384249447658110805"), + MontFp!(Fq, "742483168411032072323733249644347333168432665415341249073150659015707795549260947228694495111018381111866512337576"), + MontFp!(Fq, "1662231279858095762833829698537304807741442669992646287950513237989158777254081548205552083108208170765474149568658"), + MontFp!(Fq, "1668238650112823419388205992952852912407572045257706138925379268508860023191233729074751042562151098884528280913356"), + MontFp!(Fq, "369162719928976119195087327055926326601627748362769544198813069133429557026740823593067700396825489145575282378487"), + MontFp!(Fq, "2164195715141237148945939585099633032390257748382945597506236650132835917087090097395995817229686247227784224263055"), MontFp!(Fq, "1"), ]; } From 2281ccf401432d4fd680e3d93354360eaae025e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 11:30:02 +0200 Subject: [PATCH 30/56] only negate `y` if parity(u) != parity(y) --- ec/src/hashing/curve_maps/swu/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index 39d6ac576..1f80d6bab 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -164,7 +164,7 @@ impl MapToCurve> for SWUMap

{ let y = if gx1_square { y1 } else { y2 }; let x_affine = num_x / div; - let y_affine = if parity(&y) { -y } else { y }; + let y_affine = if parity(&y) != parity(&point) { -y } else { y }; let point_on_curve = GroupAffine::

::new(x_affine, y_affine, false); assert!( point_on_curve.is_on_curve(), From 4fdba020837c27e47ff4f94d17fb0c4ad2b8a32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 11:36:27 +0200 Subject: [PATCH 31/56] Adapt parity method to be compatible for all `m` - originally would return the oddness of first non-zero element - adapted so that it returns true if AT LEAST one of the base field elements is odd --- ec/src/hashing/curve_maps/swu/mod.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index 1f80d6bab..aec4e2074 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -34,10 +34,15 @@ pub struct SWUMap { /// /// - [\[1\]] pub fn parity(element: &F) -> bool { - element - .to_base_prime_field_elements() - .find(|&x| !x.is_zero()) - .map_or(false, |x| x.into_bigint().is_odd()) + let mut sign = false; + let mut zero = true; + for elem in element.to_base_prime_field_elements() { + let sign_i = elem.into_bigint().is_odd(); + let zero_i = elem.is_zero(); + sign = sign || (zero && sign_i); + zero = zero && zero_i; + } + sign } impl MapToCurve> for SWUMap

{ From 9a4077ca47bd8ba19f25a2d8eb17c299fbd34e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 11:37:52 +0200 Subject: [PATCH 32/56] Simplify reading an fq_vec with a helper method --- ec/src/hashing/tests/suites.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 66d75c3e1..9b41259e0 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -64,9 +64,7 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { let want: Vec = (&v.u) .into_iter() .map(|x| { - x.split(",").map(|f| { - Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap()) - }) + read_fq_vec(x) }) .flatten() .collect(); @@ -83,14 +81,8 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { // then, test curve points let got: GroupAffine = mapper.hash(&v.msg.as_bytes()).unwrap(); assert!(got.is_on_curve()); - let x: Vec = (&v.p.x) - .split(",") - .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) - .collect(); - let y: Vec = (&v.p.y) - .split(",") - .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) - .collect(); + let x: Vec = read_fq_vec(&v.p.x); + let y: Vec = read_fq_vec(&v.p.y); let want: GroupAffine = GroupAffine::::new(x[0], y[0], false); assert!(want.is_on_curve()); if got != want { @@ -106,3 +98,9 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { } Outcome::Passed } + +fn read_fq_vec(input: &String) -> Vec { + input.split(",") + .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) + .collect() +} From 9dbdc4007dea752a7518462c0d39769b5b7b916b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 11:39:14 +0200 Subject: [PATCH 33/56] Use a COFACTOR param from the draft for G1 --- test-curves/src/bls12_381/g1.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-curves/src/bls12_381/g1.rs b/test-curves/src/bls12_381/g1.rs index f6523c3f4..5c903ea32 100644 --- a/test-curves/src/bls12_381/g1.rs +++ b/test-curves/src/bls12_381/g1.rs @@ -17,7 +17,7 @@ impl ModelParameters for Parameters { type ScalarField = Fr; /// COFACTOR = (x - 1)^2 / 3 = 76329603384216526031706109802092473003 - const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156]; + const COFACTOR: &'static [u64] = &[0xd201000000010001]; /// COFACTOR_INV = COFACTOR^{-1} mod r /// = 52435875175126190458656871551744051925719901746859129887267498875565241663483 From 572f16cba67b7196efd47a69b6eba1f933fd6fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 12:43:36 +0200 Subject: [PATCH 34/56] Bring fq12 and g2 from bls12-381 to test-curves --- test-curves/src/bls12_381/fq12.rs | 76 ++++++++++++++++ test-curves/src/bls12_381/g2.rs | 145 ++++++++++++++++++++++++++++++ test-curves/src/bls12_381/mod.rs | 27 +++++- 3 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 test-curves/src/bls12_381/fq12.rs create mode 100644 test-curves/src/bls12_381/g2.rs diff --git a/test-curves/src/bls12_381/fq12.rs b/test-curves/src/bls12_381/fq12.rs new file mode 100644 index 000000000..6bb539ae4 --- /dev/null +++ b/test-curves/src/bls12_381/fq12.rs @@ -0,0 +1,76 @@ +use crate::bls12_381::*; +use ark_ff::{MontFp, QuadExt, CubicExt, fields::*}; + +pub type Fq12 = Fp12; + +#[derive(Clone, Copy)] +pub struct Fq12Config; + +impl Fp12Config for Fq12Config { + type Fp6Config = Fq6Config; + + const NONRESIDUE: Fq6 = CubicExt!(FQ2_ZERO, FQ2_ONE, FQ2_ZERO); + + const FROBENIUS_COEFF_FP12_C1: &'static [Fq2] = &[ + // Fp2::NONRESIDUE^(((q^0) - 1) / 6) + QuadExt!( + MontFp!(Fq, "1"), + MontFp!(Fq, "0"), + ), + // Fp2::NONRESIDUE^(((q^1) - 1) / 6) + QuadExt!( + MontFp!(Fq, "3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760"), + MontFp!(Fq, "151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027"), + ), + // Fp2::NONRESIDUE^(((q^2) - 1) / 6) + QuadExt!( + MontFp!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351"), + MontFp!(Fq, "0"), + ), + // Fp2::NONRESIDUE^(((q^3) - 1) / 6) + QuadExt!( + MontFp!(Fq, "2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"), + MontFp!(Fq, "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"), + ), + // Fp2::NONRESIDUE^(((q^4) - 1) / 6) + QuadExt!( + MontFp!(Fq, "793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350"), + MontFp!(Fq, "0"), + ), + // Fp2::NONRESIDUE^(((q^5) - 1) / 6) + QuadExt!( + MontFp!(Fq, "3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557"), + MontFp!(Fq, "877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230"), + ), + // Fp2::NONRESIDUE^(((q^6) - 1) / 6) + QuadExt!( + MontFp!(Fq, "-1"), + MontFp!(Fq, "0"), + ), + // Fp2::NONRESIDUE^(((q^7) - 1) / 6) + QuadExt!( + MontFp!(Fq, "151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027"), + MontFp!(Fq, "3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760"), + ), + // Fp2::NONRESIDUE^(((q^8) - 1) / 6) + QuadExt!( + MontFp!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"), + MontFp!(Fq, "0"), + ), + // Fp2::NONRESIDUE^(((q^9) - 1) / 6) + QuadExt!( + MontFp!(Fq, "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257"), + MontFp!(Fq, "2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"), + ), + // Fp2::NONRESIDUE^(((q^10) - 1) / 6) + QuadExt!( + MontFp!(Fq, "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437"), + MontFp!(Fq, "0"), + ), + // Fp2::NONRESIDUE^(((q^11) - 1) / 6) + QuadExt!( + MontFp!(Fq, "877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230"), + MontFp!(Fq, "3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557"), + ), + ]; +} diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs new file mode 100644 index 000000000..85cee71b4 --- /dev/null +++ b/test-curves/src/bls12_381/g2.rs @@ -0,0 +1,145 @@ +use crate::bls12_381::*; +use ark_ec::{ + bls12, + models::{ModelParameters, SWModelParameters}, + short_weierstrass_jacobian::GroupAffine, + AffineCurve, +}; +use ark_ff::{MontFp, QuadExt, Field, Zero, BigInt}; + +pub type G2Affine = bls12::G2Affine; +pub type G2Projective = bls12::G2Projective; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct Parameters; + +impl ModelParameters for Parameters { + type BaseField = Fq2; + type ScalarField = Fr; + + /// COFACTOR = (x^8 - 4 x^7 + 5 x^6) - (4 x^4 + 6 x^3 - 4 x^2 - 4 x + 13) // + /// 9 + /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 + #[rustfmt::skip] + const COFACTOR: &'static [u64] = &[ + 0xcf1c38e31c7238e5, + 0x1616ec6e786f0c70, + 0x21537e293a6691ae, + 0xa628f1cb4d9e82ef, + 0xa68a205b2e5a7ddf, + 0xcd91de4547085aba, + 0x91d50792876a202, + 0x5d543a95414e7f1, + ]; + + /// COFACTOR_INV = COFACTOR^{-1} mod r + /// 26652489039290660355457965112010883481355318854675681319708643586776743290055 + #[rustfmt::skip] + const COFACTOR_INV: Fr = MontFp!( + Fr, + "26652489039290660355457965112010883481355318854675681319708643586776743290055" + ); +} + +impl SWModelParameters for Parameters { + /// COEFF_A = [0, 0] + const COEFF_A: Fq2 = QuadExt!(g1::Parameters::COEFF_A, g1::Parameters::COEFF_A,); + + /// COEFF_B = [4, 4] + const COEFF_B: Fq2 = QuadExt!(g1::Parameters::COEFF_B, g1::Parameters::COEFF_B,); + + /// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (G2_GENERATOR_X, G2_GENERATOR_Y); + + #[inline(always)] + fn mul_by_a(_: &Self::BaseField) -> Self::BaseField { + Self::BaseField::zero() + } + + fn is_in_correct_subgroup_assuming_on_curve(point: &G2Affine) -> bool { + // Algorithm from Section 4 of https://eprint.iacr.org/2021/1130. + // + // Checks that [p]P = [X]P + + let mut x_times_point = point.mul(BigInt::new([crate::bls12_381::Parameters::X[0], 0, 0, 0])); + if crate::bls12_381::Parameters::X_IS_NEGATIVE { + x_times_point = -x_times_point; + } + + let p_times_point = p_power_endomorphism(point); + + x_times_point.eq(&p_times_point) + } +} + +pub const G2_GENERATOR_X: Fq2 = QuadExt!(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); +pub const G2_GENERATOR_Y: Fq2 = QuadExt!(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); + +/// G2_GENERATOR_X_C0 = +/// 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 +#[rustfmt::skip] +pub const G2_GENERATOR_X_C0: Fq = MontFp!(Fq, "352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160"); + +/// G2_GENERATOR_X_C1 = +/// 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 +#[rustfmt::skip] +pub const G2_GENERATOR_X_C1: Fq = MontFp!(Fq, "3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758"); + +/// G2_GENERATOR_Y_C0 = +/// 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 +#[rustfmt::skip] +pub const G2_GENERATOR_Y_C0: Fq = MontFp!(Fq, "1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905"); + +/// G2_GENERATOR_Y_C1 = +/// 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582 +#[rustfmt::skip] +pub const G2_GENERATOR_Y_C1: Fq = MontFp!(Fq, "927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582"); + +// psi(x,y) = (x**p * PSI_X, y**p * PSI_Y) is the Frobenius composed +// with the quadratic twist and its inverse + +// PSI_X = 1/(u+1)^((p-1)/3) +pub const P_POWER_ENDOMORPHISM_COEFF_0 : Fq2 = QuadExt!( + FQ_ZERO, + MontFp!( + Fq, + "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437" + ) +); + +// PSI_Y = 1/(u+1)^((p-1)/2) +pub const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = QuadExt!( + MontFp!( + Fq, + "2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530"), + MontFp!( + Fq, + "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") +); + +pub fn p_power_endomorphism(p: &GroupAffine) -> GroupAffine { + // The p-power endomorphism for G2 is defined as follows: + // 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1). To map a point (x, y) in E' to (s, t) in E, + // one set s = x / ((u+1) ^ (1/3)), t = y / ((u+1) ^ (1/2)), because E: y^2 = x^3 + 4. + // 2. Apply the Frobenius endomorphism (s, t) => (s', t'), another point on curve E, + // where s' = s^p, t' = t^p. + // 3. Map the point from E back to E'; that is, + // one set x' = s' * ((u+1) ^ (1/3)), y' = t' * ((u+1) ^ (1/2)). + // + // To sum up, it maps + // (x,y) -> (x^p / ((u+1)^((p-1)/3)), y^p / ((u+1)^((p-1)/2))) + // as implemented in the code as follows. + + let mut res = *p; + res.x.frobenius_map(1); + res.y.frobenius_map(1); + + let tmp_x = res.x.clone(); + res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c1; + res.x.c1 = P_POWER_ENDOMORPHISM_COEFF_0.c1 * &tmp_x.c0; + res.y *= P_POWER_ENDOMORPHISM_COEFF_1; + + res +} + diff --git a/test-curves/src/bls12_381/mod.rs b/test-curves/src/bls12_381/mod.rs index 77da67848..81ebc2f48 100644 --- a/test-curves/src/bls12_381/mod.rs +++ b/test-curves/src/bls12_381/mod.rs @@ -1,5 +1,6 @@ pub mod fr; pub use fr::*; +use ark_ec::bls12::{Bls12, Bls12Parameters, TwistType}; #[cfg(feature = "bls12_381_curve")] pub mod fq; @@ -8,11 +9,33 @@ pub mod fq2; #[cfg(feature = "bls12_381_curve")] pub mod fq6; #[cfg(feature = "bls12_381_curve")] +pub mod fq12; +#[cfg(feature = "bls12_381_curve")] pub mod g1; #[cfg(feature = "bls12_381_curve")] pub mod g1_swu_iso; - #[cfg(feature = "bls12_381_curve")] -pub use {fq::*, fq2::*, fq6::*, g1::*, g1_swu_iso::*}; +pub mod g2; +#[cfg(feature = "bls12_381_curve")] +pub mod g2_swu_iso; +#[cfg(feature = "bls12_381_curve")] +pub use {fq::*, fq2::*, fq6::*, g1::*, g1_swu_iso::*, g2_swu_iso::*}; + #[cfg(test)] mod tests; + +pub type Bls12_381 = Bls12; + +pub struct Parameters; + +impl Bls12Parameters for Parameters { + const X: &'static [u64] = &[0xd201000000010000]; + const X_IS_NEGATIVE: bool = true; + const TWIST_TYPE: TwistType = TwistType::M; + type Fp = Fq; + type Fp2Config = Fq2Config; + type Fp6Config = Fq6Config; + type Fp12Config = Fq12Config; + type G1Parameters = self::g1::Parameters; + type G2Parameters = self::g2::Parameters; +} From 00cb0cb0fb9f0a1b67028c5874176cf1e8b481d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 13:58:19 +0200 Subject: [PATCH 35/56] Implement the isogeny traits for g2 --- test-curves/src/bls12_381/g2.rs | 62 +++++++++++++ test-curves/src/bls12_381/g2_swu_iso.rs | 115 ++++++++++++++++++++++++ test-curves/src/bls12_381/mod.rs | 2 +- 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 test-curves/src/bls12_381/g2_swu_iso.rs diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index 85cee71b4..7f0e4724c 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -4,6 +4,7 @@ use ark_ec::{ models::{ModelParameters, SWModelParameters}, short_weierstrass_jacobian::GroupAffine, AffineCurve, + hashing::curve_maps::wb::WBParams, }; use ark_ff::{MontFp, QuadExt, Field, Zero, BigInt}; @@ -143,3 +144,64 @@ pub fn p_power_endomorphism(p: &GroupAffine) -> GroupAffine::BaseField] = &[ + QuadExt!( + MontFp!(Fq, "889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542"), + MontFp!(Fq, "889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235542")), + QuadExt!( + MontFp!(Fq, "0"), + MontFp!(Fq, "2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706522")), + QuadExt!( + MontFp!(Fq, "2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706526"), + MontFp!(Fq, "1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853261")), + QuadExt!( + MontFp!(Fq, "3557697382419259905260257622876359250272784728834673675850718343221361467102966990615722337003569479144794908942033"), + MontFp!(Fq, "0")), + ]; + + const PHI_X_DEN: &'static [::BaseField] = &[ + QuadExt!( + MontFp!(Fq, "0"), + MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559715")), + QuadExt!( + MontFp!(Fq, "12"), + MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559775")), + QuadExt!( + MontFp!(Fq, "1"), + MontFp!(Fq, "0")), + ]; + + const PHI_Y_NOM: &'static [::BaseField] = &[ + QuadExt!( + MontFp!(Fq, "741186954670679146929220338099241510473496818507223682468899654837783638979784789711608820209076974821832272696229"), + MontFp!(Fq, "741186954670679146929220338099241510473496818507223682468899654837783638979784789711608820209076974821832272696229")), + QuadExt!( + MontFp!(Fq, "0"), + MontFp!(Fq, "3112985209616852417102725420016814343988686637730339466369378550318691283715096116788757044878123294251695545324269")), + QuadExt!( + MontFp!(Fq, "1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853263"), + MontFp!(Fq, "2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706524")), + QuadExt!( + MontFp!(Fq, "1185899127473086635086752540958786416757594909611557891950239447740453822367655663538574112334523159714931636314011"), + MontFp!(Fq, "0")), + ]; + + const PHI_Y_DEN: &'static [::BaseField] = &[ + QuadExt!( + MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559355"), + MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559355")), + QuadExt!( + MontFp!(Fq, "0"), + MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559571")), + QuadExt!( + MontFp!(Fq, "18"), + MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559769")), + QuadExt!( + MontFp!(Fq, "1"), + MontFp!(Fq, "0")), + ]; +} diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs new file mode 100644 index 000000000..2a59499cd --- /dev/null +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -0,0 +1,115 @@ +use crate::bls12_381::*; +use ark_ec::models::{ModelParameters, SWModelParameters}; +use ark_ff::{MontFp, QuadExt}; + +use ark_ec::hashing::curve_maps::swu::{SWUParams}; + +#[derive(Clone, Default, PartialEq, Eq)] +pub struct SwuIsoParameters; + +impl ModelParameters for SwuIsoParameters { + type BaseField = Fq2; + type ScalarField = Fr; + + //sage: g2_iso.codomain().order() == g2_iso.domain().order() + //True + /// COFACTOR = (x^8 - 4 x^7 + 5 x^6) - (4 x^4 + 6 x^3 - 4 x^2 - 4 x + 13) // + /// 9 + /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 + #[rustfmt::skip] + const COFACTOR: &'static [u64] = &[ + 0xbc69f08f2ee75b35, + 0x84c6a0ea91b35288, + 0x8e2a8e9145ad7689, + 0x986ff031508ffe13, + 0x29c2f178731db956, + 0xd82bf015d1212b02, + 0xec0ec69d7477c1ae, + 0x954cbc06689f6a35, + 0x9894c0adebbf6b4e, + 0x8020005aaa95551 + ]; + // const COFACTOR: &'static [u64] = &[ + // 0xcf1c38e31c7238e5, + // 0x1616ec6e786f0c70, + // 0x21537e293a6691ae, + // 0xa628f1cb4d9e82ef, + // 0xa68a205b2e5a7ddf, + // 0xcd91de4547085aba, + // 0x91d50792876a202, + // 0x5d543a95414e7f1, + // ]; + + /// COFACTOR_INV = COFACTOR^{-1} mod r + /// 26652489039290660355457965112010883481355318854675681319708643586776743290055 + #[rustfmt::skip] + const COFACTOR_INV: Fr = MontFp!(Fr, "26652489039290660355457965112010883481355318854675681319708643586776743290055"); + +} + +// https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/ +// Hashing to Elliptic Curves +// 8.8.2. BLS12-381 G2 +// * E': y'^2 = x'^3 + A' * x' + B', where +// +// - A' = 240 * I +// +// - B' = 1012 * (1 + I) +// +// * Z: -(2 + I) + +impl SWModelParameters for SwuIsoParameters { + /// COEFF_A = [240, 0] + const COEFF_A: Fq2 = QuadExt!(MontFp!(Fq, "0"), MontFp!(Fq, "240"),); + + /// COEFF_B = [1012, 1012] + const COEFF_B: Fq2 = QuadExt!(MontFp!(Fq, "1012"), MontFp!(Fq, "1012"),); + + /// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y) + const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = + (G2_GENERATOR_X, G2_GENERATOR_Y); + +} + +pub const G2_GENERATOR_X: Fq2 = QuadExt!(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); +pub const G2_GENERATOR_Y: Fq2 = QuadExt!(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); + +// sage: gen_p = E2p.random_point() +// sage: gen_p *= 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 +// sage: gen_p +// (3742867872338536021971219193407057626975566811775929228638115610845414823755734136602223916420662890679205212867815*X + 2008970337784971958599114573863246208442825790877271736434783886837659225024554344101831904846457859657000371883048 : 347020557560111175564150279686487416538085532798697633906066128669670325197422119639641125873165591545442034801173*X + 3002750085289950562156391971969303286031832683890522668239999505933394032768942051901168474820339778663917384775384 : 1) + +#[rustfmt::skip] +pub const G2_GENERATOR_X_C0: Fq = MontFp!(Fq, "2008970337784971958599114573863246208442825790877271736434783886837659225024554344101831904846457859657000371883048"); + +/// G2_GENERATOR_X_C1 = +#[rustfmt::skip] +pub const G2_GENERATOR_X_C1: Fq = MontFp!(Fq, "3742867872338536021971219193407057626975566811775929228638115610845414823755734136602223916420662890679205212867815"); + +/// G2_GENERATOR_Y_C0 = +#[rustfmt::skip] +pub const G2_GENERATOR_Y_C0: Fq = MontFp!(Fq, "3002750085289950562156391971969303286031832683890522668239999505933394032768942051901168474820339778663917384775384"); + +/// G2_GENERATOR_Y_C1 = +#[rustfmt::skip] +pub const G2_GENERATOR_Y_C1: Fq = MontFp!(Fq, "347020557560111175564150279686487416538085532798697633906066128669670325197422119639641125873165591545442034801173"); + +// sage: Fq2 = g2_iso.domain().base_field() +// sage: Fq2 +// Finite Field in X of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787^2 +// sage: Fq2.primitive_element() +// X + 2 +// sage: Zeta = _ +// sage: Zeta +// X + 2 +// sage: Xi = Fq2(-Fq2.gens()[0] - 2) +// sage: Xi == -Zeta +// True +// sage: (Xi/Zeta).square_root() +//X +impl SWUParams for SwuIsoParameters { + const XI : Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); //a nonsquare in Fq ietf standard + const ZETA: Fq2 = QuadExt!(MontFp!(Fq, "2"), MontFp!(Fq, "1"),); //arbitatry primitive root of unity (element) + const XI_ON_ZETA_SQRT: Fq2 = QuadExt!(MontFp!(Fq, "0"), MontFp!(Fq, "1"),); ////square root of THETA=Xi/Zeta + +} diff --git a/test-curves/src/bls12_381/mod.rs b/test-curves/src/bls12_381/mod.rs index 81ebc2f48..bbdc588bb 100644 --- a/test-curves/src/bls12_381/mod.rs +++ b/test-curves/src/bls12_381/mod.rs @@ -19,7 +19,7 @@ pub mod g2; #[cfg(feature = "bls12_381_curve")] pub mod g2_swu_iso; #[cfg(feature = "bls12_381_curve")] -pub use {fq::*, fq2::*, fq6::*, g1::*, g1_swu_iso::*, g2_swu_iso::*}; +pub use {fq::*, fq2::*, fq6::*, fq12::*, g1::*, g1_swu_iso::*, g2_swu_iso::*}; #[cfg(test)] mod tests; From a48b61e4ec8d6a2b9657150a3c8539f60c2d14c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 13:59:26 +0200 Subject: [PATCH 36/56] Adapt the test suites to run for both g1 & g2 Revert "Adapt parity method to be compatible for all `m`" This reverts commit 4fdba020837c27e47ff4f94d17fb0c4ad2b8a32c. --- ec/src/hashing/curve_maps/swu/mod.rs | 13 ++--- ec/src/hashing/tests/suites.rs | 81 ++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index aec4e2074..1f80d6bab 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -34,15 +34,10 @@ pub struct SWUMap { /// /// - [\[1\]] pub fn parity(element: &F) -> bool { - let mut sign = false; - let mut zero = true; - for elem in element.to_base_prime_field_elements() { - let sign_i = elem.into_bigint().is_odd(); - let zero_i = elem.is_zero(); - sign = sign || (zero && sign_i); - zero = zero && zero_i; - } - sign + element + .to_base_prime_field_elements() + .find(|&x| !x.is_zero()) + .map_or(false, |x| x.into_bigint().is_odd()) } impl MapToCurve> for SWUMap

{ diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 9b41259e0..27e119e46 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -10,8 +10,10 @@ use ark_test_curves::{ short_weierstrass_jacobian::GroupAffine, }; -use ark_ff::PrimeField; -use ark_test_curves::bls12_381::{Fq, Fq2, Parameters}; +use ark_ff::{Field, PrimeField}; +use ark_test_curves::bls12_381::{ + g1::Parameters as G1Parameters, g2::Parameters as G2Parameters, Fq, Fq2, +}; use sha2::Sha256; #[test] @@ -37,14 +39,18 @@ fn suites() { fn run_test_w(Test { data, .. }: &Test) -> Outcome { assert_eq!(data.hash, "sha256"); let dst = data.dst.as_bytes(); - let mapper; let hasher; let m; - // TODO: differentiate between G1 and G2 Params! - mapper = MapToCurveBasedHasher::< - GroupAffine, + let g1_mapper = MapToCurveBasedHasher::< + GroupAffine, + DefaultFieldHasher, + WBMap, + >::new(dst) + .unwrap(); + let g2_mapper = MapToCurveBasedHasher::< + GroupAffine, DefaultFieldHasher, - WBMap, + WBMap, >::new(dst) .unwrap(); match data.curve.as_str() { @@ -60,12 +66,11 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { } for v in data.vectors.iter() { + // first, hash-to-field tests let got: Vec = hasher.hash_to_field(&v.msg.as_bytes(), 2 * m); let want: Vec = (&v.u) .into_iter() - .map(|x| { - read_fq_vec(x) - }) + .map(|x| read_fq_vec(x)) .flatten() .collect(); if got != want { @@ -78,22 +83,52 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { )), }; } + // then, test curve points - let got: GroupAffine = mapper.hash(&v.msg.as_bytes()).unwrap(); - assert!(got.is_on_curve()); let x: Vec = read_fq_vec(&v.p.x); let y: Vec = read_fq_vec(&v.p.y); - let want: GroupAffine = GroupAffine::::new(x[0], y[0], false); - assert!(want.is_on_curve()); - if got != want { - return Outcome::Failed { - msg: Some(format!( - "Suite: {:?}\ngot: {:?}\nwant: {:?}", - data.ciphersuite, - got.to_string(), - want.to_string() - )), - }; + match data.curve.as_str() { + "BLS12-381 G1" => { + let got = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); + let want = GroupAffine::::new( + Fq::from_base_prime_field_elems(&x[..]).unwrap(), + Fq::from_base_prime_field_elems(&y[..]).unwrap(), + false, + ); + assert!(got.is_on_curve()); + assert!(want.is_on_curve()); + if got != want { + return Outcome::Failed { + msg: Some(format!( + "Suite: {:?}\ngot: {:?}\nwant: {:?}", + data.ciphersuite, + got.to_string(), + want.to_string() + )), + }; + } + }, + "BLS12-381 G2" => { + let got = g2_mapper.hash(&v.msg.as_bytes()).unwrap(); + let want = GroupAffine::::new( + Fq2::from_base_prime_field_elems(&x[..]).unwrap(), + Fq2::from_base_prime_field_elems(&y[..]).unwrap(), + false, + ); + assert!(got.is_on_curve()); + assert!(want.is_on_curve()); + if got != want { + return Outcome::Failed { + msg: Some(format!( + "Suite: {:?}\ngot: {:?}\nwant: {:?}", + data.ciphersuite, + got.to_string(), + want.to_string() + )), + }; + } + }, + _ => return Outcome::Ignored, } } Outcome::Passed From 14344350af67c6fa433bc76818035b79479fd8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 14:02:37 +0200 Subject: [PATCH 37/56] format --- ec/src/hashing/tests/suites.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 27e119e46..8a42c2134 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -135,7 +135,8 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { } fn read_fq_vec(input: &String) -> Vec { - input.split(",") - .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) - .collect() + input + .split(",") + .map(|f| Fq::from_be_bytes_mod_order(&hex::decode(f.trim_start_matches("0x")).unwrap())) + .collect() } From fc4e25d22c83e95ab3cb46fc882b618e08a01c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 11 May 2022 14:03:13 +0200 Subject: [PATCH 38/56] Update the cofactor for g2 --- test-curves/src/bls12_381/g2.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index 7f0e4724c..ae4a84fe0 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -23,14 +23,16 @@ impl ModelParameters for Parameters { /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 #[rustfmt::skip] const COFACTOR: &'static [u64] = &[ - 0xcf1c38e31c7238e5, - 0x1616ec6e786f0c70, - 0x21537e293a6691ae, - 0xa628f1cb4d9e82ef, - 0xa68a205b2e5a7ddf, - 0xcd91de4547085aba, - 0x91d50792876a202, - 0x5d543a95414e7f1, + 0xbc69f08f2ee75b35, + 0x84c6a0ea91b35288, + 0x8e2a8e9145ad7689, + 0x986ff031508ffe13, + 0x29c2f178731db956, + 0xd82bf015d1212b02, + 0xec0ec69d7477c1ae, + 0x954cbc06689f6a35, + 0x9894c0adebbf6b4e, + 0x8020005aaa95551 ]; /// COFACTOR_INV = COFACTOR^{-1} mod r From 9fa58bd94ace9e8f07bbe1748b00d7a048ffffeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Mon, 16 May 2022 15:46:26 +0200 Subject: [PATCH 39/56] Make the test suites more explicit provide intermediate values q0, q1 adapt tests to output of P,q0,q1 --- ec/src/hashing/curve_maps/swu/mod.rs | 2 +- ec/src/hashing/curve_maps/wb/mod.rs | 4 ++-- ec/src/hashing/map_to_curve_hasher.rs | 5 +++-- ec/src/hashing/mod.rs | 2 +- ec/src/hashing/tests/json.rs | 4 ++++ ec/src/hashing/tests/suites.rs | 31 +++++++++++++++++++++++---- 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index 1f80d6bab..16983550d 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -280,7 +280,7 @@ mod test { let hash_result = test_swu_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); assert!( - hash_result.is_on_curve(), + hash_result.0.is_on_curve(), "hash results into a point off the curve" ); } diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index 2098d025d..a1ece8fe1 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -308,12 +308,12 @@ mod test { let hash_result = test_wb_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); assert!( - hash_result.x != F127_ZERO && hash_result.y != F127_ZERO, + hash_result.0.x != F127_ZERO && hash_result.0.y != F127_ZERO, "we assume that not both a and b coefficienst are zero for the test curve" ); assert!( - hash_result.is_on_curve(), + hash_result.0.is_on_curve(), "hash results into a point off the curve" ); } diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index 4e4d8e5dd..359553157 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -47,7 +47,7 @@ where // traits. This uses the IETF hash to curve's specification for Random // oracle encoding (hash_to_curve) defined by combining these components. // See https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-09#section-3 - fn hash(&self, msg: &[u8]) -> Result { + fn hash(&self, msg: &[u8]) -> Result<(T, T, T), HashToCurveError> { // IETF spec of hash_to_curve, from hash_to_field and map_to_curve // sub-components // 1. u = hash_to_field(msg, 2) @@ -64,7 +64,8 @@ where let rand_curve_elem = rand_curve_elem_0 + rand_curve_elem_1; let rand_subgroup_elem = rand_curve_elem.mul_by_cofactor(); + // let rand_subgroup_elem = rand_curve_elem; - Ok(rand_subgroup_elem) + Ok((rand_subgroup_elem, rand_curve_elem_0, rand_curve_elem_1)) } } diff --git a/ec/src/hashing/mod.rs b/ec/src/hashing/mod.rs index 23901ea39..ba8dad708 100644 --- a/ec/src/hashing/mod.rs +++ b/ec/src/hashing/mod.rs @@ -13,7 +13,7 @@ pub trait HashToCurve: Sized { /// Produce a hash of the message, which also depends on the domain. /// The output of the hash is a curve point in the prime order subgroup /// of the given elliptic curve. - fn hash(&self, message: &[u8]) -> Result; + fn hash(&self, message: &[u8]) -> Result<(T, T, T), HashToCurveError>; } /// This is an error that could occur during the hash to curve process diff --git a/ec/src/hashing/tests/json.rs b/ec/src/hashing/tests/json.rs index 8f2694db1..1378d80b2 100644 --- a/ec/src/hashing/tests/json.rs +++ b/ec/src/hashing/tests/json.rs @@ -29,6 +29,10 @@ pub struct Map { pub struct Vector { #[serde(rename = "P")] pub p: P, + #[serde(rename = "Q0")] + pub q0: P, + #[serde(rename = "Q1")] + pub q1: P, pub msg: String, pub u: Vec, } diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 8a42c2134..4467eba73 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -87,9 +87,14 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { // then, test curve points let x: Vec = read_fq_vec(&v.p.x); let y: Vec = read_fq_vec(&v.p.y); + let x_q0: Vec = read_fq_vec(&v.q0.x); + let x_q1: Vec = read_fq_vec(&v.q1.x); + let y_q0: Vec = read_fq_vec(&v.q0.y); + let y_q1: Vec = read_fq_vec(&v.q1.y); match data.curve.as_str() { "BLS12-381 G1" => { - let got = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); + let out = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); + let got = out.0; let want = GroupAffine::::new( Fq::from_base_prime_field_elems(&x[..]).unwrap(), Fq::from_base_prime_field_elems(&y[..]).unwrap(), @@ -109,7 +114,20 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { } }, "BLS12-381 G2" => { - let got = g2_mapper.hash(&v.msg.as_bytes()).unwrap(); + let out = g2_mapper.hash(&v.msg.as_bytes()).unwrap(); + let q0 = out.1; + let q1 = out.2; + let got = out.0; + let want_q0 = GroupAffine::::new( + Fq2::from_base_prime_field_elems(&x_q0[..]).unwrap(), + Fq2::from_base_prime_field_elems(&y_q0[..]).unwrap(), + false, + ); + let want_q1 = GroupAffine::::new( + Fq2::from_base_prime_field_elems(&x_q1[..]).unwrap(), + Fq2::from_base_prime_field_elems(&y_q1[..]).unwrap(), + false, + ); let want = GroupAffine::::new( Fq2::from_base_prime_field_elems(&x[..]).unwrap(), Fq2::from_base_prime_field_elems(&y[..]).unwrap(), @@ -120,10 +138,15 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { if got != want { return Outcome::Failed { msg: Some(format!( - "Suite: {:?}\ngot: {:?}\nwant: {:?}", + "Suite: {:?}\nmsg: {}\n\ngot: {:?}\nwant: {:?}\n\ngot Q0: {}\nwant Q0: {}\n\ngot Q1: {}\nwant Q1: {}", data.ciphersuite, + v.msg, got.to_string(), - want.to_string() + want.to_string(), + q0.to_string(), + want_q0.to_string(), + q1.to_string(), + want_q1.to_string(), )), }; } From 2b9fd7ebe2308b770d3d9dc588402dd03ddc1fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 22 Jun 2022 16:04:05 +0200 Subject: [PATCH 40/56] Rename xi -> zeta --- ec/src/hashing/curve_maps/swu/mod.rs | 60 +++++++++++++------------ ec/src/hashing/curve_maps/wb/mod.rs | 8 ++-- ff/src/fields/mod.rs | 2 +- test-curves/src/bls12_381/g1_swu_iso.rs | 8 ++-- test-curves/src/bls12_381/g2_swu_iso.rs | 16 +++---- 5 files changed, 48 insertions(+), 46 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index 16983550d..7821b15e8 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -15,14 +15,14 @@ use crate::{ /// - [\[WB2019\]] pub trait SWUParams: SWModelParameters { /// An element of the base field that is not a square root see \[WB2019, Section 4\]. - /// It is also convenient to have $g(b/xi * a)$ to be square. In general - /// we use a `XI` with low absolute value coefficients when they are + /// It is also convenient to have $g(b/ZETA * a)$ to be square. In general + /// we use a `ZETA` with low absolute value coefficients when they are /// represented as integers. - const XI: Self::BaseField; - /// An arbitrary nonsquare conveniently chosen to be a primitive element of the base field const ZETA: Self::BaseField; - /// Square root of `THETA = Self::XI/Self::ZETA`. - const XI_ON_ZETA_SQRT: Self::BaseField; + /// An arbitrary nonsquare conveniently chosen to be a primitive element of the base field + const XI: Self::BaseField; + /// Square root of `THETA = Self::ZETA/Self::XI`. + const ZETA_ON_XI_SQRT: Self::BaseField; } /// Represents the SWU hash-to-curve map defined by `P`. @@ -43,27 +43,27 @@ pub fn parity(element: &F) -> bool { impl MapToCurve> for SWUMap

{ /// Constructs a new map if `P` represents a valid map. fn new() -> Result { - // Verifying that both XI and ZETA are non-squares - if P::XI.legendre().is_qr() || P::ZETA.legendre().is_qr() { + // Verifying that both ZETA and XI are non-squares + if P::ZETA.legendre().is_qr() || P::XI.legendre().is_qr() { return Err(HashToCurveError::MapToCurveError( - "both xi and zeta should be quadratic non-residues for the SWU map".to_string(), + "both ZETA and XI should be quadratic non-residues for the SWU map".to_string(), )); } // Verifying precomupted values - let xi_on_zeta = P::XI / P::ZETA; - match xi_on_zeta.sqrt() { - Some(xi_on_zeta_sqrt) => { - if xi_on_zeta_sqrt != P::XI_ON_ZETA_SQRT && xi_on_zeta_sqrt != -P::XI_ON_ZETA_SQRT { + let zeta_on_xi = P::ZETA / P::XI; + match zeta_on_xi.sqrt() { + Some(zeta_on_xi_sqrt) => { + if zeta_on_xi_sqrt != P::ZETA_ON_XI_SQRT && zeta_on_xi_sqrt != -P::ZETA_ON_XI_SQRT { return Err(HashToCurveError::MapToCurveError( - "precomputed P::XI_ON_ZETA_SQRT is not what it is supposed to be" + "precomputed P::ZETA_ON_XI_SQRT is not what it is supposed to be" .to_string(), )); } }, None => { panic!( - "`xi_on_zeta` was expected to have a sqrt, since the numerator and denominator are non-residues and Legendre symbol is multiplicative. Q.E.D" + "`ZETA_ON_XI` was expected to have a sqrt, since the numerator and denominator are non-residues and Legendre symbol is multiplicative. Q.E.D" ); }, } @@ -105,40 +105,41 @@ impl MapToCurve> for SWUMap

{ // gx1 = num_gx1/div_gx1 = [num_x1^3 + A * num_x1 * div^2 + B * div^3] / div^3 let a = P::COEFF_A; let b = P::COEFF_B; - let xi_t2 = P::XI * point.square(); - let ta = xi_t2.square() + xi_t2; + + let zeta_u2 = P::ZETA * point.square(); + let ta = zeta_u2.square() + zeta_u2; let num_x1 = b * (ta + ::one()); - let div = a * if ta.is_zero() { P::XI } else { -ta }; + let div = a * if ta.is_zero() { P::ZETA } else { -ta }; + let num2_x1 = num_x1.square(); let div2 = div.square(); let div3 = div2 * div; let num_gx1 = (num2_x1 + a * div2) * num_x1 + b * div3; // 5. x2 = Z * u^2 * x1 - let num_x2 = xi_t2 * num_x1; // same div + let num_x2 = zeta_u2 * num_x1; // same div // 6. gx2 = x2^3 + A * x2 + B [optimized out; see below] // 7. If is_square(gx1), set x = x1 and y = sqrt(gx1) // 8. Else set x = x2 and y = sqrt(gx2) let gx1_square; let gx1; - let zeta_gx1; assert!( !div3.is_zero(), - "we have checked that neither a or xi are zero. Q.E.D." + "we have checked that neither a or ZETA are zero. Q.E.D." ); let y1: P::BaseField = { gx1 = num_gx1 / div3; - zeta_gx1 = P::ZETA * gx1; if gx1.legendre().is_qr() { gx1_square = true; gx1.sqrt() .expect("We have checked that gx1 is a quadratic residue. Q.E.D") } else { + let zeta_gx1 = P::ZETA * gx1; gx1_square = false; zeta_gx1.sqrt().expect( - "zeta * gx1 is a quadratic residue because legard is multiplicative. Q.E.D", + "ZETA * gx1 is a quadratic residue because legard is multiplicative. Q.E.D", ) } }; @@ -159,8 +160,9 @@ impl MapToCurve> for SWUMap

{ // u^3 * y1 is a square root of gx2. Note that we don't actually need to // compute gx2. - let y2 = P::XI_ON_ZETA_SQRT * xi_t2 * point * y1; + let y2 = zeta_u2 * point * y1; let num_x = if gx1_square { num_x1 } else { num_x2 }; + println!("gx1_square = {}", gx1_square); let y = if gx1_square { y1 } else { y2 }; let x_affine = num_x / div; @@ -235,9 +237,9 @@ mod test { } impl SWUParams for TestSWUMapToCurveParams { - const XI: F127 = MontFp!(F127, "-1"); - const ZETA: F127 = MontFp!(F127, "3"); - const XI_ON_ZETA_SQRT: F127 = MontFp!(F127, "13"); + const ZETA: F127 = MontFp!(F127, "-1"); + const XI: F127 = MontFp!(F127, "3"); + const ZETA_ON_XI_SQRT: F127 = MontFp!(F127, "13"); } /// test that MontFp make a none zero element out of 1 @@ -260,10 +262,10 @@ mod test { assert!(num / den == num_on_den); } - /// Check that the hashing parameters are sane: zeta should be a non-square + /// Check that the hashing parameters are sane: XI should be a non-square #[test] fn checking_the_hashing_parameters() { - assert!(SquareRootField::legendre(&TestSWUMapToCurveParams::ZETA).is_qr() == false); + assert!(SquareRootField::legendre(&TestSWUMapToCurveParams::XI).is_qr() == false); } /// The point of the test is to get a simple SWU compatible curve and make diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index a1ece8fe1..54d58c4d5 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -190,11 +190,11 @@ mod test { /// SWU parameters for E_isogenous impl SWUParams for TestSWU127MapToIsogenousCurveParams { /// NON-SQUARE = - 1 - const XI: F127 = MontFp!(F127, "-1"); + const ZETA: F127 = MontFp!(F127, "-1"); /// A Primitive Root of unity = 3 - const ZETA: F127 = MontFp!(F127, "3"); - /// sqrt(Xi/Zeta) - const XI_ON_ZETA_SQRT: F127 = MontFp!(F127, "13"); + const XI: F127 = MontFp!(F127, "3"); + /// sqrt(ZETA/XI) + const ZETA_ON_XI_SQRT: F127 = MontFp!(F127, "13"); } /// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite diff --git a/ff/src/fields/mod.rs b/ff/src/fields/mod.rs index e63bb9d14..8d6d2910f 100644 --- a/ff/src/fields/mod.rs +++ b/ff/src/fields/mod.rs @@ -86,7 +86,7 @@ pub trait Field: + From { type BasePrimeField: PrimeField; - type BasePrimeFieldIter: Iterator; + type BasePrimeFieldIter: Iterator + DoubleEndedIterator; /// Returns the characteristic of the field, /// in little-endian representation. diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs index 75d2cd5fe..eae97f5d8 100644 --- a/test-curves/src/bls12_381/g1_swu_iso.rs +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -45,12 +45,12 @@ impl SWModelParameters for SwuIsoParameters { // Finite Field of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 // sage: Fq.primitive_element() // 2 -// sage: (Fq(11)/Fq(2)).sqrt() +// sage: (Fq(2)/Fq(11)).sqrt() // 1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394 impl SWUParams for SwuIsoParameters { - const XI: Fq = MontFp!(Fq, "11"); // a nonsquare in Fq ietf standard - const ZETA: Fq = MontFp!(Fq, "2"); // arbitatry primitive root of unity (element) - const XI_ON_ZETA_SQRT: Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=Xi/Zeta Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=Xi/Zeta + const ZETA: Fq = MontFp!(Fq, "11"); // a nonsquare in Fq ietf standard + const XI: Fq = MontFp!(Fq, "2"); // arbitatry primitive root of unity (element) + const ZETA_ON_XI_SQRT: Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=ZETA/XI Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=ZETA/XI } // sage: E1p = g1_iso.domain() diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index 2a59499cd..b106ecf51 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -99,17 +99,17 @@ pub const G2_GENERATOR_Y_C1: Fq = MontFp!(Fq, "347020557560111175564150279686487 // Finite Field in X of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787^2 // sage: Fq2.primitive_element() // X + 2 -// sage: Zeta = _ -// sage: Zeta +// sage: XI = _ +// sage: XI // X + 2 -// sage: Xi = Fq2(-Fq2.gens()[0] - 2) -// sage: Xi == -Zeta +// sage: ZETA = Fq2(-Fq2.gens()[0] - 2) +// sage: ZETA == -XI // True -// sage: (Xi/Zeta).square_root() +// sage: (ZETA/XI).square_root() //X impl SWUParams for SwuIsoParameters { - const XI : Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); //a nonsquare in Fq ietf standard - const ZETA: Fq2 = QuadExt!(MontFp!(Fq, "2"), MontFp!(Fq, "1"),); //arbitatry primitive root of unity (element) - const XI_ON_ZETA_SQRT: Fq2 = QuadExt!(MontFp!(Fq, "0"), MontFp!(Fq, "1"),); ////square root of THETA=Xi/Zeta + const ZETA : Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); //a nonsquare in Fq ietf standard + const XI: Fq2 = QuadExt!(MontFp!(Fq, "2"), MontFp!(Fq, "1"),); //arbitatry primitive root of unity (element) + const ZETA_ON_XI_SQRT: Fq2 = QuadExt!(MontFp!(Fq, "0"), MontFp!(Fq, "1"),); ////square root of THETA=ZETA/XI } From 34ecae3ba0e26efd44a34050570d1664b6d99b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 22 Jun 2022 17:26:57 +0200 Subject: [PATCH 41/56] update cofactor to h_eff --- test-curves/src/bls12_381/g2.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index e60bbe211..91882cdf5 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -23,14 +23,16 @@ impl ModelParameters for Parameters { /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 #[rustfmt::skip] const COFACTOR: &'static [u64] = &[ - 0xcf1c38e31c7238e5, - 0x1616ec6e786f0c70, - 0x21537e293a6691ae, - 0xa628f1cb4d9e82ef, - 0xa68a205b2e5a7ddf, - 0xcd91de4547085aba, - 0x91d50792876a202, - 0x5d543a95414e7f1, + 0xbc69f08f2ee75b35, + 0x84c6a0ea91b35288, + 0x8e2a8e9145ad7689, + 0x986ff031508ffe13, + 0x29c2f178731db956, + 0xd82bf015d1212b02, + 0xec0ec69d7477c1ae, + 0x954cbc06689f6a35, + 0x9894c0adebbf6b4e, + 0x8020005aaa95551 ]; /// COFACTOR_INV = COFACTOR^{-1} mod r From 7945d11ad211eac9740fcba3a3105b317651b5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 22 Jun 2022 18:50:40 +0200 Subject: [PATCH 42/56] update cofactor: should be in BE --- test-curves/src/bls12_381/g2.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index 91882cdf5..c86e31253 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -23,16 +23,16 @@ impl ModelParameters for Parameters { /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 #[rustfmt::skip] const COFACTOR: &'static [u64] = &[ - 0xbc69f08f2ee75b35, - 0x84c6a0ea91b35288, - 0x8e2a8e9145ad7689, - 0x986ff031508ffe13, - 0x29c2f178731db956, - 0xd82bf015d1212b02, - 0xec0ec69d7477c1ae, - 0x954cbc06689f6a35, - 0x9894c0adebbf6b4e, - 0x8020005aaa95551 + 0xe8020005aaa95551, + 0x59894c0adebbf6b4, + 0xe954cbc06689f6a3, + 0x2ec0ec69d7477c1a, + 0x6d82bf015d1212b0, + 0x329c2f178731db95, + 0x9986ff031508ffe1, + 0x88e2a8e9145ad768, + 0x584c6a0ea91b3528, + 0xbc69f08f2ee75b3, ]; /// COFACTOR_INV = COFACTOR^{-1} mod r From bb8f611315d1f9df5d07791690c82d2a28ce38b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 22 Jun 2022 19:04:16 +0200 Subject: [PATCH 43/56] Remove redundant code --- ec/src/hashing/curve_maps/swu/mod.rs | 1 - ec/src/hashing/map_to_curve_hasher.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index 7821b15e8..99b9297f0 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -162,7 +162,6 @@ impl MapToCurve> for SWUMap

{ let y2 = zeta_u2 * point * y1; let num_x = if gx1_square { num_x1 } else { num_x2 }; - println!("gx1_square = {}", gx1_square); let y = if gx1_square { y1 } else { y2 }; let x_affine = num_x / div; diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index 359553157..f3955e9b8 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -64,7 +64,6 @@ where let rand_curve_elem = rand_curve_elem_0 + rand_curve_elem_1; let rand_subgroup_elem = rand_curve_elem.mul_by_cofactor(); - // let rand_subgroup_elem = rand_curve_elem; Ok((rand_subgroup_elem, rand_curve_elem_0, rand_curve_elem_1)) } From 0ce9f81ccd5bca9a508699a675939c3cfc9abfd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Wed, 22 Jun 2022 21:20:39 +0200 Subject: [PATCH 44/56] negate the Y-isogeny for g2 BLS12-381 to match the specifications Co-Authored-By: drskalman <35698397+drskalman@users.noreply.github.com> --- test-curves/src/bls12_381/g2.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index c86e31253..19b940e32 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -180,16 +180,16 @@ impl WBParams for Parameters const PHI_Y_NOM: &'static [::BaseField] = &[ QuadExt!( - MontFp!(Fq, "741186954670679146929220338099241510473496818507223682468899654837783638979784789711608820209076974821832272696229"), - MontFp!(Fq, "741186954670679146929220338099241510473496818507223682468899654837783638979784789711608820209076974821832272696229")), + MontFp!(Fq, "3261222600550988246488569487636662646083386001431784202863158481286248011511053074731078808919938689216061999863558"), + MontFp!(Fq, "3261222600550988246488569487636662646083386001431784202863158481286248011511053074731078808919938689216061999863558")), QuadExt!( MontFp!(Fq, "0"), - MontFp!(Fq, "3112985209616852417102725420016814343988686637730339466369378550318691283715096116788757044878123294251695545324269")), + MontFp!(Fq, "889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235518")), QuadExt!( - MontFp!(Fq, "1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853263"), - MontFp!(Fq, "2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706524")), + MontFp!(Fq, "2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706524"), + MontFp!(Fq, "1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853263")), QuadExt!( - MontFp!(Fq, "1185899127473086635086752540958786416757594909611557891950239447740453822367655663538574112334523159714931636314011"), + MontFp!(Fq, "2816510427748580758331037284777117739799287910327449993381818688383577828123182200904113516794492504322962636245776"), MontFp!(Fq, "0")), ]; From 5a94ff0400867270f7f4d070d9337c304a32e96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 23 Jun 2022 12:13:49 +0200 Subject: [PATCH 45/56] Remove XI, ZETA_ON_XI as they're no longer used --- ec/src/hashing/curve_maps/swu/mod.rs | 37 ++----------------------- ec/src/hashing/curve_maps/wb/mod.rs | 4 --- test-curves/src/bls12_381/g1_swu_iso.rs | 12 ++------ test-curves/src/bls12_381/g2_swu_iso.rs | 18 ++---------- 4 files changed, 7 insertions(+), 64 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index 99b9297f0..d8816e3a0 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -19,10 +19,6 @@ pub trait SWUParams: SWModelParameters { /// we use a `ZETA` with low absolute value coefficients when they are /// represented as integers. const ZETA: Self::BaseField; - /// An arbitrary nonsquare conveniently chosen to be a primitive element of the base field - const XI: Self::BaseField; - /// Square root of `THETA = Self::ZETA/Self::XI`. - const ZETA_ON_XI_SQRT: Self::BaseField; } /// Represents the SWU hash-to-curve map defined by `P`. @@ -43,31 +39,13 @@ pub fn parity(element: &F) -> bool { impl MapToCurve> for SWUMap

{ /// Constructs a new map if `P` represents a valid map. fn new() -> Result { - // Verifying that both ZETA and XI are non-squares - if P::ZETA.legendre().is_qr() || P::XI.legendre().is_qr() { + // Verifying that ZETA is a non-square + if P::ZETA.legendre().is_qr() { return Err(HashToCurveError::MapToCurveError( - "both ZETA and XI should be quadratic non-residues for the SWU map".to_string(), + "ZETA should be a quadratic non-residue for the SWU map".to_string(), )); } - // Verifying precomupted values - let zeta_on_xi = P::ZETA / P::XI; - match zeta_on_xi.sqrt() { - Some(zeta_on_xi_sqrt) => { - if zeta_on_xi_sqrt != P::ZETA_ON_XI_SQRT && zeta_on_xi_sqrt != -P::ZETA_ON_XI_SQRT { - return Err(HashToCurveError::MapToCurveError( - "precomputed P::ZETA_ON_XI_SQRT is not what it is supposed to be" - .to_string(), - )); - } - }, - None => { - panic!( - "`ZETA_ON_XI` was expected to have a sqrt, since the numerator and denominator are non-residues and Legendre symbol is multiplicative. Q.E.D" - ); - }, - } - // Verifying the prerequisite for applicability of SWU map if P::COEFF_A.is_zero() || P::COEFF_B.is_zero() { return Err(HashToCurveError::MapToCurveError("Simplified SWU requires a * b != 0 in the short Weierstrass form of y^2 = x^3 + a*x + b ".to_string())); @@ -184,7 +162,6 @@ mod test { use ark_std::vec::Vec; use super::*; - use ark_ff::SquareRootField; use ark_ff::{fields::Fp64, MontBackend, MontFp}; use hashbrown::HashMap; use sha2::Sha256; @@ -237,8 +214,6 @@ mod test { impl SWUParams for TestSWUMapToCurveParams { const ZETA: F127 = MontFp!(F127, "-1"); - const XI: F127 = MontFp!(F127, "3"); - const ZETA_ON_XI_SQRT: F127 = MontFp!(F127, "13"); } /// test that MontFp make a none zero element out of 1 @@ -261,12 +236,6 @@ mod test { assert!(num / den == num_on_den); } - /// Check that the hashing parameters are sane: XI should be a non-square - #[test] - fn checking_the_hashing_parameters() { - assert!(SquareRootField::legendre(&TestSWUMapToCurveParams::XI).is_qr() == false); - } - /// The point of the test is to get a simple SWU compatible curve and make /// simple hash #[test] diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index 54d58c4d5..cea25e733 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -191,10 +191,6 @@ mod test { impl SWUParams for TestSWU127MapToIsogenousCurveParams { /// NON-SQUARE = - 1 const ZETA: F127 = MontFp!(F127, "-1"); - /// A Primitive Root of unity = 3 - const XI: F127 = MontFp!(F127, "3"); - /// sqrt(ZETA/XI) - const ZETA_ON_XI_SQRT: F127 = MontFp!(F127, "13"); } /// E_isogenous : Elliptic Curve defined by y^2 = x^3 + 109*x + 124 over Finite diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs index eae97f5d8..0e89e3a0d 100644 --- a/test-curves/src/bls12_381/g1_swu_iso.rs +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -40,17 +40,9 @@ impl SWModelParameters for SwuIsoParameters { (G1_GENERATOR_X, G1_GENERATOR_Y); } -// sage: Fq = E1p.base_field() -// sage: Fq -// Finite Field of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 -// sage: Fq.primitive_element() -// 2 -// sage: (Fq(2)/Fq(11)).sqrt() -// 1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394 impl SWUParams for SwuIsoParameters { - const ZETA: Fq = MontFp!(Fq, "11"); // a nonsquare in Fq ietf standard - const XI: Fq = MontFp!(Fq, "2"); // arbitatry primitive root of unity (element) - const ZETA_ON_XI_SQRT: Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=ZETA/XI Fq = MontFp!(Fq, "1496378135713580363480696149166996094826100595588415922929784991932724092840119474685212307129579508222230250924394"); ////square root of THETA=ZETA/XI + // 0xb as per the IETF draft. + const ZETA: Fq = MontFp!(Fq, "11"); } // sage: E1p = g1_iso.domain() diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index b106ecf51..18b7bb5db 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -94,22 +94,8 @@ pub const G2_GENERATOR_Y_C0: Fq = MontFp!(Fq, "300275008528995056215639197196930 #[rustfmt::skip] pub const G2_GENERATOR_Y_C1: Fq = MontFp!(Fq, "347020557560111175564150279686487416538085532798697633906066128669670325197422119639641125873165591545442034801173"); -// sage: Fq2 = g2_iso.domain().base_field() -// sage: Fq2 -// Finite Field in X of size 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787^2 -// sage: Fq2.primitive_element() -// X + 2 -// sage: XI = _ -// sage: XI -// X + 2 -// sage: ZETA = Fq2(-Fq2.gens()[0] - 2) -// sage: ZETA == -XI -// True -// sage: (ZETA/XI).square_root() -//X impl SWUParams for SwuIsoParameters { - const ZETA : Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); //a nonsquare in Fq ietf standard - const XI: Fq2 = QuadExt!(MontFp!(Fq, "2"), MontFp!(Fq, "1"),); //arbitatry primitive root of unity (element) - const ZETA_ON_XI_SQRT: Fq2 = QuadExt!(MontFp!(Fq, "0"), MontFp!(Fq, "1"),); ////square root of THETA=ZETA/XI + // ZETA = -(2 + u) as per IETF draft. + const ZETA : Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); } From 7174d780b294a14f9890f78c4f54f81a62dc0573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 23 Jun 2022 12:15:00 +0200 Subject: [PATCH 46/56] Fix formatting --- test-curves/src/bls12_381/g2.rs | 11 +++++------ test-curves/src/bls12_381/g2_swu_iso.rs | 9 +++------ test-curves/src/bls12_381/mod.rs | 8 ++++---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index 19b940e32..07a7a6fef 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -1,10 +1,10 @@ use crate::bls12_381::*; use ark_ec::{ bls12, + hashing::curve_maps::wb::WBParams, models::{ModelParameters, SWModelParameters}, short_weierstrass_jacobian::GroupAffine, AffineCurve, - hashing::curve_maps::wb::WBParams, }; use ark_ff::{BigInt, Field, MontFp, QuadExt, Zero}; @@ -147,8 +147,7 @@ pub fn p_power_endomorphism(p: &GroupAffine) -> GroupAffine::BaseField] = &[ @@ -165,7 +164,7 @@ impl WBParams for Parameters MontFp!(Fq, "3557697382419259905260257622876359250272784728834673675850718343221361467102966990615722337003569479144794908942033"), MontFp!(Fq, "0")), ]; - + const PHI_X_DEN: &'static [::BaseField] = &[ QuadExt!( MontFp!(Fq, "0"), @@ -177,7 +176,7 @@ impl WBParams for Parameters MontFp!(Fq, "1"), MontFp!(Fq, "0")), ]; - + const PHI_Y_NOM: &'static [::BaseField] = &[ QuadExt!( MontFp!(Fq, "3261222600550988246488569487636662646083386001431784202863158481286248011511053074731078808919938689216061999863558"), @@ -192,7 +191,7 @@ impl WBParams for Parameters MontFp!(Fq, "2816510427748580758331037284777117739799287910327449993381818688383577828123182200904113516794492504322962636245776"), MontFp!(Fq, "0")), ]; - + const PHI_Y_DEN: &'static [::BaseField] = &[ QuadExt!( MontFp!(Fq, "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559355"), diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index 18b7bb5db..5c4331740 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -2,7 +2,7 @@ use crate::bls12_381::*; use ark_ec::models::{ModelParameters, SWModelParameters}; use ark_ff::{MontFp, QuadExt}; -use ark_ec::hashing::curve_maps::swu::{SWUParams}; +use ark_ec::hashing::curve_maps::swu::SWUParams; #[derive(Clone, Default, PartialEq, Eq)] pub struct SwuIsoParameters; @@ -44,7 +44,6 @@ impl ModelParameters for SwuIsoParameters { /// 26652489039290660355457965112010883481355318854675681319708643586776743290055 #[rustfmt::skip] const COFACTOR_INV: Fr = MontFp!(Fr, "26652489039290660355457965112010883481355318854675681319708643586776743290055"); - } // https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/ @@ -68,7 +67,6 @@ impl SWModelParameters for SwuIsoParameters { /// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y) const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = (G2_GENERATOR_X, G2_GENERATOR_Y); - } pub const G2_GENERATOR_X: Fq2 = QuadExt!(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); @@ -94,8 +92,7 @@ pub const G2_GENERATOR_Y_C0: Fq = MontFp!(Fq, "300275008528995056215639197196930 #[rustfmt::skip] pub const G2_GENERATOR_Y_C1: Fq = MontFp!(Fq, "347020557560111175564150279686487416538085532798697633906066128669670325197422119639641125873165591545442034801173"); -impl SWUParams for SwuIsoParameters { +impl SWUParams for SwuIsoParameters { // ZETA = -(2 + u) as per IETF draft. - const ZETA : Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); - + const ZETA: Fq2 = QuadExt!(MontFp!(Fq, "-2"), MontFp!(Fq, "-1"),); } diff --git a/test-curves/src/bls12_381/mod.rs b/test-curves/src/bls12_381/mod.rs index bbdc588bb..3866c1a73 100644 --- a/test-curves/src/bls12_381/mod.rs +++ b/test-curves/src/bls12_381/mod.rs @@ -1,16 +1,16 @@ pub mod fr; -pub use fr::*; use ark_ec::bls12::{Bls12, Bls12Parameters, TwistType}; +pub use fr::*; #[cfg(feature = "bls12_381_curve")] pub mod fq; #[cfg(feature = "bls12_381_curve")] +pub mod fq12; +#[cfg(feature = "bls12_381_curve")] pub mod fq2; #[cfg(feature = "bls12_381_curve")] pub mod fq6; #[cfg(feature = "bls12_381_curve")] -pub mod fq12; -#[cfg(feature = "bls12_381_curve")] pub mod g1; #[cfg(feature = "bls12_381_curve")] pub mod g1_swu_iso; @@ -19,7 +19,7 @@ pub mod g2; #[cfg(feature = "bls12_381_curve")] pub mod g2_swu_iso; #[cfg(feature = "bls12_381_curve")] -pub use {fq::*, fq2::*, fq6::*, fq12::*, g1::*, g1_swu_iso::*, g2_swu_iso::*}; +pub use {fq::*, fq12::*, fq2::*, fq6::*, g1::*, g1_swu_iso::*, g2_swu_iso::*}; #[cfg(test)] mod tests; From 2f2e7ad7e2d96b79f2172ad79b31626667feab00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 23 Jun 2022 12:23:58 +0200 Subject: [PATCH 47/56] Limit the output of `hash` to just one, final elem instead of including the intermediate values q0, q1 in the output --- ec/src/hashing/curve_maps/swu/mod.rs | 2 +- ec/src/hashing/curve_maps/wb/mod.rs | 4 ++-- ec/src/hashing/map_to_curve_hasher.rs | 4 ++-- ec/src/hashing/mod.rs | 2 +- ec/src/hashing/tests/suites.rs | 28 +++------------------------ 5 files changed, 9 insertions(+), 31 deletions(-) diff --git a/ec/src/hashing/curve_maps/swu/mod.rs b/ec/src/hashing/curve_maps/swu/mod.rs index d8816e3a0..c210cbf70 100644 --- a/ec/src/hashing/curve_maps/swu/mod.rs +++ b/ec/src/hashing/curve_maps/swu/mod.rs @@ -250,7 +250,7 @@ mod test { let hash_result = test_swu_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); assert!( - hash_result.0.is_on_curve(), + hash_result.is_on_curve(), "hash results into a point off the curve" ); } diff --git a/ec/src/hashing/curve_maps/wb/mod.rs b/ec/src/hashing/curve_maps/wb/mod.rs index cea25e733..1b8587a54 100644 --- a/ec/src/hashing/curve_maps/wb/mod.rs +++ b/ec/src/hashing/curve_maps/wb/mod.rs @@ -304,12 +304,12 @@ mod test { let hash_result = test_wb_to_curve_hasher.hash(b"if you stick a Babel fish in your ear you can instantly understand anything said to you in any form of language.").expect("fail to hash the string to curve"); assert!( - hash_result.0.x != F127_ZERO && hash_result.0.y != F127_ZERO, + hash_result.x != F127_ZERO && hash_result.y != F127_ZERO, "we assume that not both a and b coefficienst are zero for the test curve" ); assert!( - hash_result.0.is_on_curve(), + hash_result.is_on_curve(), "hash results into a point off the curve" ); } diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index f3955e9b8..4e4d8e5dd 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -47,7 +47,7 @@ where // traits. This uses the IETF hash to curve's specification for Random // oracle encoding (hash_to_curve) defined by combining these components. // See https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-09#section-3 - fn hash(&self, msg: &[u8]) -> Result<(T, T, T), HashToCurveError> { + fn hash(&self, msg: &[u8]) -> Result { // IETF spec of hash_to_curve, from hash_to_field and map_to_curve // sub-components // 1. u = hash_to_field(msg, 2) @@ -65,6 +65,6 @@ where let rand_curve_elem = rand_curve_elem_0 + rand_curve_elem_1; let rand_subgroup_elem = rand_curve_elem.mul_by_cofactor(); - Ok((rand_subgroup_elem, rand_curve_elem_0, rand_curve_elem_1)) + Ok(rand_subgroup_elem) } } diff --git a/ec/src/hashing/mod.rs b/ec/src/hashing/mod.rs index ba8dad708..23901ea39 100644 --- a/ec/src/hashing/mod.rs +++ b/ec/src/hashing/mod.rs @@ -13,7 +13,7 @@ pub trait HashToCurve: Sized { /// Produce a hash of the message, which also depends on the domain. /// The output of the hash is a curve point in the prime order subgroup /// of the given elliptic curve. - fn hash(&self, message: &[u8]) -> Result<(T, T, T), HashToCurveError>; + fn hash(&self, message: &[u8]) -> Result; } /// This is an error that could occur during the hash to curve process diff --git a/ec/src/hashing/tests/suites.rs b/ec/src/hashing/tests/suites.rs index 4467eba73..8369064fb 100644 --- a/ec/src/hashing/tests/suites.rs +++ b/ec/src/hashing/tests/suites.rs @@ -87,14 +87,9 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { // then, test curve points let x: Vec = read_fq_vec(&v.p.x); let y: Vec = read_fq_vec(&v.p.y); - let x_q0: Vec = read_fq_vec(&v.q0.x); - let x_q1: Vec = read_fq_vec(&v.q1.x); - let y_q0: Vec = read_fq_vec(&v.q0.y); - let y_q1: Vec = read_fq_vec(&v.q1.y); match data.curve.as_str() { "BLS12-381 G1" => { - let out = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); - let got = out.0; + let got = g1_mapper.hash(&v.msg.as_bytes()).unwrap(); let want = GroupAffine::::new( Fq::from_base_prime_field_elems(&x[..]).unwrap(), Fq::from_base_prime_field_elems(&y[..]).unwrap(), @@ -114,20 +109,7 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { } }, "BLS12-381 G2" => { - let out = g2_mapper.hash(&v.msg.as_bytes()).unwrap(); - let q0 = out.1; - let q1 = out.2; - let got = out.0; - let want_q0 = GroupAffine::::new( - Fq2::from_base_prime_field_elems(&x_q0[..]).unwrap(), - Fq2::from_base_prime_field_elems(&y_q0[..]).unwrap(), - false, - ); - let want_q1 = GroupAffine::::new( - Fq2::from_base_prime_field_elems(&x_q1[..]).unwrap(), - Fq2::from_base_prime_field_elems(&y_q1[..]).unwrap(), - false, - ); + let got = g2_mapper.hash(&v.msg.as_bytes()).unwrap(); let want = GroupAffine::::new( Fq2::from_base_prime_field_elems(&x[..]).unwrap(), Fq2::from_base_prime_field_elems(&y[..]).unwrap(), @@ -138,15 +120,11 @@ fn run_test_w(Test { data, .. }: &Test) -> Outcome { if got != want { return Outcome::Failed { msg: Some(format!( - "Suite: {:?}\nmsg: {}\n\ngot: {:?}\nwant: {:?}\n\ngot Q0: {}\nwant Q0: {}\n\ngot Q1: {}\nwant Q1: {}", + "Suite: {:?}\nmsg: {}\n\ngot: {:?}\nwant: {:?}", data.ciphersuite, v.msg, got.to_string(), want.to_string(), - q0.to_string(), - want_q0.to_string(), - q1.to_string(), - want_q1.to_string(), )), }; } From 83666cb28ab8784464d77b54642d251d105efb35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 23 Jun 2022 12:25:22 +0200 Subject: [PATCH 48/56] no need to parse q0, q1 when reading json --- ec/src/hashing/tests/json.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ec/src/hashing/tests/json.rs b/ec/src/hashing/tests/json.rs index 1378d80b2..8f2694db1 100644 --- a/ec/src/hashing/tests/json.rs +++ b/ec/src/hashing/tests/json.rs @@ -29,10 +29,6 @@ pub struct Map { pub struct Vector { #[serde(rename = "P")] pub p: P, - #[serde(rename = "Q0")] - pub q0: P, - #[serde(rename = "Q1")] - pub q1: P, pub msg: String, pub u: Vec, } From 84a4d5645712883a04f895bcf239939e16212e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Thu, 23 Jun 2022 12:26:35 +0200 Subject: [PATCH 49/56] Double-ended iterator is not needed at bonud --- ff/src/fields/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ff/src/fields/mod.rs b/ff/src/fields/mod.rs index 8d6d2910f..e63bb9d14 100644 --- a/ff/src/fields/mod.rs +++ b/ff/src/fields/mod.rs @@ -86,7 +86,7 @@ pub trait Field: + From { type BasePrimeField: PrimeField; - type BasePrimeFieldIter: Iterator + DoubleEndedIterator; + type BasePrimeFieldIter: Iterator; /// Returns the characteristic of the field, /// in little-endian representation. From 1b751c5763d4511a56bf74914867c6df4de3a38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Fri, 24 Jun 2022 11:33:02 +0200 Subject: [PATCH 50/56] Use clear_cofactor instead of mul_by_cofactor --- ec/src/hashing/map_to_curve_hasher.rs | 2 +- test-curves/src/bls12_381/g1.rs | 2 +- test-curves/src/bls12_381/g2.rs | 37 +++++++++++++++++++-------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index 4e4d8e5dd..1afd17078 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -63,7 +63,7 @@ where let rand_curve_elem_1 = self.curve_mapper.map_to_curve(rand_field_elems[1])?; let rand_curve_elem = rand_curve_elem_0 + rand_curve_elem_1; - let rand_subgroup_elem = rand_curve_elem.mul_by_cofactor(); + let rand_subgroup_elem = rand_curve_elem.clear_cofactor(); Ok(rand_subgroup_elem) } diff --git a/test-curves/src/bls12_381/g1.rs b/test-curves/src/bls12_381/g1.rs index 3f6c25b81..fe230425c 100644 --- a/test-curves/src/bls12_381/g1.rs +++ b/test-curves/src/bls12_381/g1.rs @@ -17,7 +17,7 @@ impl ModelParameters for Parameters { type ScalarField = Fr; /// COFACTOR = (x - 1)^2 / 3 = 76329603384216526031706109802092473003 - const COFACTOR: &'static [u64] = &[0xd201000000010001]; + const COFACTOR: &'static [u64] = &[0x8c00aaab0000aaab, 0x396c8c005555e156]; /// COFACTOR_INV = COFACTOR^{-1} mod r /// = 52435875175126190458656871551744051925719901746859129887267498875565241663483 diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index 07a7a6fef..4974c0d3c 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -23,16 +23,14 @@ impl ModelParameters for Parameters { /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 #[rustfmt::skip] const COFACTOR: &'static [u64] = &[ - 0xe8020005aaa95551, - 0x59894c0adebbf6b4, - 0xe954cbc06689f6a3, - 0x2ec0ec69d7477c1a, - 0x6d82bf015d1212b0, - 0x329c2f178731db95, - 0x9986ff031508ffe1, - 0x88e2a8e9145ad768, - 0x584c6a0ea91b3528, - 0xbc69f08f2ee75b3, + 0xcf1c38e31c7238e5, + 0x1616ec6e786f0c70, + 0x21537e293a6691ae, + 0xa628f1cb4d9e82ef, + 0xa68a205b2e5a7ddf, + 0xcd91de4547085aba, + 0x91d50792876a202, + 0x5d543a95414e7f1, ]; /// COFACTOR_INV = COFACTOR^{-1} mod r @@ -75,6 +73,25 @@ impl SWModelParameters for Parameters { x_times_point.eq(&p_times_point) } + + #[inline] + fn clear_cofactor(p: &G2Affine) -> G2Affine { + // Using the effective cofactor, as explained in + // Section 5 of https://eprint.iacr.org/2019/403.pdf. + let h_eff: &'static [u64] = &[ + 0xe8020005aaa95551, + 0x59894c0adebbf6b4, + 0xe954cbc06689f6a3, + 0x2ec0ec69d7477c1a, + 0x6d82bf015d1212b0, + 0x329c2f178731db95, + 0x9986ff031508ffe1, + 0x88e2a8e9145ad768, + 0x584c6a0ea91b3528, + 0xbc69f08f2ee75b3, + ]; + Parameters::mul_affine(&p, h_eff).into() + } } pub const G2_GENERATOR_X: Fq2 = QuadExt!(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); From 093e69e3ca254956f7b74abdf67e1408a9b50581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Sat, 16 Jul 2022 17:19:59 +0200 Subject: [PATCH 51/56] g2 & g2_iso should have the same cofactor --- test-curves/src/bls12_381/g2_swu_iso.rs | 28 +++++++------------------ 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index 07c123bf6..e8106c252 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -23,27 +23,15 @@ impl CurveConfig for SwuIsoParameters { /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 #[rustfmt::skip] const COFACTOR: &'static [u64] = &[ - 0xbc69f08f2ee75b35, - 0x84c6a0ea91b35288, - 0x8e2a8e9145ad7689, - 0x986ff031508ffe13, - 0x29c2f178731db956, - 0xd82bf015d1212b02, - 0xec0ec69d7477c1ae, - 0x954cbc06689f6a35, - 0x9894c0adebbf6b4e, - 0x8020005aaa95551 + 0xcf1c38e31c7238e5, + 0x1616ec6e786f0c70, + 0x21537e293a6691ae, + 0xa628f1cb4d9e82ef, + 0xa68a205b2e5a7ddf, + 0xcd91de4547085aba, + 0x91d50792876a202, + 0x5d543a95414e7f1, ]; - // const COFACTOR: &'static [u64] = &[ - // 0xcf1c38e31c7238e5, - // 0x1616ec6e786f0c70, - // 0x21537e293a6691ae, - // 0xa628f1cb4d9e82ef, - // 0xa68a205b2e5a7ddf, - // 0xcd91de4547085aba, - // 0x91d50792876a202, - // 0x5d543a95414e7f1, - // ]; /// COFACTOR_INV = COFACTOR^{-1} mod r /// 26652489039290660355457965112010883481355318854675681319708643586776743290055 From cffad6d39773f8d6272c77dc3d3dff0f3c500a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Sat, 16 Jul 2022 17:28:23 +0200 Subject: [PATCH 52/56] Add source for the WB-map parameters --- test-curves/src/bls12_381/g1.rs | 1 + test-curves/src/bls12_381/g2.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/test-curves/src/bls12_381/g1.rs b/test-curves/src/bls12_381/g1.rs index 151ea7fba..2a66ac1cd 100644 --- a/test-curves/src/bls12_381/g1.rs +++ b/test-curves/src/bls12_381/g1.rs @@ -53,6 +53,7 @@ impl short_weierstrass::SWCurveConfig for Parameters { } } +// Parameters from the [IETF draft v16, section E.2](https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-11-isogeny-map-for-bls12-381). impl WBParams for Parameters { type IsogenousCurve = SwuIsoParameters; diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index 34c0eefab..fced18af8 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -159,6 +159,7 @@ pub fn p_power_endomorphism(p: &Affine) -> Affine { res } +// Parameters from the [IETF draft v16, section E.3](https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-3-isogeny-map-for-bls12-381). impl WBParams for Parameters { type IsogenousCurve = g2_swu_iso::SwuIsoParameters; From c8723aba7984ae888e553c823fb7a48ce710c0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Sat, 16 Jul 2022 17:38:00 +0200 Subject: [PATCH 53/56] Use the more efficient g2 cofactor clearing --- test-curves/src/bls12_381/g2.rs | 64 ++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/test-curves/src/bls12_381/g2.rs b/test-curves/src/bls12_381/g2.rs index fced18af8..07e2f0ccb 100644 --- a/test-curves/src/bls12_381/g2.rs +++ b/test-curves/src/bls12_381/g2.rs @@ -1,10 +1,12 @@ +use core::ops::Neg; + use crate::bls12_381::*; use ark_ec::{ bls12, hashing::curve_maps::wb::WBParams, models::CurveConfig, short_weierstrass::{self, *}, - AffineCurve, + AffineCurve, ProjectiveCurve, }; use ark_ff::{BigInt, Field, MontFp, Zero}; @@ -74,21 +76,36 @@ impl short_weierstrass::SWCurveConfig for Parameters { #[inline] fn clear_cofactor(p: &G2Affine) -> G2Affine { - // Using the effective cofactor, as explained in - // Section 5 of https://eprint.iacr.org/2019/403.pdf. - let h_eff: &'static [u64] = &[ - 0xe8020005aaa95551, - 0x59894c0adebbf6b4, - 0xe954cbc06689f6a3, - 0x2ec0ec69d7477c1a, - 0x6d82bf015d1212b0, - 0x329c2f178731db95, - 0x9986ff031508ffe1, - 0x88e2a8e9145ad768, - 0x584c6a0ea91b3528, - 0xbc69f08f2ee75b3, - ]; - Parameters::mul_affine(&p, h_eff).into() + // Based on Section 4.1 of https://eprint.iacr.org/2017/419.pdf + // [h(ψ)]P = [x^2 − x − 1]P + [x − 1]ψ(P) + (ψ^2)(2P) + + // x = -15132376222941642752 + // When multiplying, use -c1 instead, and then negate the result. That's much + // more efficient, since the scalar -c1 has less limbs and a much lower Hamming + // weight. + let x: &'static [u64] = crate::bls12_381::Parameters::X; + let p_projective = p.into_projective(); + + // [x]P + let x_p = Parameters::mul_affine(p, &x).neg(); + // ψ(P) + let psi_p = p_power_endomorphism(&p); + // (ψ^2)(2P) + let mut psi2_p2 = double_p_power_endomorphism(&p_projective.double()); + + // tmp = [x]P + ψ(P) + let mut tmp = x_p.clone(); + tmp.add_assign_mixed(&psi_p); + + // tmp2 = [x^2]P + [x]ψ(P) + let mut tmp2: Projective = tmp; + tmp2 = tmp2.mul(x).neg(); + + // add up all the terms + psi2_p2 += tmp2; + psi2_p2 -= x_p; + psi2_p2.add_assign_mixed(&-psi_p); + (psi2_p2 - p_projective).into_affine() } } @@ -134,6 +151,11 @@ pub const P_POWER_ENDOMORPHISM_COEFF_1: Fq2 = Fq2::new( "1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257") ); +pub const DOUBLE_P_POWER_ENDOMORPHISM: Fq2 = Fq2::new( + MontFp!("4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436"), + FQ_ZERO +); + pub fn p_power_endomorphism(p: &Affine) -> Affine { // The p-power endomorphism for G2 is defined as follows: // 1. Note that G2 is defined on curve E': y^2 = x^3 + 4(u+1). To map a point @@ -159,6 +181,16 @@ pub fn p_power_endomorphism(p: &Affine) -> Affine { res } +/// For a p-power endomorphism psi(P), compute psi(psi(P)) +pub fn double_p_power_endomorphism(p: &Projective) -> Projective { + let mut res = *p; + + res.x *= DOUBLE_P_POWER_ENDOMORPHISM; + res.y = res.y.neg(); + + res +} + // Parameters from the [IETF draft v16, section E.3](https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#name-3-isogeny-map-for-bls12-381). impl WBParams for Parameters { type IsogenousCurve = g2_swu_iso::SwuIsoParameters; From 7fea6c9b43f4e42845af4ff4eeb9ac4a70e14a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Tue, 19 Jul 2022 11:58:15 +0200 Subject: [PATCH 54/56] Define generators as per method in zcash Based on rationale here: https://github.com/zcash/librustzcash/blob/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381/README.md#generators --- test-curves/src/bls12_381/g1_swu_iso.rs | 25 +++++--------- test-curves/src/bls12_381/g2_swu_iso.rs | 43 +++++++++---------------- 2 files changed, 23 insertions(+), 45 deletions(-) diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs index 5f225972c..1818ad30a 100644 --- a/test-curves/src/bls12_381/g1_swu_iso.rs +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -40,27 +40,18 @@ impl SWCurveConfig for SwuIsoParameters { #[rustfmt::skip] const COEFF_B: Fq = MontFp!("2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280"); - /// AFFINE_GENERATOR_COEFFS = (G1_GENERATOR_X, G1_GENERATOR_Y) const GENERATOR: G1Affine = G1Affine::new_unchecked(G1_GENERATOR_X, G1_GENERATOR_Y); } +/// Lexicographically smallest, valid x-coordinate of a point P on the curve (with its corresponding y) multiplied by the cofactor. +/// P_x = 2 +/// P_y = 658522096176515125667361255350269797307718222519385801637008089782287711363858559738763090642304321670226247205569 +/// P = E(P_x, P_y) +/// G = P * COFACTOR +const G1_GENERATOR_X: Fq = MontFp!("1677416608493238977774703213729589714082762656433187746258164626835771660734158898989765932111853529350617333597651"); +const G1_GENERATOR_Y: Fq = MontFp!("1405098061573104639413728190240719229571583960971553962991897960445246185035342568402755187331334546673157015627211"); + impl SWUParams for SwuIsoParameters { // 0xb as per the IETF draft. const ZETA: Fq = MontFp!("11"); } - -// sage: E1p = g1_iso.domain() -// sage: gen_p = E1p.random_point() -// sage: gen_p = 76329603384216526031706109802092473003 * gen_p -// sage: gen_p -// (628127623378585612843095022119507708025289394540669560027004601611569871267541856210323712812047239723504248810248 : 344075650239127142968089520704786925624745533124141202280424406752399324209523628375922007963596482424831722220273 : 1) -// sage: gen_p * 52435875175126190479447740508185965837690552500527637822603658699938581184513 -// (0 : 1 : 0) - -/// G1_GENERATOR_X = -#[rustfmt::skip] -pub const G1_GENERATOR_X: Fq = MontFp!("1020232295111649411126762359530270833151925872915888263107080350435116244445972822132949957555221231229957568042978"); - -/// G1_GENERATOR_Y = -#[rustfmt::skip] -pub const G1_GENERATOR_Y: Fq = MontFp!("572738012940399893876716047881377207991025392386390068007901896139525257801331726850963609787517204283814804267188"); diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index e8106c252..2c45f2755 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -16,8 +16,7 @@ impl CurveConfig for SwuIsoParameters { type BaseField = Fq2; type ScalarField = Fr; - //sage: g2_iso.codomain().order() == g2_iso.domain().order() - //True + /// Cofactors of g2_iso and g2 are the same. /// COFACTOR = (x^8 - 4 x^7 + 5 x^6) - (4 x^4 + 6 x^3 - 4 x^2 - 4 x + 13) // /// 9 /// = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 @@ -49,40 +48,28 @@ impl CurveConfig for SwuIsoParameters { // - B' = 1012 * (1 + I) // // * Z: -(2 + I) - impl SWCurveConfig for SwuIsoParameters { - /// COEFF_A = [240, 0] + /// COEFF_A = 240 * I const COEFF_A: Fq2 = Fq2::new(MontFp!("0"), MontFp!("240")); - /// COEFF_B = [1012, 1012] + /// COEFF_B = 1012 + 1012 * I const COEFF_B: Fq2 = Fq2::new(MontFp!("1012"), MontFp!("1012")); - /// AFFINE_GENERATOR_COEFFS = (G2_GENERATOR_X, G2_GENERATOR_Y) const GENERATOR: G2Affine = G2Affine::new_unchecked(G2_GENERATOR_X, G2_GENERATOR_Y); } -pub const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); -pub const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); - -// sage: gen_p = E2p.random_point() -// sage: gen_p *= 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 -// sage: gen_p -// (3742867872338536021971219193407057626975566811775929228638115610845414823755734136602223916420662890679205212867815*X + 2008970337784971958599114573863246208442825790877271736434783886837659225024554344101831904846457859657000371883048 : 347020557560111175564150279686487416538085532798697633906066128669670325197422119639641125873165591545442034801173*X + 3002750085289950562156391971969303286031832683890522668239999505933394032768942051901168474820339778663917384775384 : 1) - -#[rustfmt::skip] -pub const G2_GENERATOR_X_C0: Fq = MontFp!("2008970337784971958599114573863246208442825790877271736434783886837659225024554344101831904846457859657000371883048"); - -/// G2_GENERATOR_X_C1 = -#[rustfmt::skip] -pub const G2_GENERATOR_X_C1: Fq = MontFp!("3742867872338536021971219193407057626975566811775929228638115610845414823755734136602223916420662890679205212867815"); - -/// G2_GENERATOR_Y_C0 = -#[rustfmt::skip] -pub const G2_GENERATOR_Y_C0: Fq = MontFp!("3002750085289950562156391971969303286031832683890522668239999505933394032768942051901168474820339778663917384775384"); - -/// G2_GENERATOR_Y_C1 = -#[rustfmt::skip] -pub const G2_GENERATOR_Y_C1: Fq = MontFp!("347020557560111175564150279686487416538085532798697633906066128669670325197422119639641125873165591545442034801173"); +/// Lexicographically smallest, valid x-coordinate of a point P on the curve (with its corresponding y) multiplied by the cofactor. +/// P_x = 1 +/// P_y = 1199519624119946820355795551601605892701128025883245860600494152840508171012839086684258857614063467038089173303263 + 2721622435888802346851223931977585460571674503470326381323808470905804676865417627238564067834747838523978879375704 * I +/// P = E(P_x, P_y) +/// G = P * COFACTOR +const G2_GENERATOR_X: Fq2 = Fq2::new(G2_GENERATOR_X_C0, G2_GENERATOR_X_C1); +const G2_GENERATOR_Y: Fq2 = Fq2::new(G2_GENERATOR_Y_C0, G2_GENERATOR_Y_C1); + +const G2_GENERATOR_X_C0: Fq = MontFp!("2595569946714414516067015540153643524656442638788025933727967960306287756885400469291119095920626560658971252184199"); +const G2_GENERATOR_X_C1: Fq = MontFp!("1037079738597573406765355774006601850633656296583542639082316151670128374872040593053087014315526494961765370307992"); +const G2_GENERATOR_Y_C0: Fq = MontFp!("3927929472994661655038722055497331445175131868678630546921475383290711810401295661250673209427965906654429357114487"); +const G2_GENERATOR_Y_C1: Fq = MontFp!("3300326318345570015758639333209189167876318321385223785506096497597561910823001330832964776707374262378602791224889"); impl SWUParams for SwuIsoParameters { // ZETA = -(2 + u) as per IETF draft. From 9fbd1500b9eb44aacb309eacfa823c9ad61eec17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Tue, 19 Jul 2022 12:02:55 +0200 Subject: [PATCH 55/56] Update comments --- test-curves/src/bls12_381/g1_swu_iso.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs index 1818ad30a..b271e6765 100644 --- a/test-curves/src/bls12_381/g1_swu_iso.rs +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -35,7 +35,7 @@ impl CurveConfig for SwuIsoParameters { // - B' = 2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280 // * Z: 11 impl SWCurveConfig for SwuIsoParameters { - const COEFF_A: Fq = MontFp!("12190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677"); //sage doesn't approve of this + const COEFF_A: Fq = MontFp!("12190336318893619529228877361869031420615612348429846051986726275283378313155663745811710833465465981901188123677"); #[rustfmt::skip] const COEFF_B: Fq = MontFp!("2906670324641927570491258158026293881577086121416628140204402091718288198173574630967936031029026176254968826637280"); @@ -52,6 +52,6 @@ const G1_GENERATOR_X: Fq = MontFp!("16774166084932389777747032137295897140827626 const G1_GENERATOR_Y: Fq = MontFp!("1405098061573104639413728190240719229571583960971553962991897960445246185035342568402755187331334546673157015627211"); impl SWUParams for SwuIsoParameters { - // 0xb as per the IETF draft. + // ZETA = 0xb as per the IETF draft. const ZETA: Fq = MontFp!("11"); } From 007621bdcd9a8b7346432a078647b0805ee6b4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20G=C3=B3rny?= Date: Tue, 19 Jul 2022 12:12:45 +0200 Subject: [PATCH 56/56] Add explicit tests for G1, G2 generators --- test-curves/src/bls12_381/g1_swu_iso.rs | 12 ++++++++++++ test-curves/src/bls12_381/g2_swu_iso.rs | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/test-curves/src/bls12_381/g1_swu_iso.rs b/test-curves/src/bls12_381/g1_swu_iso.rs index b271e6765..5be970f37 100644 --- a/test-curves/src/bls12_381/g1_swu_iso.rs +++ b/test-curves/src/bls12_381/g1_swu_iso.rs @@ -55,3 +55,15 @@ impl SWUParams for SwuIsoParameters { // ZETA = 0xb as per the IETF draft. const ZETA: Fq = MontFp!("11"); } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_gen() { + let gen: G1Affine = SwuIsoParameters::GENERATOR; + assert!(gen.is_on_curve()); + assert!(gen.is_in_correct_subgroup_assuming_on_curve()); + } +} diff --git a/test-curves/src/bls12_381/g2_swu_iso.rs b/test-curves/src/bls12_381/g2_swu_iso.rs index 2c45f2755..337ad1c78 100644 --- a/test-curves/src/bls12_381/g2_swu_iso.rs +++ b/test-curves/src/bls12_381/g2_swu_iso.rs @@ -75,3 +75,14 @@ impl SWUParams for SwuIsoParameters { // ZETA = -(2 + u) as per IETF draft. const ZETA: Fq2 = Fq2::new(MontFp!("-2"), MontFp!("-1")); } +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_gen() { + let gen: G2Affine = g2_swu_iso::SwuIsoParameters::GENERATOR; + assert!(gen.is_on_curve()); + assert!(gen.is_in_correct_subgroup_assuming_on_curve()); + } +}