diff --git a/Cargo.lock b/Cargo.lock index 179c0d658..454104ebd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -780,6 +780,15 @@ dependencies = [ "digest", ] +[[package]] +name = "hybrid-array" +version = "0.2.0-pre.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27fbaf242418fe980caf09ed348d5a6aeabe71fc1bd8bebad641f4591ae0a46d" +dependencies = [ + "typenum", +] + [[package]] name = "indexmap" version = "2.1.0" @@ -1408,8 +1417,8 @@ version = "0.8.0-pre" dependencies = [ "base16ct", "der 0.8.0-pre", - "generic-array", "hex-literal 0.4.1", + "hybrid-array", "pkcs8 0.11.0-pre", "serdect", "subtle", diff --git a/sec1/Cargo.toml b/sec1/Cargo.toml index 255079701..9725cbfb1 100644 --- a/sec1/Cargo.toml +++ b/sec1/Cargo.toml @@ -18,7 +18,7 @@ rust-version = "1.70" [dependencies] base16ct = { version = "0.2", optional = true, default-features = false } der = { version = "=0.8.0-pre", optional = true, features = ["oid"] } -generic-array = { version = "0.14.7", optional = true, default-features = false } +hybrid-array = { version = "=0.2.0-pre.8", optional = true, default-features = false } pkcs8 = { version = "=0.11.0-pre", optional = true, default-features = false } serdect = { version = "=0.3.0-pre", optional = true, default-features = false, features = ["alloc"] } subtle = { version = "2", optional = true, default-features = false } @@ -35,7 +35,7 @@ std = ["alloc", "der?/std"] der = ["dep:der", "zeroize"] pem = ["alloc", "der/pem", "pkcs8/pem"] -point = ["dep:base16ct", "dep:generic-array"] +point = ["dep:base16ct", "dep:hybrid-array"] serde = ["dep:serdect"] zeroize = ["dep:zeroize", "der?/zeroize"] diff --git a/sec1/src/lib.rs b/sec1/src/lib.rs index f6b419081..0a25dd446 100644 --- a/sec1/src/lib.rs +++ b/sec1/src/lib.rs @@ -49,7 +49,7 @@ pub use crate::error::{Error, Result}; pub use crate::point::EncodedPoint; #[cfg(feature = "point")] -pub use generic_array::typenum::consts; +pub use hybrid_array::typenum::consts; #[cfg(feature = "der")] pub use crate::{parameters::EcParameters, private_key::EcPrivateKey, traits::DecodeEcPrivateKey}; diff --git a/sec1/src/point.rs b/sec1/src/point.rs index 6e040ae5e..fa32f720b 100644 --- a/sec1/src/point.rs +++ b/sec1/src/point.rs @@ -11,12 +11,12 @@ use core::{ cmp::Ordering, fmt::{self, Debug}, hash::{Hash, Hasher}, - ops::Add, + ops::{Add, Sub}, str, }; -use generic_array::{ +use hybrid_array::{ typenum::{U1, U24, U28, U32, U48, U66}, - ArrayLength, GenericArray, + Array, ArraySize, }; #[cfg(feature = "alloc")] @@ -34,20 +34,20 @@ use zeroize::Zeroize; /// Trait for supported modulus sizes which precomputes the typenums for /// various point encodings so they don't need to be included as bounds. // TODO(tarcieri): replace this all with const generic expressions. -pub trait ModulusSize: 'static + ArrayLength + Copy + Debug { +pub trait ModulusSize: 'static + ArraySize + Copy + Debug { /// Size of a compressed point for the given elliptic curve when encoded /// using the SEC1 `Elliptic-Curve-Point-to-Octet-String` algorithm /// (including leading `0x02` or `0x03` tag byte). - type CompressedPointSize: 'static + ArrayLength + Copy + Debug; + type CompressedPointSize: 'static + ArraySize + Copy + Debug; /// Size of an uncompressed point for the given elliptic curve when encoded /// using the SEC1 `Elliptic-Curve-Point-to-Octet-String` algorithm /// (including leading `0x04` tag byte). - type UncompressedPointSize: 'static + ArrayLength + Copy + Debug; + type UncompressedPointSize: 'static + ArraySize + Copy + Debug; /// Size of an untagged point for given elliptic curve, i.e. size of two /// serialized base field elements. - type UntaggedPointSize: 'static + ArrayLength + Copy + Debug; + type UntaggedPointSize: 'static + ArraySize + Copy + Debug + Sub; } macro_rules! impl_modulus_size { @@ -72,7 +72,7 @@ pub struct EncodedPoint where Size: ModulusSize, { - bytes: GenericArray, + bytes: Array, } #[allow(clippy::len_without_is_empty)] @@ -103,7 +103,7 @@ where return Err(Error::PointEncoding); } - let mut bytes = GenericArray::default(); + let mut bytes = Array::default(); bytes[..expected_len].copy_from_slice(input); Ok(Self { bytes }) } @@ -111,16 +111,16 @@ where /// Decode elliptic curve point from raw uncompressed coordinates, i.e. /// encoded as the concatenated `x || y` coordinates with no leading SEC1 /// tag byte (which would otherwise be `0x04` for an uncompressed point). - pub fn from_untagged_bytes(bytes: &GenericArray) -> Self { - let (x, y) = bytes.split_at(Size::to_usize()); - Self::from_affine_coordinates(x.into(), y.into(), false) + pub fn from_untagged_bytes(bytes: &Array) -> Self { + let (x, y) = bytes.split_ref(); + Self::from_affine_coordinates(x, y, false) } /// Encode an elliptic curve point from big endian serialized coordinates /// (with optional point compression) pub fn from_affine_coordinates( - x: &GenericArray, - y: &GenericArray, + x: &Array, + y: &Array, compress: bool, ) -> Self { let tag = if compress { @@ -129,7 +129,7 @@ where Tag::Uncompressed }; - let mut bytes = GenericArray::default(); + let mut bytes = Array::default(); bytes[0] = tag.into(); bytes[1..(Size::to_usize() + 1)].copy_from_slice(x); @@ -200,19 +200,20 @@ where return Coordinates::Identity; } - let (x, y) = self.bytes[1..].split_at(Size::to_usize()); + let (x_bytes, y_bytes) = self.bytes[1..].split_at(Size::to_usize()); + let x = Array::ref_from_slice(x_bytes); if self.is_compressed() { Coordinates::Compressed { - x: x.into(), + x, y_is_odd: self.tag() as u8 & 1 == 1, } } else if self.is_compact() { Coordinates::Compact { x: x.into() } } else { Coordinates::Uncompressed { - x: x.into(), - y: y.into(), + x, + y: Array::ref_from_slice(y_bytes), } } } @@ -220,7 +221,7 @@ where /// Get the x-coordinate for this [`EncodedPoint`]. /// /// Returns `None` if this point is the identity point. - pub fn x(&self) -> Option<&GenericArray> { + pub fn x(&self) -> Option<&Array> { match self.coordinates() { Coordinates::Identity => None, Coordinates::Compressed { x, .. } => Some(x), @@ -232,7 +233,7 @@ where /// Get the y-coordinate for this [`EncodedPoint`]. /// /// Returns `None` if this point is compressed or the identity point. - pub fn y(&self) -> Option<&GenericArray> { + pub fn y(&self) -> Option<&Array> { match self.coordinates() { Coordinates::Compressed { .. } | Coordinates::Identity => None, Coordinates::Uncompressed { y, .. } => Some(y), @@ -255,10 +256,10 @@ where impl ConditionallySelectable for EncodedPoint where Size: ModulusSize, - >::ArrayType: Copy, + ::ArrayType: Copy, { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - let mut bytes = GenericArray::default(); + let mut bytes = Array::default(); for (i, byte) in bytes.iter_mut().enumerate() { *byte = u8::conditional_select(&a.bytes[i], &b.bytes[i], choice); @@ -271,7 +272,7 @@ where impl Copy for EncodedPoint where Size: ModulusSize, - >::ArrayType: Copy, + ::ArrayType: Copy, { } @@ -382,7 +383,7 @@ where type Err = Error; fn from_str(hex: &str) -> Result { - let mut buf = GenericArray::::default(); + let mut buf = Array::::default(); base16ct::mixed::decode(hex, &mut buf) .map_err(|_| Error::PointEncoding) .and_then(Self::from_bytes) @@ -426,13 +427,13 @@ pub enum Coordinates<'a, Size: ModulusSize> { /// Compact curve point Compact { /// x-coordinate - x: &'a GenericArray, + x: &'a Array, }, /// Compressed curve point Compressed { /// x-coordinate - x: &'a GenericArray, + x: &'a Array, /// Is the y-coordinate odd? y_is_odd: bool, @@ -441,10 +442,10 @@ pub enum Coordinates<'a, Size: ModulusSize> { /// Uncompressed curve point Uncompressed { /// x-coordinate - x: &'a GenericArray, + x: &'a Array, /// y-coordinate - y: &'a GenericArray, + y: &'a Array, }, } @@ -556,8 +557,8 @@ impl From for u8 { mod tests { use super::{Coordinates, Tag}; use core::str::FromStr; - use generic_array::{typenum::U32, GenericArray}; use hex_literal::hex; + use hybrid_array::typenum::U32; #[cfg(feature = "alloc")] use alloc::string::ToString; @@ -600,7 +601,7 @@ mod tests { assert_eq!( compressed_even_y.x().unwrap(), - &hex!("0100000000000000000000000000000000000000000000000000000000000000").into() + &hex!("0100000000000000000000000000000000000000000000000000000000000000") ); assert_eq!(compressed_even_y.y(), None); @@ -625,7 +626,7 @@ mod tests { assert_eq!( compressed_odd_y.x().unwrap(), - &hex!("0200000000000000000000000000000000000000000000000000000000000000").into() + &hex!("0200000000000000000000000000000000000000000000000000000000000000") ); assert_eq!(compressed_odd_y.y(), None); } @@ -649,11 +650,11 @@ mod tests { assert_eq!( uncompressed_point.x().unwrap(), - &hex!("1111111111111111111111111111111111111111111111111111111111111111").into() + &hex!("1111111111111111111111111111111111111111111111111111111111111111") ); assert_eq!( uncompressed_point.y().unwrap(), - &hex!("2222222222222222222222222222222222222222222222222222222222222222").into() + &hex!("2222222222222222222222222222222222222222222222222222222222222222") ); } @@ -701,8 +702,7 @@ mod tests { #[test] fn from_untagged_point() { let untagged_bytes = hex!("11111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222222"); - let uncompressed_point = - EncodedPoint::from_untagged_bytes(GenericArray::from_slice(&untagged_bytes[..])); + let uncompressed_point = EncodedPoint::from_untagged_bytes(&untagged_bytes.into()); assert_eq!(uncompressed_point.as_bytes(), &UNCOMPRESSED_BYTES[..]); }