Skip to content

Commit

Permalink
p521: implement hash2curve (#964)
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda authored Nov 11, 2023
1 parent 0b28c07 commit 699f43e
Show file tree
Hide file tree
Showing 8 changed files with 434 additions and 39 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
allow-unwrap-in-tests = true
45 changes: 28 additions & 17 deletions p256/src/arithmetic/hash2curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,13 @@ impl OsswuMap for FieldElement {
0x3fff_ffff_c000_0000,
],
c2: FieldElement(U256::from_be_hex(
"a3323851ba997e271ac5d59c3298bf50b2806c63966a1a6653e43951f64fdbe7",
)),
map_a: FieldElement(U256::from_be_hex(
"fffffffc00000004000000000000000000000003fffffffffffffffffffffffc",
"9051d26e12a8f3046913c88f9ea8dfee78400ad7423dcf70a1fd38ee98a195fd",
)),
map_a: FieldElement::from_u64(3).neg(),
map_b: FieldElement(U256::from_be_hex(
"dc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf",
)),
z: FieldElement(U256::from_be_hex(
"fffffff50000000b00000000000000000000000afffffffffffffffffffffff5",
)),
z: FieldElement::from_u64(10).neg(),
};
}

Expand Down Expand Up @@ -97,20 +93,35 @@ impl FromOkm for Scalar {

#[cfg(test)]
mod tests {
use crate::{FieldElement, NistP256, Scalar, U256};
use crate::{arithmetic::field::MODULUS, FieldElement, NistP256, Scalar, U256};
use elliptic_curve::{
bigint::{ArrayEncoding, NonZero, U384},
bigint::{ArrayEncoding, CheckedSub, NonZero, U384},
consts::U48,
generic_array::GenericArray,
group::cofactor::CofactorGroup,
hash2curve::{self, ExpandMsgXmd, FromOkm, GroupDigest, MapToCurve},
hash2curve::{self, ExpandMsgXmd, FromOkm, GroupDigest, MapToCurve, OsswuMap},
sec1::{self, ToEncodedPoint},
Curve, Field,
};
use hex_literal::hex;
use proptest::{num::u64::ANY, prelude::ProptestConfig, proptest};
use sha2::Sha256;

#[test]
fn params() {
let params = <FieldElement as OsswuMap>::PARAMS;

let c1 = MODULUS.0.checked_sub(&U256::from_u8(3)).unwrap()
/ NonZero::new(U256::from_u8(4)).unwrap();
assert_eq!(
GenericArray::from_iter(params.c1.iter().rev().flat_map(|v| v.to_be_bytes())),
c1.to_be_byte_array()
);

let c2 = FieldElement::from_u64(10).sqrt().unwrap();
assert_eq!(params.c2, c2);
}

#[allow(dead_code)] // TODO(tarcieri): fix commented out code
#[test]
fn hash_to_curve() {
Expand Down Expand Up @@ -230,7 +241,7 @@ mod tests {
}
}

/// Taken from <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-16.html#name-oprfp-256-sha-256-2>.
/// Taken from <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-voprf#appendix-A.3>.
#[test]
fn hash_to_scalar_voprf() {
struct TestVector {
Expand All @@ -242,22 +253,22 @@ mod tests {

const TEST_VECTORS: &[TestVector] = &[
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x00\x00\x03",
dst: b"DeriveKeyPairOPRFV1-\x00-P256-SHA256",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("274d7747cf2e26352ecea6bd768c426087da3dfcd466b6841b441ada8412fb33"),
sk_sm: &hex!("159749d750713afe245d2d39ccfaae8381c53ce92d098a9375ee70739c7ac0bf"),
},
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x01\x00\x03",
dst: b"DeriveKeyPairOPRFV1-\x01-P256-SHA256",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("b3d12edba73e40401fdc27c0094a56337feb3646d1633345af7e7142a6b1559d"),
sk_sm: &hex!("ca5d94c8807817669a51b196c34c1b7f8442fde4334a7121ae4736364312fca6"),
},
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x02\x00\x03",
dst: b"DeriveKeyPairOPRFV1-\x02-P256-SHA256",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("59519f6c7da344f340ad35ad895a5b97437673cc3ac8b964b823cdb52c932f86"),
sk_sm: &hex!("6ad2173efa689ef2c27772566ad7ff6e2d59b3b196f00219451fb2c89ee4dae2"),
},
];

Expand Down
51 changes: 31 additions & 20 deletions p384/src/arithmetic/hash2curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,13 @@ impl OsswuMap for FieldElement {
0x3fff_ffff_ffff_ffff,
],
c2: FieldElement::from_hex(
"019877cc1041b7555743c0ae2e3a3e61fb2aaa2e0e87ea557a563d8b598a0940d0a697a9e0b9e92cfaa314f583c9d066",
),
map_a: FieldElement::from_hex(
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc",
"2accb4a656b0249c71f0500e83da2fdd7f98e383d68b53871f872fcb9ccb80c53c0de1f8a80f7e1914e2ec69f5a626b3",
),
map_a: FieldElement::from_u64(3).neg(),
map_b: FieldElement::from_hex(
"b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef",
),
z: FieldElement::from_hex(
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffff3",
),
z: FieldElement::from_u64(12).neg(),
};
}

Expand Down Expand Up @@ -100,13 +96,13 @@ impl FromOkm for Scalar {

#[cfg(test)]
mod tests {
use crate::{FieldElement, NistP384, Scalar};
use crate::{arithmetic::field::MODULUS, FieldElement, NistP384, Scalar};
use elliptic_curve::{
bigint::{ArrayEncoding, NonZero, U384, U576},
bigint::{ArrayEncoding, CheckedSub, NonZero, U384, U576},
consts::U72,
generic_array::GenericArray,
group::cofactor::CofactorGroup,
hash2curve::{self, ExpandMsgXmd, FromOkm, GroupDigest, MapToCurve},
hash2curve::{self, ExpandMsgXmd, FromOkm, GroupDigest, MapToCurve, OsswuMap},
ops::Reduce,
sec1::{self, ToEncodedPoint},
Curve,
Expand All @@ -115,6 +111,21 @@ mod tests {
use proptest::{num::u64::ANY, prelude::ProptestConfig, proptest};
use sha2::Sha384;

#[test]
fn params() {
let params = <FieldElement as OsswuMap>::PARAMS;

let c1 = MODULUS.checked_sub(&U384::from_u8(3)).unwrap()
/ NonZero::new(U384::from_u8(4)).unwrap();
assert_eq!(
GenericArray::from_iter(params.c1.iter().rev().flat_map(|v| v.to_be_bytes())),
c1.to_be_byte_array()
);

let c2 = FieldElement::from_u64(12).sqrt().unwrap();
assert_eq!(params.c2, c2);
}

#[test]
fn hash_to_curve() {
struct TestVector {
Expand Down Expand Up @@ -233,7 +244,7 @@ mod tests {
}
}

/// Taken from <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-16.html#name-oprfp-384-sha-384-2>.
/// Taken from <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-voprf#appendix-A.4>.
#[test]
fn hash_to_scalar_voprf() {
struct TestVector {
Expand All @@ -245,22 +256,22 @@ mod tests {

const TEST_VECTORS: &[TestVector] = &[
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x00\x00\x04",
dst: b"DeriveKeyPairOPRFV1-\x00-P384-SHA384",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("c0503759ddd1e31d8c7eae9304c9b1c16f83d1f6d962e3e7b789cd85fd581800e96c5c4256131aafcff9a76919abbd55"),
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("dfe7ddc41a4646901184f2b432616c8ba6d452f9bcd0c4f75a5150ef2b2ed02ef40b8b92f60ae591bcabd72a6518f188"),
},
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x01\x00\x04",
dst: b"DeriveKeyPairOPRFV1-\x01-P384-SHA384",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("514fb6fe2e66af1383840759d56f71730331280f062930ee2a2f7ea42f935acf94087355699d788abfdf09d19a5c85ac"),
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("051646b9e6e7a71ae27c1e1d0b87b4381db6d3595eeeb1adb41579adbf992f4278f9016eafc944edaa2b43183581779d"),
},
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x02\x00\x04",
dst: b"DeriveKeyPairOPRFV1-\x02-P384-SHA384",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("0fcba4a204f67d6c13f780e613915f755319aaa3cb03cd20a5a4a6c403a4812a4fff5d3223e2c309aa66b05cb7611fd4"),
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("5b2690d6954b8fbb159f19935d64133f12770c00b68422559c65431942d721ff79d47d7a75906c30b7818ec0f38b7fb2"),
},
];

Expand Down
2 changes: 2 additions & 0 deletions p521/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ blobby = "0.3"
ecdsa-core = { version = "0.16", package = "ecdsa", default-features = false, features = ["dev"] }
hex-literal = "0.4"
primeorder = { version = "0.13.3", features = ["dev"], path = "../primeorder" }
proptest = "1.3"
rand_core = { version = "0.6", features = ["getrandom"] }

[features]
Expand All @@ -44,6 +45,7 @@ digest = ["ecdsa-core/digest", "ecdsa-core/hazmat"]
ecdh = ["arithmetic", "elliptic-curve/ecdh"]
ecdsa = ["arithmetic", "ecdsa-core/signing", "ecdsa-core/verifying", "sha512"]
getrandom = ["rand_core/getrandom"]
hash2curve = ["arithmetic", "elliptic-curve/hash2curve"]
jwk = ["elliptic-curve/jwk"]
pem = ["elliptic-curve/pem", "pkcs8"]
pkcs8 = ["ecdsa-core?/pkcs8", "elliptic-curve/pkcs8"]
Expand Down
2 changes: 2 additions & 0 deletions p521/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
//! [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final

pub(crate) mod field;
#[cfg(feature = "hash2curve")]
mod hash2curve;
pub(crate) mod scalar;
mod util;

Expand Down
4 changes: 2 additions & 2 deletions p521/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ use super::util::u576_to_le_bytes;
/// p = 2^{521} − 1
const MODULUS_HEX: &str = "00000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";

const MODULUS: U576 = U576::from_be_hex(MODULUS_HEX);
pub(crate) const MODULUS: U576 = U576::from_be_hex(MODULUS_HEX);

/// Element of the secp521r1 base field used for curve coordinates.
#[derive(Clone, Copy)]
pub struct FieldElement(fiat_p521_tight_field_element);
pub struct FieldElement(pub(crate) fiat_p521_tight_field_element);

impl FieldElement {
/// Zero element.
Expand Down
Loading

0 comments on commit 699f43e

Please sign in to comment.