From 7e232077089cb59366d80b6fb76d5e5c6ca4a181 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 31 Jan 2023 20:53:40 -0700 Subject: [PATCH] Add `FieldBytesEncoding` trait impls The `elliptic-curve` v0.13.0-pre.3 release refactored encoding onto a `FieldBytesEncoding` trait which provides curve-specific conversions between `Uint` and `FieldBytes`. This commit adds these trait impls and otherwise cleans up serialization-related code to use the new API. The `*_be_*` and `*_le_*` APIs have all been removed in favor of curves having a canonical endianness each. That's customizable on a per-curve basis via `FieldBytesEncoding`. Also bumps `ecdsa` to v0.16.0-pre.0. --- Cargo.lock | 15 ++++--- Cargo.toml | 6 +-- bp256/Cargo.toml | 4 +- bp256/src/r1.rs | 20 +++++++-- bp256/src/t1.rs | 20 +++++++-- bp384/Cargo.toml | 4 +- bp384/src/r1.rs | 20 +++++++-- bp384/src/t1.rs | 20 +++++++-- k256/Cargo.toml | 6 +-- k256/src/ecdsa.rs | 6 +-- k256/src/lib.rs | 27 ++++++------ k256/src/schnorr/signing.rs | 8 ++-- k256/src/schnorr/verifying.rs | 7 ++- p224/Cargo.toml | 2 +- p224/src/lib.rs | 7 ++- p256/Cargo.toml | 6 +-- p256/benches/field.rs | 4 +- p256/src/arithmetic.rs | 13 ++---- p256/src/arithmetic/field.rs | 41 +++++++----------- p256/src/arithmetic/hash2curve.rs | 6 +-- p256/src/lib.rs | 32 +++++++------- p384/Cargo.toml | 6 +-- p384/benches/field.rs | 4 +- p384/src/arithmetic.rs | 6 +-- p384/src/arithmetic/field.rs | 25 ++++------- p384/src/arithmetic/scalar.rs | 22 ++++------ p384/src/lib.rs | 33 +++++++------- p521/Cargo.toml | 2 +- p521/src/lib.rs | 8 ++-- primeorder/Cargo.toml | 2 +- primeorder/src/affine.rs | 6 +-- primeorder/src/field.rs | 72 ++++++++----------------------- 32 files changed, 229 insertions(+), 231 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b62c5885e..c1e005f4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,8 +330,9 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.0-pre" -source = "git+https://github.com/RustCrypto/signatures.git#4af28dd9fa18411b7c8ac09f83ddcfedabe94e29" +version = "0.16.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcd6964e28e4802aed67abfaddd5e5430f368c54cc3e498d2a6a8444e5361fe5" dependencies = [ "der", "elliptic-curve", @@ -348,8 +349,9 @@ checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elliptic-curve" -version = "0.13.0-pre.2" -source = "git+https://github.com/RustCrypto/traits.git#adbf0ad45be30b6866f733c4f366cdb129ad50ce" +version = "0.13.0-pre.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a583fbbbfde04e0ef9c8b84c3bf8e504155a1642f91bf5cc2d6e7355cfb6ac4f" dependencies = [ "base16ct", "base64ct", @@ -912,8 +914,9 @@ dependencies = [ [[package]] name = "rfc6979" -version = "0.4.0-pre" -source = "git+https://github.com/RustCrypto/signatures.git#4af28dd9fa18411b7c8ac09f83ddcfedabe94e29" +version = "0.4.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b3595c18d975a2c373afdb4f8d17016589e65f9d84305c1c36fc55272def0bd" dependencies = [ "hmac", "subtle", diff --git a/Cargo.toml b/Cargo.toml index 5bb87ab49..5b42a8e24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,4 @@ members = [ ] [profile.dev] -opt-level = 2 - -[patch.crates-io] -elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" } -ecdsa = { git = "https://github.com/RustCrypto/signatures.git" } +opt-level = 2 \ No newline at end of file diff --git a/bp256/Cargo.toml b/bp256/Cargo.toml index 5c024fd0b..ec10a82e3 100644 --- a/bp256/Cargo.toml +++ b/bp256/Cargo.toml @@ -13,10 +13,10 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } # optional dependencies -ecdsa = { version = "=0.16.0-pre", optional = true, default-features = false, features = ["der"] } +ecdsa = { version = "=0.16.0-pre.0", optional = true, default-features = false, features = ["der"] } sha2 = { version = "0.10", optional = true, default-features = false } [features] diff --git a/bp256/src/r1.rs b/bp256/src/r1.rs index 8a611052e..4a8bc0e80 100644 --- a/bp256/src/r1.rs +++ b/bp256/src/r1.rs @@ -3,7 +3,11 @@ #[cfg(feature = "ecdsa")] pub mod ecdsa; -use elliptic_curve::{bigint::U256, consts::U32}; +use elliptic_curve::{ + bigint::{ArrayEncoding, U256}, + consts::U32, + FieldBytesEncoding, +}; #[cfg(feature = "pkcs8")] use crate::pkcs8; @@ -36,13 +40,23 @@ impl pkcs8::AssociatedOid for BrainpoolP256r1 { pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.7"); } +/// brainpoolP256r1 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// brainpoolP256r1 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// brainpoolP256r1 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U256 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U256::from_be_byte_array(*field_bytes) + } + + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} /// brainpoolP256r1 secret key. pub type SecretKey = elliptic_curve::SecretKey; diff --git a/bp256/src/t1.rs b/bp256/src/t1.rs index ae2543953..2bf618ceb 100644 --- a/bp256/src/t1.rs +++ b/bp256/src/t1.rs @@ -3,7 +3,11 @@ #[cfg(feature = "ecdsa")] pub mod ecdsa; -use elliptic_curve::{bigint::U256, consts::U32}; +use elliptic_curve::{ + bigint::{ArrayEncoding, U256}, + consts::U32, + FieldBytesEncoding, +}; #[cfg(feature = "pkcs8")] use crate::pkcs8; @@ -36,13 +40,23 @@ impl pkcs8::AssociatedOid for BrainpoolP256t1 { pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.8"); } +/// brainpoolP256t1 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// brainpoolP256t1 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// brainpoolP256t1 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U256 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U256::from_be_byte_array(*field_bytes) + } + + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} /// brainpoolP256t1 secret key. pub type SecretKey = elliptic_curve::SecretKey; diff --git a/bp384/Cargo.toml b/bp384/Cargo.toml index a4032c4c8..7da110caf 100644 --- a/bp384/Cargo.toml +++ b/bp384/Cargo.toml @@ -13,10 +13,10 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } # optional dependencies -ecdsa = { version = "=0.16.0-pre", optional = true, default-features = false, features = ["der"] } +ecdsa = { version = "=0.16.0-pre.0", optional = true, default-features = false, features = ["der"] } sha2 = { version = "0.10", optional = true, default-features = false } [features] diff --git a/bp384/src/r1.rs b/bp384/src/r1.rs index 62857b593..848b3505a 100644 --- a/bp384/src/r1.rs +++ b/bp384/src/r1.rs @@ -3,7 +3,11 @@ #[cfg(feature = "ecdsa")] pub mod ecdsa; -use elliptic_curve::{bigint::U384, consts::U48}; +use elliptic_curve::{ + bigint::{ArrayEncoding, U384}, + consts::U48, + FieldBytesEncoding, +}; #[cfg(feature = "pkcs8")] use crate::pkcs8; @@ -36,13 +40,23 @@ impl pkcs8::AssociatedOid for BrainpoolP384r1 { pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.11"); } +/// brainpoolP384r1 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// brainpoolP384r1 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// brainpoolP384r1 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U384 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U384::from_be_byte_array(*field_bytes) + } + + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} /// brainpoolP384r1 secret key. pub type SecretKey = elliptic_curve::SecretKey; diff --git a/bp384/src/t1.rs b/bp384/src/t1.rs index 0cce62136..bb618e720 100644 --- a/bp384/src/t1.rs +++ b/bp384/src/t1.rs @@ -3,7 +3,11 @@ #[cfg(feature = "ecdsa")] pub mod ecdsa; -use elliptic_curve::{bigint::U384, consts::U48}; +use elliptic_curve::{ + bigint::{ArrayEncoding, U384}, + consts::U48, + FieldBytesEncoding, +}; #[cfg(feature = "pkcs8")] use crate::pkcs8; @@ -36,13 +40,23 @@ impl pkcs8::AssociatedOid for BrainpoolP384t1 { pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.12"); } +/// brainpoolP384t1 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// brainpoolP384t1 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// brainpoolP384t1 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U384 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U384::from_be_byte_array(*field_bytes) + } + + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} /// brainpoolP384t1 secret key. pub type SecretKey = elliptic_curve::SecretKey; diff --git a/k256/Cargo.toml b/k256/Cargo.toml index 2e6982d97..4ba5f9173 100644 --- a/k256/Cargo.toml +++ b/k256/Cargo.toml @@ -19,11 +19,11 @@ rust-version = "1.61" [dependencies] cfg-if = "1.0" -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } # optional dependencies once_cell = { version = "1.16", optional = true, default-features = false } -ecdsa-core = { version = "=0.16.0-pre", package = "ecdsa", optional = true, default-features = false, features = ["der"] } +ecdsa-core = { version = "=0.16.0-pre.0", package = "ecdsa", optional = true, default-features = false, features = ["der"] } hex-literal = { version = "0.3", optional = true } serdect = { version = "0.1", optional = true, default-features = false } sha2 = { version = "0.10", optional = true, default-features = false } @@ -32,7 +32,7 @@ signature = { version = "2", optional = true } [dev-dependencies] blobby = "0.3" criterion = "0.4" -ecdsa-core = { version = "=0.16.0-pre", package = "ecdsa", default-features = false, features = ["dev"] } +ecdsa-core = { version = "=0.16.0-pre.0", package = "ecdsa", default-features = false, features = ["dev"] } hex-literal = "0.3" num-bigint = "0.4" num-traits = "0.2" diff --git a/k256/src/ecdsa.rs b/k256/src/ecdsa.rs index f2cbd9612..d23c0594d 100644 --- a/k256/src/ecdsa.rs +++ b/k256/src/ecdsa.rs @@ -160,10 +160,10 @@ use { crate::{AffinePoint, FieldBytes, ProjectivePoint, Scalar}, ecdsa_core::hazmat::{SignPrimitive, VerifyPrimitive}, elliptic_curve::{ + bigint::U256, ops::{Invert, MulByGenerator, Reduce}, scalar::IsHigh, subtle::CtOption, - Curve, }, }; @@ -201,7 +201,7 @@ impl SignPrimitive for Scalar { return Err(Error::new()); } - let z = Self::reduce(Secp256k1::decode_field_bytes(z)); + let z = >::reduce_bytes(z); // Compute scalar inversion of ๐‘˜ let k_inv = Option::::from(k.invert()).ok_or_else(Error::new)?; @@ -211,7 +211,7 @@ impl SignPrimitive for Scalar { // Lift x-coordinate of ๐‘น (element of base field) into a serialized big // integer, then reduce it into an element of the scalar field - let r = Self::reduce(Secp256k1::decode_field_bytes(&R.x.to_bytes())); + let r = >::reduce_bytes(&R.x.to_bytes()); // Compute ๐’” as a signature over ๐’“ and ๐’›. let s = k_inv * (z + (r * self)); diff --git a/k256/src/lib.rs b/k256/src/lib.rs index da5d9b1de..1fd604e6e 100644 --- a/k256/src/lib.rs +++ b/k256/src/lib.rs @@ -59,6 +59,7 @@ use elliptic_curve::{ bigint::ArrayEncoding, consts::{U32, U33, U64}, generic_array::GenericArray, + FieldBytesEncoding, }; /// Order of the secp256k1 elliptic curve in hexadecimal. @@ -90,16 +91,6 @@ impl elliptic_curve::Curve for Secp256k1 { /// Curve order. const ORDER: U256 = ORDER; - - /// Decode unsigned integer from serialized field element. - fn decode_field_bytes(field_bytes: &FieldBytes) -> U256 { - U256::from_be_byte_array(*field_bytes) - } - - /// Encode unsigned integer into serialized field element. - fn encode_field_bytes(uint: &U256) -> FieldBytes { - uint.to_be_byte_array() - } } impl elliptic_curve::PrimeCurve for Secp256k1 {} @@ -122,17 +113,27 @@ impl pkcs8::AssociatedOid for Secp256k1 { /// Compressed SEC1-encoded secp256k1 (K-256) curve point. pub type CompressedPoint = GenericArray; +/// SEC1-encoded secp256k1 (K-256) curve point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// secp256k1 (K-256) field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). pub type FieldBytes = elliptic_curve::FieldBytes; +impl FieldBytesEncoding for U256 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U256::from_be_byte_array(*field_bytes) + } + + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} + /// Bytes used by a wide reduction: twice the width of [`FieldBytes`]. pub type WideBytes = GenericArray; -/// SEC1-encoded secp256k1 (K-256) curve point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; - /// Non-zero secp256k1 (K-256) scalar field element. #[cfg(feature = "arithmetic")] pub type NonZeroScalar = elliptic_curve::NonZeroScalar; diff --git a/k256/src/schnorr/signing.rs b/k256/src/schnorr/signing.rs index 9df8a8ec3..b1226da7f 100644 --- a/k256/src/schnorr/signing.rs +++ b/k256/src/schnorr/signing.rs @@ -2,8 +2,7 @@ use super::{tagged_hash, Signature, VerifyingKey, AUX_TAG, CHALLENGE_TAG, NONCE_TAG}; use crate::{ - AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Scalar, Secp256k1, - SecretKey, + AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Scalar, SecretKey, }; use elliptic_curve::{ bigint::U256, @@ -11,7 +10,6 @@ use elliptic_curve::{ rand_core::CryptoRngCore, subtle::ConditionallySelectable, zeroize::{Zeroize, ZeroizeOnDrop}, - Curve, }; use sha2::{Digest, Sha256}; use signature::{ @@ -100,13 +98,13 @@ impl SigningKey { let verifying_point = AffinePoint::from(k.verifying_key); let r = verifying_point.x.normalize(); - let e = >::reduce(Secp256k1::decode_field_bytes( + let e = >::reduce_bytes( &tagged_hash(CHALLENGE_TAG) .chain_update(r.to_bytes()) .chain_update(self.verifying_key.to_bytes()) .chain_update(msg_digest) .finalize(), - )); + ); let s = *secret_key + e * *self.secret_key; let s = Option::from(NonZeroScalar::new(s)).ok_or_else(Error::new)?; diff --git a/k256/src/schnorr/verifying.rs b/k256/src/schnorr/verifying.rs index 15d7274ab..8094b0125 100644 --- a/k256/src/schnorr/verifying.rs +++ b/k256/src/schnorr/verifying.rs @@ -1,12 +1,11 @@ //! Taproot Schnorr verifying key. use super::{tagged_hash, Signature, CHALLENGE_TAG}; -use crate::{AffinePoint, FieldBytes, ProjectivePoint, PublicKey, Scalar, Secp256k1}; +use crate::{AffinePoint, FieldBytes, ProjectivePoint, PublicKey, Scalar}; use elliptic_curve::{ bigint::U256, ops::{LinearCombination, Reduce}, point::DecompactPoint, - Curve, }; use sha2::{ digest::{consts::U32, FixedOutput}, @@ -64,13 +63,13 @@ impl PrehashVerifier for VerifyingKey { let prehash: [u8; 32] = prehash.try_into().map_err(|_| Error::new())?; let (r, s) = signature.split(); - let e = >::reduce(Secp256k1::decode_field_bytes( + let e = >::reduce_bytes( &tagged_hash(CHALLENGE_TAG) .chain_update(signature.r.to_bytes()) .chain_update(self.to_bytes()) .chain_update(prehash) .finalize(), - )); + ); let R = ProjectivePoint::lincomb( &ProjectivePoint::GENERATOR, diff --git a/p224/Cargo.toml b/p224/Cargo.toml index 62b462b0a..67f7fafc6 100644 --- a/p224/Cargo.toml +++ b/p224/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } [features] default = ["pem", "std"] diff --git a/p224/src/lib.rs b/p224/src/lib.rs index 3c64d8f8f..d509261c3 100644 --- a/p224/src/lib.rs +++ b/p224/src/lib.rs @@ -16,6 +16,7 @@ pub use elliptic_curve::{self, bigint::U256}; use elliptic_curve::{ consts::{U28, U29}, generic_array::GenericArray, + FieldBytesEncoding, }; /// NIST P-224 elliptic curve. @@ -52,14 +53,16 @@ impl pkcs8::AssociatedOid for NistP224 { /// Compressed SEC1-encoded NIST P-224 curve point. pub type CompressedPoint = GenericArray; +/// NIST P-224 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// NIST P-224 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or /// scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// NIST P-224 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U256 {} /// NIST P-224 secret key. pub type SecretKey = elliptic_curve::SecretKey; diff --git a/p256/Cargo.toml b/p256/Cargo.toml index bb1b80ad2..4dddc87e3 100644 --- a/p256/Cargo.toml +++ b/p256/Cargo.toml @@ -17,11 +17,11 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } primeorder = { version = "=0.13.0-pre", path = "../primeorder" } # optional dependencies -ecdsa-core = { version = "=0.16.0-pre", package = "ecdsa", optional = true, default-features = false, features = ["der"] } +ecdsa-core = { version = "=0.16.0-pre.0", package = "ecdsa", optional = true, default-features = false, features = ["der"] } hex-literal = { version = "0.3", optional = true } serdect = { version = "0.1", optional = true, default-features = false } sha2 = { version = "0.10", optional = true, default-features = false } @@ -29,7 +29,7 @@ sha2 = { version = "0.10", optional = true, default-features = false } [dev-dependencies] blobby = "0.3" criterion = "0.4" -ecdsa-core = { version = "=0.16.0-pre", package = "ecdsa", default-features = false, features = ["dev"] } +ecdsa-core = { version = "=0.16.0-pre.0", package = "ecdsa", default-features = false, features = ["dev"] } hex-literal = "0.3" proptest = "1" rand_core = { version = "0.6", features = ["getrandom"] } diff --git a/p256/benches/field.rs b/p256/benches/field.rs index de89987f3..43ece839f 100644 --- a/p256/benches/field.rs +++ b/p256/benches/field.rs @@ -7,14 +7,14 @@ use hex_literal::hex; use p256::FieldElement; fn test_field_element_x() -> FieldElement { - FieldElement::from_sec1( + FieldElement::from_bytes( &hex!("1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83").into(), ) .unwrap() } fn test_field_element_y() -> FieldElement { - FieldElement::from_sec1( + FieldElement::from_bytes( &hex!("ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9").into(), ) .unwrap() diff --git a/p256/src/arithmetic.rs b/p256/src/arithmetic.rs index b8bca5061..d99aac884 100644 --- a/p256/src/arithmetic.rs +++ b/p256/src/arithmetic.rs @@ -37,9 +37,8 @@ impl PrimeCurveParams for NistP256 { .sub(&FieldElement::ONE) .sub(&FieldElement::ONE); - const EQUATION_B: FieldElement = FieldElement::from_be_hex( - "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", - ); + const EQUATION_B: FieldElement = + FieldElement::from_hex("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"); /// Base point of P-256. /// @@ -50,11 +49,7 @@ impl PrimeCurveParams for NistP256 { /// Gแตง = 4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5 /// ``` const GENERATOR: (FieldElement, FieldElement) = ( - FieldElement::from_be_hex( - "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", - ), - FieldElement::from_be_hex( - "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", - ), + FieldElement::from_hex("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"), + FieldElement::from_hex("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"), ); } diff --git a/p256/src/arithmetic/field.rs b/p256/src/arithmetic/field.rs index 7adb789a6..2f0d87394 100644 --- a/p256/src/arithmetic/field.rs +++ b/p256/src/arithmetic/field.rs @@ -7,7 +7,7 @@ mod field_impl; use self::field_impl::*; -use crate::FieldBytes; +use crate::{FieldBytes, NistP256}; use core::{ iter::{Product, Sum}, ops::{AddAssign, Mul, MulAssign, Neg, SubAssign}, @@ -37,6 +37,7 @@ const R_2: U256 = pub struct FieldElement(pub(crate) U256); primeorder::impl_field_element!( + NistP256, FieldElement, FieldBytes, U256, @@ -52,19 +53,6 @@ primeorder::impl_field_element!( ); impl FieldElement { - /// Attempts to parse the given byte array as an SEC1-encoded field element. - /// - /// Returns None if the byte array does not contain a big-endian integer in the range - /// [0, p). - pub fn from_sec1(bytes: FieldBytes) -> CtOption { - Self::from_be_bytes(bytes) - } - - /// Returns the SEC1 encoding of this field element. - pub fn to_sec1(self) -> FieldBytes { - self.to_be_bytes() - } - /// Returns `self^by`, where `by` is a little-endian integer exponent. /// /// **This operation is variable time with respect to the exponent.** If the exponent @@ -168,14 +156,17 @@ impl PrimeField for FieldElement { const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked(); const DELTA: Self = Self::ZERO; // TODO + #[inline] fn from_repr(bytes: FieldBytes) -> CtOption { - Self::from_sec1(bytes) + Self::from_bytes(&bytes) } + #[inline] fn to_repr(&self) -> FieldBytes { - self.to_sec1() + self.to_bytes() } + #[inline] fn is_odd(&self) -> Choice { self.is_odd() } @@ -205,12 +196,12 @@ mod tests { #[test] fn from_bytes() { assert_eq!( - FieldElement::from_sec1(FieldBytes::default()).unwrap(), + FieldElement::from_bytes(&FieldBytes::default()).unwrap(), FieldElement::ZERO ); assert_eq!( - FieldElement::from_sec1( - [ + FieldElement::from_bytes( + &[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ] @@ -220,15 +211,15 @@ mod tests { FieldElement::ONE ); assert!(bool::from( - FieldElement::from_sec1([0xff; 32].into()).is_none() + FieldElement::from_bytes(&[0xff; 32].into()).is_none() )); } #[test] fn to_bytes() { - assert_eq!(FieldElement::ZERO.to_sec1(), FieldBytes::default()); + assert_eq!(FieldElement::ZERO.to_bytes(), FieldBytes::default()); assert_eq!( - FieldElement::ONE.to_sec1(), + FieldElement::ONE.to_bytes(), [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 @@ -241,7 +232,7 @@ mod tests { fn repeated_add() { let mut r = FieldElement::ONE; for i in 0..DBL_TEST_VECTORS.len() { - assert_eq!(r.to_sec1(), DBL_TEST_VECTORS[i].into()); + assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into()); r = r + &r; } } @@ -250,7 +241,7 @@ mod tests { fn repeated_double() { let mut r = FieldElement::ONE; for i in 0..DBL_TEST_VECTORS.len() { - assert_eq!(r.to_sec1(), DBL_TEST_VECTORS[i].into()); + assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into()); r = r.double(); } } @@ -260,7 +251,7 @@ mod tests { let mut r = FieldElement::ONE; let two = r + &r; for i in 0..DBL_TEST_VECTORS.len() { - assert_eq!(r.to_sec1(), DBL_TEST_VECTORS[i].into()); + assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into()); r = r * &two; } } diff --git a/p256/src/arithmetic/hash2curve.rs b/p256/src/arithmetic/hash2curve.rs index e67d39b04..ee59124e4 100644 --- a/p256/src/arithmetic/hash2curve.rs +++ b/p256/src/arithmetic/hash2curve.rs @@ -69,7 +69,7 @@ impl MapToCurve for FieldElement { let (qx, qy) = self.osswu(); // TODO(tarcieri): assert that `qy` is correct? less circuitous conversion? - AffinePoint::decompress(&qx.to_sec1(), qy.is_odd()) + AffinePoint::decompress(&qx.to_bytes(), qy.is_odd()) .unwrap() .into() } @@ -211,8 +211,8 @@ mod tests { }; } - assert_eq!(u[0].to_sec1().as_slice(), test_vector.u_0); - assert_eq!(u[1].to_sec1().as_slice(), test_vector.u_1); + assert_eq!(u[0].to_bytes().as_slice(), test_vector.u_0); + assert_eq!(u[1].to_bytes().as_slice(), test_vector.u_1); let q0 = u[0].map_to_curve(); assert_point_eq!(q0, test_vector.q0_x, test_vector.q0_y); diff --git a/p256/src/lib.rs b/p256/src/lib.rs index 72aa98054..491afbd1f 100644 --- a/p256/src/lib.rs +++ b/p256/src/lib.rs @@ -49,7 +49,9 @@ pub use arithmetic::field::FieldElement; #[cfg(feature = "pkcs8")] pub use elliptic_curve::pkcs8; -use elliptic_curve::{bigint::ArrayEncoding, consts::U33, generic_array::GenericArray}; +use elliptic_curve::{ + bigint::ArrayEncoding, consts::U33, generic_array::GenericArray, FieldBytesEncoding, +}; /// Order of NIST P-256's elliptic curve group (i.e. scalar modulus) serialized /// as hexadecimal. @@ -102,16 +104,6 @@ impl elliptic_curve::Curve for NistP256 { /// Order of NIST P-256's elliptic curve group (i.e. scalar modulus). const ORDER: U256 = U256::from_be_hex(ORDER_HEX); - - /// Decode unsigned integer from serialized field element. - fn decode_field_bytes(field_bytes: &FieldBytes) -> U256 { - U256::from_be_byte_array(*field_bytes) - } - - /// Encode unsigned integer into serialized field element. - fn encode_field_bytes(uint: &U256) -> FieldBytes { - uint.to_be_byte_array() - } } impl elliptic_curve::PrimeCurve for NistP256 {} @@ -143,13 +135,23 @@ pub type BlindedScalar = elliptic_curve::scalar::BlindedScalar; /// Compressed SEC1-encoded NIST P-256 curve point. pub type CompressedPoint = GenericArray; +/// NIST P-256 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// NIST P-256 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// NIST P-256 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U256 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U256::from_be_byte_array(*field_bytes) + } + + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} /// Non-zero NIST P-256 scalar field element. #[cfg(feature = "arithmetic")] @@ -171,8 +173,8 @@ pub type ScalarBits = elliptic_curve::scalar::ScalarBits; #[cfg(feature = "voprf")] impl elliptic_curve::VoprfParameters for NistP256 { - /// See . - const ID: u16 = 0x0003; + /// See . + const ID: &'static str = "P256-SHA256"; /// See . type Hash = sha2::Sha256; diff --git a/p384/Cargo.toml b/p384/Cargo.toml index 6d36a4d7e..26ccb0bdc 100644 --- a/p384/Cargo.toml +++ b/p384/Cargo.toml @@ -17,11 +17,11 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } primeorder = { version = "=0.13.0-pre", path = "../primeorder" } # optional dependencies -ecdsa-core = { version = "=0.16.0-pre", package = "ecdsa", optional = true, default-features = false, features = ["der"] } +ecdsa-core = { version = "=0.16.0-pre.0", package = "ecdsa", optional = true, default-features = false, features = ["der"] } hex-literal = { version = "0.3", optional = true } serdect = { version = "0.1", optional = true, default-features = false } sha2 = { version = "0.10", optional = true, default-features = false } @@ -29,7 +29,7 @@ sha2 = { version = "0.10", optional = true, default-features = false } [dev-dependencies] blobby = "0.3" criterion = "0.4" -ecdsa-core = { version = "=0.16.0-pre", package = "ecdsa", default-features = false, features = ["dev"] } +ecdsa-core = { version = "=0.16.0-pre.0", package = "ecdsa", default-features = false, features = ["dev"] } hex-literal = "0.3" proptest = "1.0" rand_core = { version = "0.6", features = ["getrandom"] } diff --git a/p384/benches/field.rs b/p384/benches/field.rs index 6dcd524c6..f1b1d4529 100644 --- a/p384/benches/field.rs +++ b/p384/benches/field.rs @@ -7,14 +7,14 @@ use hex_literal::hex; use p384::FieldElement; fn test_field_element_x() -> FieldElement { - FieldElement::from_sec1( + FieldElement::from_bytes( hex!("c2b47944fb5de342d03285880177ca5f7d0f2fcad7678cce4229d6e1932fcac11bfc3c3e97d942a3c56bf34123013dbf").into() ) .unwrap() } fn test_field_element_y() -> FieldElement { - FieldElement::from_sec1( + FieldElement::from_bytes( hex!("37257906a8223866eda0743c519616a76a758ae58aee81c5fd35fbf3a855b7754a36d4a0672df95d6c44a81cf7620c2d").into() ) .unwrap() diff --git a/p384/src/arithmetic.rs b/p384/src/arithmetic.rs index 7e2354a5c..9d6d8d8de 100644 --- a/p384/src/arithmetic.rs +++ b/p384/src/arithmetic.rs @@ -44,7 +44,7 @@ impl PrimeCurveParams for NistP384 { /// b = b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 /// 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef - const EQUATION_B: FieldElement = FieldElement::from_be_hex("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"); + const EQUATION_B: FieldElement = FieldElement::from_hex("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"); /// Base point of P-384. /// @@ -60,7 +60,7 @@ impl PrimeCurveParams for NistP384 { /// NOTE: coordinate field elements have been translated into the Montgomery /// domain. const GENERATOR: (FieldElement, FieldElement) = ( - FieldElement::from_be_hex("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"), - FieldElement::from_be_hex("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"), + FieldElement::from_hex("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"), + FieldElement::from_hex("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f"), ); } diff --git a/p384/src/arithmetic/field.rs b/p384/src/arithmetic/field.rs index 8b101cece..760ef89f2 100644 --- a/p384/src/arithmetic/field.rs +++ b/p384/src/arithmetic/field.rs @@ -25,7 +25,7 @@ mod field_impl; use self::field_impl::*; -use crate::FieldBytes; +use crate::{FieldBytes, NistP384}; use core::{ iter::{Product, Sum}, ops::{AddAssign, MulAssign, Neg, SubAssign}, @@ -45,6 +45,7 @@ pub(crate) const MODULUS: U384 = U384::from_be_hex(FieldElement::MODULUS); pub struct FieldElement(pub(super) U384); primeorder::impl_field_element!( + NistP384, FieldElement, FieldBytes, U384, @@ -60,19 +61,6 @@ primeorder::impl_field_element!( ); impl FieldElement { - /// Parse the given byte array as an SEC1-encoded field element. - /// - /// Returns `None` if the byte array does not contain a big-endian integer in - /// the range `[0, p)`. - pub fn from_sec1(bytes: FieldBytes) -> CtOption { - Self::from_be_bytes(bytes) - } - - /// Returns the SEC1 encoding of this field element. - pub fn to_sec1(self) -> FieldBytes { - self.to_be_bytes() - } - /// Compute [`FieldElement`] inversion: `1 / self`. pub fn invert(&self) -> CtOption { let ret = impl_field_invert!( @@ -135,18 +123,21 @@ impl PrimeField for FieldElement { const TWO_INV: Self = Self::ZERO; // TODO const MULTIPLICATIVE_GENERATOR: Self = Self(U384::from_u32(19)); const S: u32 = 1; - const ROOT_OF_UNITY: Self = Self::from_be_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe"); + const ROOT_OF_UNITY: Self = Self::from_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe"); const ROOT_OF_UNITY_INV: Self = Self::ZERO; // TODO const DELTA: Self = Self::ZERO; // TODO + #[inline] fn from_repr(bytes: FieldBytes) -> CtOption { - Self::from_be_bytes(bytes) + Self::from_bytes(&bytes) } + #[inline] fn to_repr(&self) -> FieldBytes { - self.to_be_bytes() + self.to_bytes() } + #[inline] fn is_odd(&self) -> Choice { self.is_odd() } diff --git a/p384/src/arithmetic/scalar.rs b/p384/src/arithmetic/scalar.rs index 00f200fe0..992cc0c5b 100644 --- a/p384/src/arithmetic/scalar.rs +++ b/p384/src/arithmetic/scalar.rs @@ -70,6 +70,7 @@ use core::ops::{Add, Mul, Sub}; pub struct Scalar(U384); primeorder::impl_field_element!( + NistP384, Scalar, FieldBytes, U384, @@ -157,14 +158,6 @@ impl Scalar { pub const fn shr_vartime(&self, shift: usize) -> Scalar { Self(self.0.shr_vartime(shift)) } - - /// Returns the SEC1 encoding of this scalar. - /// - /// Required for running test vectors. - #[cfg(test)] - pub fn to_bytes(&self) -> FieldBytes { - self.to_be_bytes() - } } impl AsRef for Scalar { @@ -219,18 +212,21 @@ impl PrimeField for Scalar { const TWO_INV: Self = Self::ZERO; // TODO const MULTIPLICATIVE_GENERATOR: Self = Self(U384::from_u64(2)); const S: u32 = 1; - const ROOT_OF_UNITY: Self = Self::from_be_hex("ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972"); + const ROOT_OF_UNITY: Self = Self::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972"); const ROOT_OF_UNITY_INV: Self = Self::ZERO; // TODO const DELTA: Self = Self::ZERO; // TODO + #[inline] fn from_repr(bytes: FieldBytes) -> CtOption { - Self::from_be_bytes(bytes) + Self::from_bytes(&bytes) } + #[inline] fn to_repr(&self) -> FieldBytes { - self.to_be_bytes() + self.to_bytes() } + #[inline] fn is_odd(&self) -> Choice { self.is_odd() } @@ -356,10 +352,10 @@ mod tests { fn from_to_bytes_roundtrip() { let k: u64 = 42; let mut bytes = FieldBytes::default(); - bytes[40..].copy_from_slice(k.to_le_bytes().as_ref()); + bytes[40..].copy_from_slice(k.to_be_bytes().as_ref()); let scalar = Scalar::from_repr(bytes).unwrap(); - assert_eq!(bytes, scalar.to_be_bytes()); + assert_eq!(bytes, scalar.to_bytes()); } /// Basic tests that multiplication works. diff --git a/p384/src/lib.rs b/p384/src/lib.rs index 760e8a101..f88cbc065 100644 --- a/p384/src/lib.rs +++ b/p384/src/lib.rs @@ -42,7 +42,9 @@ pub use arithmetic::field::FieldElement; #[cfg(feature = "pkcs8")] pub use elliptic_curve::pkcs8; -use elliptic_curve::{bigint::ArrayEncoding, consts::U49, generic_array::GenericArray}; +use elliptic_curve::{ + bigint::ArrayEncoding, consts::U49, generic_array::GenericArray, FieldBytesEncoding, +}; /// Order of NIST P-384's elliptic curve group (i.e. scalar modulus) in hexadecimal. const ORDER_HEX: &str = "ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973"; @@ -60,16 +62,6 @@ impl elliptic_curve::Curve for NistP384 { /// Order of NIST P-384's elliptic curve group (i.e. scalar modulus). const ORDER: U384 = U384::from_be_hex(ORDER_HEX); - - /// Decode unsigned integer from serialized field element. - fn decode_field_bytes(field_bytes: &FieldBytes) -> U384 { - U384::from_be_byte_array(*field_bytes) - } - - /// Encode unsigned integer into serialized field element. - fn encode_field_bytes(uint: &U384) -> FieldBytes { - uint.to_be_byte_array() - } } impl elliptic_curve::PrimeCurve for NistP384 {} @@ -97,15 +89,24 @@ impl pkcs8::AssociatedOid for NistP384 { /// Compressed SEC1-encoded NIST P-384 curve point. pub type CompressedPoint = GenericArray; +/// NIST P-384 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// NIST P-384 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or /// scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// NIST P-384 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U384 { + fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { + U384::from_be_byte_array(*field_bytes) + } + fn encode_field_bytes(&self) -> FieldBytes { + self.to_be_byte_array() + } +} /// Non-zero NIST P-384 scalar field element. #[cfg(feature = "arithmetic")] pub type NonZeroScalar = elliptic_curve::NonZeroScalar; @@ -126,9 +127,9 @@ pub type ScalarBits = elliptic_curve::scalar::ScalarBits; #[cfg(feature = "voprf")] impl elliptic_curve::VoprfParameters for NistP384 { + /// See . + const ID: &'static str = "P384-SHA384"; + /// See . type Hash = sha2::Sha384; - - /// See . - const ID: u16 = 0x0004; } diff --git a/p521/Cargo.toml b/p521/Cargo.toml index 00f8c8820..4b4acaafc 100644 --- a/p521/Cargo.toml +++ b/p521/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["hazmat", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] } [features] default = ["pem", "std"] diff --git a/p521/src/lib.rs b/p521/src/lib.rs index 2db32db64..e1d9cecb0 100644 --- a/p521/src/lib.rs +++ b/p521/src/lib.rs @@ -20,7 +20,7 @@ pub use elliptic_curve::{self, bigint::U576}; #[cfg(feature = "pkcs8")] pub use elliptic_curve::pkcs8; -use elliptic_curve::{consts::U66, generic_array::GenericArray}; +use elliptic_curve::{consts::U66, generic_array::GenericArray, FieldBytesEncoding}; /// NIST P-521 elliptic curve. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] @@ -62,14 +62,16 @@ impl pkcs8::AssociatedOid for NistP521 { /// Compressed SEC1-encoded NIST P-521 curve point. pub type CompressedPoint = GenericArray; +/// NIST P-521 SEC1 encoded point. +pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; + /// NIST P-521 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or /// scalar). pub type FieldBytes = elliptic_curve::FieldBytes; -/// NIST P-521 SEC1 encoded point. -pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; +impl FieldBytesEncoding for U576 {} /// NIST P-521 secret key. pub type SecretKey = elliptic_curve::SecretKey; diff --git a/primeorder/Cargo.toml b/primeorder/Cargo.toml index 18de8a4bf..65adc3b18 100644 --- a/primeorder/Cargo.toml +++ b/primeorder/Cargo.toml @@ -17,7 +17,7 @@ edition = "2021" rust-version = "1.61" [dependencies] -elliptic-curve = { version = "=0.13.0-pre.2", default-features = false, features = ["arithmetic", "sec1"] } +elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["arithmetic", "sec1"] } # optional dependencies serdect = { version = "0.1", optional = true, default-features = false } diff --git a/primeorder/src/affine.rs b/primeorder/src/affine.rs index d5f6158cc..b821ab6e8 100644 --- a/primeorder/src/affine.rs +++ b/primeorder/src/affine.rs @@ -18,7 +18,7 @@ use elliptic_curve::{ }, subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption}, zeroize::DefaultIsZeroes, - Error, FieldBytes, FieldBytesSize, PublicKey, Result, Scalar, + Error, FieldBytes, FieldBytesEncoding, FieldBytesSize, PublicKey, Result, Scalar, }; #[cfg(feature = "serde")] @@ -66,8 +66,8 @@ where /// Conditionally negate [`AffinePoint`] for use with point compaction. fn to_compact(self) -> Self { let neg_self = -self; - let choice = C::decode_field_bytes(&self.y.to_repr()) - .ct_gt(&C::decode_field_bytes(&neg_self.y.to_repr())); + let choice = C::Uint::decode_field_bytes(&self.y.to_repr()) + .ct_gt(&C::Uint::decode_field_bytes(&neg_self.y.to_repr())); Self { x: self.x, diff --git a/primeorder/src/field.rs b/primeorder/src/field.rs index f116b8fe4..a8824f72a 100644 --- a/primeorder/src/field.rs +++ b/primeorder/src/field.rs @@ -4,14 +4,11 @@ /// # Inherent impls /// - `const ZERO: Self` /// - `const ONE: Self` (multiplicative identity) -/// - `pub fn from_be_bytes` -/// - `pub fn from_be_slice` -/// - `pub fn from_le_bytes` -/// - `pub fn from_le_slice` +/// - `pub fn from_bytes` +/// - `pub fn from_slice` /// - `pub fn from_uint` /// - `fn from_uint_unchecked` -/// - `pub fn to_be_bytes` -/// - `pub fn to_le_bytes` +/// - `pub fn to_bytes` /// - `pub fn to_canonical` /// - `pub fn is_odd` /// - `pub fn is_zero` @@ -47,6 +44,7 @@ #[macro_export] macro_rules! impl_field_element { ( + $curve:tt, $fe:tt, $bytes:ty, $uint:ty, @@ -70,36 +68,22 @@ macro_rules! impl_field_element { /// Create a [` #[doc = stringify!($fe)] /// `] from a canonical big-endian representation. - pub fn from_be_bytes(repr: $bytes) -> $crate::elliptic_curve::subtle::CtOption { - use $crate::elliptic_curve::bigint::ArrayEncoding as _; - Self::from_uint(<$uint>::from_be_byte_array(repr)) + pub fn from_bytes(repr: &$bytes) -> $crate::elliptic_curve::subtle::CtOption { + use $crate::elliptic_curve::FieldBytesEncoding; + Self::from_uint(FieldBytesEncoding::<$curve>::decode_field_bytes(repr)) } /// Decode [` #[doc = stringify!($fe)] /// `] from a big endian byte slice. - pub fn from_be_slice(slice: &[u8]) -> $crate::elliptic_curve::Result { - <$uint as $crate::elliptic_curve::bigint::Encoding>::Repr::try_from(slice) - .ok() - .and_then(|array| Self::from_be_bytes(array.into()).into()) - .ok_or($crate::elliptic_curve::Error) - } + pub fn from_slice(slice: &[u8]) -> $crate::elliptic_curve::Result { + use $crate::elliptic_curve::generic_array::{typenum::Unsigned, GenericArray}; - /// Create a [` - #[doc = stringify!($fe)] - /// `] from a canonical little-endian representation. - pub fn from_le_bytes(repr: $bytes) -> $crate::elliptic_curve::subtle::CtOption { - use $crate::elliptic_curve::bigint::ArrayEncoding as _; - Self::from_uint(<$uint>::from_le_byte_array(repr)) - } + if slice.len() != <$curve as $crate::elliptic_curve::Curve>::FieldBytesSize::USIZE { + return Err($crate::elliptic_curve::Error); + } - /// Decode [` - #[doc = stringify!($fe)] - /// `] from a little endian byte slice. - pub fn from_le_slice(slice: &[u8]) -> $crate::elliptic_curve::Result { - <$uint as $crate::elliptic_curve::bigint::Encoding>::Repr::try_from(slice) - .ok() - .and_then(|array| Self::from_le_bytes(array.into()).into()) + Option::from(Self::from_bytes(GenericArray::from_slice(slice))) .ok_or($crate::elliptic_curve::Error) } @@ -130,22 +114,10 @@ macro_rules! impl_field_element { /// /// This method is primarily intended for defining internal constants. #[allow(dead_code)] - pub(crate) const fn from_be_hex(hex: &str) -> Self { + pub(crate) const fn from_hex(hex: &str) -> Self { Self::from_uint_unchecked(<$uint>::from_be_hex(hex)) } - /// Parse a [` - #[doc = stringify!($fe)] - /// `] from little endian hex-encoded bytes. - /// - /// Does *not* perform a check that the field element does not overflow the order. - /// - /// This method is primarily intended for defining internal constants. - #[allow(dead_code)] - pub(crate) const fn from_le_hex(hex: &str) -> Self { - Self::from_uint_unchecked(<$uint>::from_le_hex(hex)) - } - /// Decode [` #[doc = stringify!($fe)] /// `] from [` @@ -162,17 +134,9 @@ macro_rules! impl_field_element { /// Returns the big-endian encoding of this [` #[doc = stringify!($fe)] /// `]. - pub fn to_be_bytes(self) -> $bytes { - use $crate::elliptic_curve::bigint::ArrayEncoding as _; - self.to_canonical().to_be_byte_array() - } - - /// Returns the little-endian encoding of this [` - #[doc = stringify!($fe)] - /// `]. - pub fn to_le_bytes(self) -> $bytes { - use $crate::elliptic_curve::bigint::ArrayEncoding as _; - self.to_canonical().to_le_byte_array() + pub fn to_bytes(self) -> $bytes { + use $crate::elliptic_curve::FieldBytesEncoding; + FieldBytesEncoding::<$curve>::encode_field_bytes(&self.to_canonical()) } /// Translate [` @@ -334,7 +298,7 @@ macro_rules! impl_field_element { loop { rng.fill_bytes(&mut bytes); - if let Some(fe) = Self::from_be_bytes(bytes).into() { + if let Some(fe) = Self::from_bytes(&bytes).into() { return fe; } }