summaryrefslogtreecommitdiffstats
path: root/vendor/elliptic-curve/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/elliptic-curve/src')
-rw-r--r--vendor/elliptic-curve/src/arithmetic.rs86
-rw-r--r--vendor/elliptic-curve/src/dev.rs844
-rw-r--r--vendor/elliptic-curve/src/ecdh.rs236
-rw-r--r--vendor/elliptic-curve/src/error.rs42
-rw-r--r--vendor/elliptic-curve/src/field.rs51
-rw-r--r--vendor/elliptic-curve/src/hash2curve.rs15
-rw-r--r--vendor/elliptic-curve/src/hash2curve/group_digest.rs123
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field.rs48
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs145
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs453
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs352
-rw-r--r--vendor/elliptic-curve/src/hash2curve/isogeny.rs58
-rw-r--r--vendor/elliptic-curve/src/hash2curve/map2curve.rs12
-rw-r--r--vendor/elliptic-curve/src/hash2curve/osswu.rs130
-rw-r--r--vendor/elliptic-curve/src/jwk.rs674
-rw-r--r--vendor/elliptic-curve/src/lib.rs197
-rw-r--r--vendor/elliptic-curve/src/ops.rs79
-rw-r--r--vendor/elliptic-curve/src/point.rs69
-rw-r--r--vendor/elliptic-curve/src/point/non_identity.rs237
-rw-r--r--vendor/elliptic-curve/src/public_key.rs566
-rw-r--r--vendor/elliptic-curve/src/scalar.rs53
-rw-r--r--vendor/elliptic-curve/src/scalar/blinded.rs74
-rw-r--r--vendor/elliptic-curve/src/scalar/nonzero.rs405
-rw-r--r--vendor/elliptic-curve/src/scalar/primitive.rs434
-rw-r--r--vendor/elliptic-curve/src/sec1.rs114
-rw-r--r--vendor/elliptic-curve/src/secret_key.rs393
-rw-r--r--vendor/elliptic-curve/src/secret_key/pkcs8.rs90
-rw-r--r--vendor/elliptic-curve/src/voprf.rs20
-rw-r--r--vendor/elliptic-curve/src/weierstrass.rs128
29 files changed, 6128 insertions, 0 deletions
diff --git a/vendor/elliptic-curve/src/arithmetic.rs b/vendor/elliptic-curve/src/arithmetic.rs
new file mode 100644
index 0000000..7ef7fc5
--- /dev/null
+++ b/vendor/elliptic-curve/src/arithmetic.rs
@@ -0,0 +1,86 @@
+//! Elliptic curve arithmetic traits.
+
+use crate::{
+ ops::{Invert, LinearCombination, MulByGenerator, Reduce, ShrAssign},
+ point::AffineCoordinates,
+ scalar::{FromUintUnchecked, IsHigh},
+ Curve, FieldBytes, PrimeCurve, ScalarPrimitive,
+};
+use core::fmt::Debug;
+use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption};
+use zeroize::DefaultIsZeroes;
+
+/// Elliptic curve with an arithmetic implementation.
+pub trait CurveArithmetic: Curve {
+ /// Elliptic curve point in affine coordinates.
+ type AffinePoint: 'static
+ + AffineCoordinates<FieldRepr = FieldBytes<Self>>
+ + Copy
+ + ConditionallySelectable
+ + ConstantTimeEq
+ + Debug
+ + Default
+ + DefaultIsZeroes
+ + Eq
+ + PartialEq
+ + Sized
+ + Send
+ + Sync;
+
+ /// Elliptic curve point in projective coordinates.
+ ///
+ /// Note: the following bounds are provided by [`group::Group`]:
+ /// - `'static`
+ /// - [`Copy`]
+ /// - [`Clone`]
+ /// - [`Debug`]
+ /// - [`Eq`]
+ /// - [`Sized`]
+ /// - [`Send`]
+ /// - [`Sync`]
+ type ProjectivePoint: ConditionallySelectable
+ + ConstantTimeEq
+ + Default
+ + DefaultIsZeroes
+ + From<Self::AffinePoint>
+ + Into<Self::AffinePoint>
+ + LinearCombination
+ + MulByGenerator
+ + group::Curve<AffineRepr = Self::AffinePoint>
+ + group::Group<Scalar = Self::Scalar>;
+
+ /// Scalar field modulo this curve's order.
+ ///
+ /// Note: the following bounds are provided by [`ff::Field`]:
+ /// - `'static`
+ /// - [`Copy`]
+ /// - [`Clone`]
+ /// - [`ConditionallySelectable`]
+ /// - [`ConstantTimeEq`]
+ /// - [`Debug`]
+ /// - [`Default`]
+ /// - [`Send`]
+ /// - [`Sync`]
+ type Scalar: AsRef<Self::Scalar>
+ + DefaultIsZeroes
+ + From<ScalarPrimitive<Self>>
+ + FromUintUnchecked<Uint = Self::Uint>
+ + Into<FieldBytes<Self>>
+ + Into<ScalarPrimitive<Self>>
+ + Into<Self::Uint>
+ + Invert<Output = CtOption<Self::Scalar>>
+ + IsHigh
+ + PartialOrd
+ + Reduce<Self::Uint, Bytes = FieldBytes<Self>>
+ + ShrAssign<usize>
+ + ff::Field
+ + ff::PrimeField<Repr = FieldBytes<Self>>;
+}
+
+/// Prime order elliptic curve with projective arithmetic implementation.
+pub trait PrimeCurveArithmetic:
+ PrimeCurve + CurveArithmetic<ProjectivePoint = Self::CurveGroup>
+{
+ /// Prime order elliptic curve group.
+ type CurveGroup: group::prime::PrimeCurve<Affine = <Self as CurveArithmetic>::AffinePoint>;
+}
diff --git a/vendor/elliptic-curve/src/dev.rs b/vendor/elliptic-curve/src/dev.rs
new file mode 100644
index 0000000..36c684a
--- /dev/null
+++ b/vendor/elliptic-curve/src/dev.rs
@@ -0,0 +1,844 @@
+//! Development-related functionality.
+//!
+//! Helpers and types for writing tests against concrete implementations of
+//! the traits in this crate.
+
+use crate::{
+ bigint::{Limb, U256},
+ error::{Error, Result},
+ generic_array::typenum::U32,
+ ops::{Invert, LinearCombination, MulByGenerator, Reduce, ShrAssign},
+ pkcs8,
+ point::AffineCoordinates,
+ rand_core::RngCore,
+ scalar::{FromUintUnchecked, IsHigh},
+ sec1::{CompressedPoint, FromEncodedPoint, ToEncodedPoint},
+ subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
+ zeroize::DefaultIsZeroes,
+ Curve, CurveArithmetic, FieldBytesEncoding, PrimeCurve,
+};
+use core::{
+ iter::{Product, Sum},
+ ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
+};
+use ff::{Field, PrimeField};
+use hex_literal::hex;
+use pkcs8::AssociatedOid;
+
+#[cfg(feature = "bits")]
+use ff::PrimeFieldBits;
+
+#[cfg(feature = "jwk")]
+use crate::JwkParameters;
+
+/// Pseudo-coordinate for fixed-based scalar mult output
+pub const PSEUDO_COORDINATE_FIXED_BASE_MUL: [u8; 32] =
+ hex!("deadbeef00000000000000000000000000000000000000000000000000000001");
+
+/// SEC1 encoded point.
+pub type EncodedPoint = crate::sec1::EncodedPoint<MockCurve>;
+
+/// Field element bytes.
+pub type FieldBytes = crate::FieldBytes<MockCurve>;
+
+/// Non-zero scalar value.
+pub type NonZeroScalar = crate::NonZeroScalar<MockCurve>;
+
+/// Public key.
+pub type PublicKey = crate::PublicKey<MockCurve>;
+
+/// Secret key.
+pub type SecretKey = crate::SecretKey<MockCurve>;
+
+/// Scalar primitive type.
+// TODO(tarcieri): make this the scalar type when it's more capable
+pub type ScalarPrimitive = crate::ScalarPrimitive<MockCurve>;
+
+/// Scalar bits.
+#[cfg(feature = "bits")]
+pub type ScalarBits = crate::scalar::ScalarBits<MockCurve>;
+
+/// Mock elliptic curve type useful for writing tests which require a concrete
+/// curve type.
+///
+/// Note: this type is roughly modeled off of NIST P-256, but does not provide
+/// an actual cure arithmetic implementation.
+#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
+pub struct MockCurve;
+
+impl Curve for MockCurve {
+ type FieldBytesSize = U32;
+ type Uint = U256;
+
+ const ORDER: U256 =
+ U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
+}
+
+impl PrimeCurve for MockCurve {}
+
+impl CurveArithmetic for MockCurve {
+ type AffinePoint = AffinePoint;
+ type ProjectivePoint = ProjectivePoint;
+ type Scalar = Scalar;
+}
+
+impl AssociatedOid for MockCurve {
+ /// OID for NIST P-256
+ const OID: pkcs8::ObjectIdentifier = pkcs8::ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7");
+}
+
+#[cfg(feature = "jwk")]
+impl JwkParameters for MockCurve {
+ const CRV: &'static str = "P-256";
+}
+
+/// Example scalar type
+#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
+pub struct Scalar(ScalarPrimitive);
+
+impl Field for Scalar {
+ const ZERO: Self = Self(ScalarPrimitive::ZERO);
+ const ONE: Self = Self(ScalarPrimitive::ONE);
+
+ fn random(mut rng: impl RngCore) -> Self {
+ let mut bytes = FieldBytes::default();
+
+ loop {
+ rng.fill_bytes(&mut bytes);
+ if let Some(scalar) = Self::from_repr(bytes).into() {
+ return scalar;
+ }
+ }
+ }
+
+ fn is_zero(&self) -> Choice {
+ self.0.is_zero()
+ }
+
+ #[must_use]
+ fn square(&self) -> Self {
+ unimplemented!();
+ }
+
+ #[must_use]
+ fn double(&self) -> Self {
+ self.add(self)
+ }
+
+ fn invert(&self) -> CtOption<Self> {
+ unimplemented!();
+ }
+
+ fn sqrt(&self) -> CtOption<Self> {
+ unimplemented!();
+ }
+
+ fn sqrt_ratio(_num: &Self, _div: &Self) -> (Choice, Self) {
+ unimplemented!();
+ }
+}
+
+impl PrimeField for Scalar {
+ type Repr = FieldBytes;
+
+ const MODULUS: &'static str =
+ "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff";
+ const NUM_BITS: u32 = 256;
+ const CAPACITY: u32 = 255;
+ const TWO_INV: Self = Self::ZERO; // BOGUS!
+ const MULTIPLICATIVE_GENERATOR: Self = Self::ZERO; // BOGUS! Should be 7
+ const S: u32 = 4;
+ const ROOT_OF_UNITY: Self = Self::ZERO; // BOGUS! Should be 0xffc97f062a770992ba807ace842a3dfc1546cad004378daf0592d7fbb41e6602
+ const ROOT_OF_UNITY_INV: Self = Self::ZERO; // BOGUS!
+ const DELTA: Self = Self::ZERO; // BOGUS!
+
+ fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
+ ScalarPrimitive::from_bytes(&bytes).map(Self)
+ }
+
+ fn to_repr(&self) -> FieldBytes {
+ self.0.to_bytes()
+ }
+
+ fn is_odd(&self) -> Choice {
+ self.0.is_odd()
+ }
+}
+
+#[cfg(feature = "bits")]
+impl PrimeFieldBits for Scalar {
+ #[cfg(target_pointer_width = "32")]
+ type ReprBits = [u32; 8];
+
+ #[cfg(target_pointer_width = "64")]
+ type ReprBits = [u64; 4];
+
+ fn to_le_bits(&self) -> ScalarBits {
+ self.0.as_uint().to_words().into()
+ }
+
+ fn char_le_bits() -> ScalarBits {
+ MockCurve::ORDER.to_words().into()
+ }
+}
+
+impl AsRef<Scalar> for Scalar {
+ fn as_ref(&self) -> &Scalar {
+ self
+ }
+}
+
+impl ConditionallySelectable for Scalar {
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ Self(ScalarPrimitive::conditional_select(&a.0, &b.0, choice))
+ }
+}
+
+impl ConstantTimeEq for Scalar {
+ fn ct_eq(&self, other: &Self) -> Choice {
+ self.0.ct_eq(&other.0)
+ }
+}
+
+impl DefaultIsZeroes for Scalar {}
+
+impl Add<Scalar> for Scalar {
+ type Output = Scalar;
+
+ fn add(self, other: Scalar) -> Scalar {
+ self.add(&other)
+ }
+}
+
+impl Add<&Scalar> for Scalar {
+ type Output = Scalar;
+
+ fn add(self, other: &Scalar) -> Scalar {
+ Self(self.0.add(&other.0))
+ }
+}
+
+impl AddAssign<Scalar> for Scalar {
+ fn add_assign(&mut self, other: Scalar) {
+ *self = *self + other;
+ }
+}
+
+impl AddAssign<&Scalar> for Scalar {
+ fn add_assign(&mut self, other: &Scalar) {
+ *self = *self + other;
+ }
+}
+
+impl Sub<Scalar> for Scalar {
+ type Output = Scalar;
+
+ fn sub(self, other: Scalar) -> Scalar {
+ self.sub(&other)
+ }
+}
+
+impl Sub<&Scalar> for Scalar {
+ type Output = Scalar;
+
+ fn sub(self, other: &Scalar) -> Scalar {
+ Self(self.0.sub(&other.0))
+ }
+}
+
+impl SubAssign<Scalar> for Scalar {
+ fn sub_assign(&mut self, other: Scalar) {
+ *self = *self - other;
+ }
+}
+
+impl SubAssign<&Scalar> for Scalar {
+ fn sub_assign(&mut self, other: &Scalar) {
+ *self = *self - other;
+ }
+}
+
+impl Mul<Scalar> for Scalar {
+ type Output = Scalar;
+
+ fn mul(self, _other: Scalar) -> Scalar {
+ unimplemented!();
+ }
+}
+
+impl Mul<&Scalar> for Scalar {
+ type Output = Scalar;
+
+ fn mul(self, _other: &Scalar) -> Scalar {
+ unimplemented!();
+ }
+}
+
+impl MulAssign<Scalar> for Scalar {
+ fn mul_assign(&mut self, _rhs: Scalar) {
+ unimplemented!();
+ }
+}
+
+impl MulAssign<&Scalar> for Scalar {
+ fn mul_assign(&mut self, _rhs: &Scalar) {
+ unimplemented!();
+ }
+}
+
+impl Neg for Scalar {
+ type Output = Scalar;
+
+ fn neg(self) -> Scalar {
+ Self(self.0.neg())
+ }
+}
+
+impl ShrAssign<usize> for Scalar {
+ fn shr_assign(&mut self, rhs: usize) {
+ self.0 >>= rhs;
+ }
+}
+
+impl Sum for Scalar {
+ fn sum<I: Iterator<Item = Self>>(_iter: I) -> Self {
+ unimplemented!();
+ }
+}
+
+impl<'a> Sum<&'a Scalar> for Scalar {
+ fn sum<I: Iterator<Item = &'a Scalar>>(_iter: I) -> Self {
+ unimplemented!();
+ }
+}
+
+impl Product for Scalar {
+ fn product<I: Iterator<Item = Self>>(_iter: I) -> Self {
+ unimplemented!();
+ }
+}
+
+impl<'a> Product<&'a Scalar> for Scalar {
+ fn product<I: Iterator<Item = &'a Scalar>>(_iter: I) -> Self {
+ unimplemented!();
+ }
+}
+
+impl Invert for Scalar {
+ type Output = CtOption<Scalar>;
+
+ fn invert(&self) -> CtOption<Scalar> {
+ unimplemented!();
+ }
+}
+
+impl Reduce<U256> for Scalar {
+ type Bytes = FieldBytes;
+
+ #[allow(clippy::integer_arithmetic)]
+ fn reduce(w: U256) -> Self {
+ let (r, underflow) = w.sbb(&MockCurve::ORDER, Limb::ZERO);
+ let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
+ let reduced = U256::conditional_select(&w, &r, !underflow);
+ Self(ScalarPrimitive::new(reduced).unwrap())
+ }
+
+ fn reduce_bytes(_: &FieldBytes) -> Self {
+ todo!()
+ }
+}
+
+impl FieldBytesEncoding<MockCurve> for U256 {}
+
+impl From<u64> for Scalar {
+ fn from(n: u64) -> Scalar {
+ Self(n.into())
+ }
+}
+
+impl From<ScalarPrimitive> for Scalar {
+ fn from(scalar: ScalarPrimitive) -> Scalar {
+ Self(scalar)
+ }
+}
+
+impl From<Scalar> for ScalarPrimitive {
+ fn from(scalar: Scalar) -> ScalarPrimitive {
+ scalar.0
+ }
+}
+
+impl From<Scalar> for U256 {
+ fn from(scalar: Scalar) -> U256 {
+ scalar.0.to_uint()
+ }
+}
+
+impl TryFrom<U256> for Scalar {
+ type Error = Error;
+
+ fn try_from(w: U256) -> Result<Self> {
+ Option::from(ScalarPrimitive::new(w)).map(Self).ok_or(Error)
+ }
+}
+
+impl FromUintUnchecked for Scalar {
+ type Uint = U256;
+
+ fn from_uint_unchecked(uint: U256) -> Self {
+ Self(ScalarPrimitive::from_uint_unchecked(uint))
+ }
+}
+
+impl From<Scalar> for FieldBytes {
+ fn from(scalar: Scalar) -> Self {
+ Self::from(&scalar)
+ }
+}
+
+impl From<&Scalar> for FieldBytes {
+ fn from(scalar: &Scalar) -> Self {
+ scalar.to_repr()
+ }
+}
+
+impl IsHigh for Scalar {
+ fn is_high(&self) -> Choice {
+ self.0.is_high()
+ }
+}
+
+/// Example affine point type
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum AffinePoint {
+ /// Result of fixed-based scalar multiplication.
+ FixedBaseOutput(Scalar),
+
+ /// Identity.
+ Identity,
+
+ /// Base point.
+ Generator,
+
+ /// Point corresponding to a given [`EncodedPoint`].
+ Other(EncodedPoint),
+}
+
+impl AffineCoordinates for AffinePoint {
+ type FieldRepr = FieldBytes;
+
+ fn x(&self) -> FieldBytes {
+ unimplemented!();
+ }
+
+ fn y_is_odd(&self) -> Choice {
+ unimplemented!();
+ }
+}
+
+impl ConstantTimeEq for AffinePoint {
+ fn ct_eq(&self, other: &Self) -> Choice {
+ match (self, other) {
+ (Self::FixedBaseOutput(scalar), Self::FixedBaseOutput(other_scalar)) => {
+ scalar.ct_eq(other_scalar)
+ }
+ (Self::Identity, Self::Identity) | (Self::Generator, Self::Generator) => 1.into(),
+ (Self::Other(point), Self::Other(other_point)) => u8::from(point == other_point).into(),
+ _ => 0.into(),
+ }
+ }
+}
+
+impl ConditionallySelectable for AffinePoint {
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ // Not really constant time, but this is dev code
+ if choice.into() {
+ *b
+ } else {
+ *a
+ }
+ }
+}
+
+impl Default for AffinePoint {
+ fn default() -> Self {
+ Self::Identity
+ }
+}
+
+impl DefaultIsZeroes for AffinePoint {}
+
+impl FromEncodedPoint<MockCurve> for AffinePoint {
+ fn from_encoded_point(encoded_point: &EncodedPoint) -> CtOption<Self> {
+ let point = if encoded_point.is_identity() {
+ Self::Identity
+ } else {
+ Self::Other(*encoded_point)
+ };
+
+ CtOption::new(point, Choice::from(1))
+ }
+}
+
+impl ToEncodedPoint<MockCurve> for AffinePoint {
+ fn to_encoded_point(&self, compress: bool) -> EncodedPoint {
+ match self {
+ Self::FixedBaseOutput(scalar) => EncodedPoint::from_affine_coordinates(
+ &scalar.to_repr(),
+ &PSEUDO_COORDINATE_FIXED_BASE_MUL.into(),
+ false,
+ ),
+ Self::Other(point) => {
+ if compress == point.is_compressed() {
+ *point
+ } else {
+ unimplemented!();
+ }
+ }
+ _ => unimplemented!(),
+ }
+ }
+}
+
+impl Mul<NonZeroScalar> for AffinePoint {
+ type Output = AffinePoint;
+
+ fn mul(self, _scalar: NonZeroScalar) -> Self {
+ unimplemented!();
+ }
+}
+
+/// Example projective point type
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ProjectivePoint {
+ /// Result of fixed-based scalar multiplication
+ FixedBaseOutput(Scalar),
+
+ /// Is this point the identity point?
+ Identity,
+
+ /// Is this point the generator point?
+ Generator,
+
+ /// Is this point a different point corresponding to a given [`AffinePoint`]
+ Other(AffinePoint),
+}
+
+impl ConstantTimeEq for ProjectivePoint {
+ fn ct_eq(&self, other: &Self) -> Choice {
+ match (self, other) {
+ (Self::FixedBaseOutput(scalar), Self::FixedBaseOutput(other_scalar)) => {
+ scalar.ct_eq(other_scalar)
+ }
+ (Self::Identity, Self::Identity) | (Self::Generator, Self::Generator) => 1.into(),
+ (Self::Other(point), Self::Other(other_point)) => point.ct_eq(other_point),
+ _ => 0.into(),
+ }
+ }
+}
+
+impl ConditionallySelectable for ProjectivePoint {
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ if choice.into() {
+ *b
+ } else {
+ *a
+ }
+ }
+}
+
+impl Default for ProjectivePoint {
+ fn default() -> Self {
+ Self::Identity
+ }
+}
+
+impl DefaultIsZeroes for ProjectivePoint {}
+
+impl From<AffinePoint> for ProjectivePoint {
+ fn from(point: AffinePoint) -> ProjectivePoint {
+ match point {
+ AffinePoint::FixedBaseOutput(scalar) => ProjectivePoint::FixedBaseOutput(scalar),
+ AffinePoint::Identity => ProjectivePoint::Identity,
+ AffinePoint::Generator => ProjectivePoint::Generator,
+ other => ProjectivePoint::Other(other),
+ }
+ }
+}
+
+impl From<ProjectivePoint> for AffinePoint {
+ fn from(point: ProjectivePoint) -> AffinePoint {
+ group::Curve::to_affine(&point)
+ }
+}
+
+impl FromEncodedPoint<MockCurve> for ProjectivePoint {
+ fn from_encoded_point(_point: &EncodedPoint) -> CtOption<Self> {
+ unimplemented!();
+ }
+}
+
+impl ToEncodedPoint<MockCurve> for ProjectivePoint {
+ fn to_encoded_point(&self, _compress: bool) -> EncodedPoint {
+ unimplemented!();
+ }
+}
+
+impl group::Group for ProjectivePoint {
+ type Scalar = Scalar;
+
+ fn random(_rng: impl RngCore) -> Self {
+ unimplemented!();
+ }
+
+ fn identity() -> Self {
+ Self::Identity
+ }
+
+ fn generator() -> Self {
+ Self::Generator
+ }
+
+ fn is_identity(&self) -> Choice {
+ Choice::from(u8::from(self == &Self::Identity))
+ }
+
+ #[must_use]
+ fn double(&self) -> Self {
+ unimplemented!();
+ }
+}
+
+impl group::GroupEncoding for AffinePoint {
+ type Repr = CompressedPoint<MockCurve>;
+
+ fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
+ EncodedPoint::from_bytes(bytes)
+ .map(|point| CtOption::new(point, Choice::from(1)))
+ .unwrap_or_else(|_| {
+ let is_identity = bytes.ct_eq(&Self::Repr::default());
+ CtOption::new(EncodedPoint::identity(), is_identity)
+ })
+ .and_then(|point| Self::from_encoded_point(&point))
+ }
+
+ fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
+ Self::from_bytes(bytes)
+ }
+
+ fn to_bytes(&self) -> Self::Repr {
+ let encoded = self.to_encoded_point(true);
+ let mut result = CompressedPoint::<MockCurve>::default();
+ result[..encoded.len()].copy_from_slice(encoded.as_bytes());
+ result
+ }
+}
+
+impl group::GroupEncoding for ProjectivePoint {
+ type Repr = CompressedPoint<MockCurve>;
+
+ fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
+ <AffinePoint as group::GroupEncoding>::from_bytes(bytes).map(Into::into)
+ }
+
+ fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
+ Self::from_bytes(bytes)
+ }
+
+ fn to_bytes(&self) -> Self::Repr {
+ group::Curve::to_affine(self).to_bytes()
+ }
+}
+
+impl group::Curve for ProjectivePoint {
+ type AffineRepr = AffinePoint;
+
+ fn to_affine(&self) -> AffinePoint {
+ match self {
+ Self::FixedBaseOutput(scalar) => AffinePoint::FixedBaseOutput(*scalar),
+ Self::Other(affine) => *affine,
+ _ => unimplemented!(),
+ }
+ }
+}
+
+impl LinearCombination for ProjectivePoint {}
+
+impl Add<ProjectivePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn add(self, _other: ProjectivePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl Add<&ProjectivePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn add(self, _other: &ProjectivePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl AddAssign<ProjectivePoint> for ProjectivePoint {
+ fn add_assign(&mut self, _rhs: ProjectivePoint) {
+ unimplemented!();
+ }
+}
+
+impl AddAssign<&ProjectivePoint> for ProjectivePoint {
+ fn add_assign(&mut self, _rhs: &ProjectivePoint) {
+ unimplemented!();
+ }
+}
+
+impl Sub<ProjectivePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn sub(self, _other: ProjectivePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl Sub<&ProjectivePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn sub(self, _other: &ProjectivePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl SubAssign<ProjectivePoint> for ProjectivePoint {
+ fn sub_assign(&mut self, _rhs: ProjectivePoint) {
+ unimplemented!();
+ }
+}
+
+impl SubAssign<&ProjectivePoint> for ProjectivePoint {
+ fn sub_assign(&mut self, _rhs: &ProjectivePoint) {
+ unimplemented!();
+ }
+}
+
+impl Add<AffinePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn add(self, _other: AffinePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl Add<&AffinePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn add(self, _other: &AffinePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl AddAssign<AffinePoint> for ProjectivePoint {
+ fn add_assign(&mut self, _rhs: AffinePoint) {
+ unimplemented!();
+ }
+}
+
+impl AddAssign<&AffinePoint> for ProjectivePoint {
+ fn add_assign(&mut self, _rhs: &AffinePoint) {
+ unimplemented!();
+ }
+}
+
+impl Sum for ProjectivePoint {
+ fn sum<I: Iterator<Item = Self>>(_iter: I) -> Self {
+ unimplemented!();
+ }
+}
+
+impl<'a> Sum<&'a ProjectivePoint> for ProjectivePoint {
+ fn sum<I: Iterator<Item = &'a ProjectivePoint>>(_iter: I) -> Self {
+ unimplemented!();
+ }
+}
+
+impl Sub<AffinePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn sub(self, _other: AffinePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl Sub<&AffinePoint> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn sub(self, _other: &AffinePoint) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+impl SubAssign<AffinePoint> for ProjectivePoint {
+ fn sub_assign(&mut self, _rhs: AffinePoint) {
+ unimplemented!();
+ }
+}
+
+impl SubAssign<&AffinePoint> for ProjectivePoint {
+ fn sub_assign(&mut self, _rhs: &AffinePoint) {
+ unimplemented!();
+ }
+}
+
+impl Mul<Scalar> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn mul(self, scalar: Scalar) -> ProjectivePoint {
+ match self {
+ Self::Generator => Self::FixedBaseOutput(scalar),
+ _ => unimplemented!(),
+ }
+ }
+}
+
+impl Mul<&Scalar> for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn mul(self, scalar: &Scalar) -> ProjectivePoint {
+ self * *scalar
+ }
+}
+
+impl MulAssign<Scalar> for ProjectivePoint {
+ fn mul_assign(&mut self, _rhs: Scalar) {
+ unimplemented!();
+ }
+}
+
+impl MulAssign<&Scalar> for ProjectivePoint {
+ fn mul_assign(&mut self, _rhs: &Scalar) {
+ unimplemented!();
+ }
+}
+
+impl MulByGenerator for ProjectivePoint {}
+
+impl Neg for ProjectivePoint {
+ type Output = ProjectivePoint;
+
+ fn neg(self) -> ProjectivePoint {
+ unimplemented!();
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::Scalar;
+ use ff::PrimeField;
+ use hex_literal::hex;
+
+ #[test]
+ fn round_trip() {
+ let bytes = hex!("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
+ let scalar = Scalar::from_repr(bytes.into()).unwrap();
+ assert_eq!(&bytes, scalar.to_repr().as_slice());
+ }
+}
diff --git a/vendor/elliptic-curve/src/ecdh.rs b/vendor/elliptic-curve/src/ecdh.rs
new file mode 100644
index 0000000..c64a696
--- /dev/null
+++ b/vendor/elliptic-curve/src/ecdh.rs
@@ -0,0 +1,236 @@
+//! Elliptic Curve Diffie-Hellman Support.
+//!
+//! This module contains a generic ECDH implementation which is usable with
+//! any elliptic curve which implements the [`CurveArithmetic`] trait (presently
+//! the `k256` and `p256` crates)
+//!
+//! # ECDH Ephemeral (ECDHE) Usage
+//!
+//! Ephemeral Diffie-Hellman provides a one-time key exchange between two peers
+//! using a randomly generated set of keys for each exchange.
+//!
+//! In practice ECDHE is used as part of an [Authenticated Key Exchange (AKE)][AKE]
+//! protocol (e.g. [SIGMA]), where an existing cryptographic trust relationship
+//! can be used to determine the authenticity of the ephemeral keys, such as
+//! a digital signature. Without such an additional step, ECDHE is insecure!
+//! (see security warning below)
+//!
+//! See the documentation for the [`EphemeralSecret`] type for more information
+//! on performing ECDH ephemeral key exchanges.
+//!
+//! # Static ECDH Usage
+//!
+//! Static ECDH key exchanges are supported via the low-level
+//! [`diffie_hellman`] function.
+//!
+//! [AKE]: https://en.wikipedia.org/wiki/Authenticated_Key_Exchange
+//! [SIGMA]: https://webee.technion.ac.il/~hugo/sigma-pdf.pdf
+
+use crate::{
+ point::AffineCoordinates, AffinePoint, Curve, CurveArithmetic, FieldBytes, NonZeroScalar,
+ ProjectivePoint, PublicKey,
+};
+use core::borrow::Borrow;
+use digest::{crypto_common::BlockSizeUser, Digest};
+use group::Curve as _;
+use hkdf::{hmac::SimpleHmac, Hkdf};
+use rand_core::CryptoRngCore;
+use zeroize::{Zeroize, ZeroizeOnDrop};
+
+/// Low-level Elliptic Curve Diffie-Hellman (ECDH) function.
+///
+/// Whenever possible, we recommend using the high-level ECDH ephemeral API
+/// provided by [`EphemeralSecret`].
+///
+/// However, if you are implementing a protocol which requires a static scalar
+/// value as part of an ECDH exchange, this API can be used to compute a
+/// [`SharedSecret`] from that value.
+///
+/// Note that this API operates on the low-level [`NonZeroScalar`] and
+/// [`AffinePoint`] types. If you are attempting to use the higher-level
+/// [`SecretKey`][`crate::SecretKey`] and [`PublicKey`] types, you will
+/// need to use the following conversions:
+///
+/// ```ignore
+/// let shared_secret = elliptic_curve::ecdh::diffie_hellman(
+/// secret_key.to_nonzero_scalar(),
+/// public_key.as_affine()
+/// );
+/// ```
+pub fn diffie_hellman<C>(
+ secret_key: impl Borrow<NonZeroScalar<C>>,
+ public_key: impl Borrow<AffinePoint<C>>,
+) -> SharedSecret<C>
+where
+ C: CurveArithmetic,
+{
+ let public_point = ProjectivePoint::<C>::from(*public_key.borrow());
+ let secret_point = (public_point * secret_key.borrow().as_ref()).to_affine();
+ SharedSecret::new(secret_point)
+}
+
+/// Ephemeral Diffie-Hellman Secret.
+///
+/// These are ephemeral "secret key" values which are deliberately designed
+/// to avoid being persisted.
+///
+/// To perform an ephemeral Diffie-Hellman exchange, do the following:
+///
+/// - Have each participant generate an [`EphemeralSecret`] value
+/// - Compute the [`PublicKey`] for that value
+/// - Have each peer provide their [`PublicKey`] to their counterpart
+/// - Use [`EphemeralSecret`] and the other participant's [`PublicKey`]
+/// to compute a [`SharedSecret`] value.
+///
+/// # ⚠️ SECURITY WARNING ⚠️
+///
+/// Ephemeral Diffie-Hellman exchanges are unauthenticated and without a
+/// further authentication step are trivially vulnerable to man-in-the-middle
+/// attacks!
+///
+/// These exchanges should be performed in the context of a protocol which
+/// takes further steps to authenticate the peers in a key exchange.
+pub struct EphemeralSecret<C>
+where
+ C: CurveArithmetic,
+{
+ scalar: NonZeroScalar<C>,
+}
+
+impl<C> EphemeralSecret<C>
+where
+ C: CurveArithmetic,
+{
+ /// Generate a cryptographically random [`EphemeralSecret`].
+ pub fn random(rng: &mut impl CryptoRngCore) -> Self {
+ Self {
+ scalar: NonZeroScalar::random(rng),
+ }
+ }
+
+ /// Get the public key associated with this ephemeral secret.
+ ///
+ /// The `compress` flag enables point compression.
+ pub fn public_key(&self) -> PublicKey<C> {
+ PublicKey::from_secret_scalar(&self.scalar)
+ }
+
+ /// Compute a Diffie-Hellman shared secret from an ephemeral secret and the
+ /// public key of the other participant in the exchange.
+ pub fn diffie_hellman(&self, public_key: &PublicKey<C>) -> SharedSecret<C> {
+ diffie_hellman(self.scalar, public_key.as_affine())
+ }
+}
+
+impl<C> From<&EphemeralSecret<C>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(ephemeral_secret: &EphemeralSecret<C>) -> Self {
+ ephemeral_secret.public_key()
+ }
+}
+
+impl<C> Zeroize for EphemeralSecret<C>
+where
+ C: CurveArithmetic,
+{
+ fn zeroize(&mut self) {
+ self.scalar.zeroize()
+ }
+}
+
+impl<C> ZeroizeOnDrop for EphemeralSecret<C> where C: CurveArithmetic {}
+
+impl<C> Drop for EphemeralSecret<C>
+where
+ C: CurveArithmetic,
+{
+ fn drop(&mut self) {
+ self.zeroize();
+ }
+}
+
+/// Shared secret value computed via ECDH key agreement.
+pub struct SharedSecret<C: Curve> {
+ /// Computed secret value
+ secret_bytes: FieldBytes<C>,
+}
+
+impl<C: Curve> SharedSecret<C> {
+ /// Create a new [`SharedSecret`] from an [`AffinePoint`] for this curve.
+ #[inline]
+ fn new(point: AffinePoint<C>) -> Self
+ where
+ C: CurveArithmetic,
+ {
+ Self {
+ secret_bytes: point.x(),
+ }
+ }
+
+ /// Use [HKDF] (HMAC-based Extract-and-Expand Key Derivation Function) to
+ /// extract entropy from this shared secret.
+ ///
+ /// This method can be used to transform the shared secret into uniformly
+ /// random values which are suitable as key material.
+ ///
+ /// The `D` type parameter is a cryptographic digest function.
+ /// `sha2::Sha256` is a common choice for use with HKDF.
+ ///
+ /// The `salt` parameter can be used to supply additional randomness.
+ /// Some examples include:
+ ///
+ /// - randomly generated (but authenticated) string
+ /// - fixed application-specific value
+ /// - previous shared secret used for rekeying (as in TLS 1.3 and Noise)
+ ///
+ /// After initializing HKDF, use [`Hkdf::expand`] to obtain output key
+ /// material.
+ ///
+ /// [HKDF]: https://en.wikipedia.org/wiki/HKDF
+ pub fn extract<D>(&self, salt: Option<&[u8]>) -> Hkdf<D, SimpleHmac<D>>
+ where
+ D: BlockSizeUser + Clone + Digest,
+ {
+ Hkdf::new(salt, &self.secret_bytes)
+ }
+
+ /// This value contains the raw serialized x-coordinate of the elliptic curve
+ /// point computed from a Diffie-Hellman exchange, serialized as bytes.
+ ///
+ /// When in doubt, use [`SharedSecret::extract`] instead.
+ ///
+ /// # ⚠️ WARNING: NOT UNIFORMLY RANDOM! ⚠️
+ ///
+ /// This value is not uniformly random and should not be used directly
+ /// as a cryptographic key for anything which requires that property
+ /// (e.g. symmetric ciphers).
+ ///
+ /// Instead, the resulting value should be used as input to a Key Derivation
+ /// Function (KDF) or cryptographic hash function to produce a symmetric key.
+ /// The [`SharedSecret::extract`] function will do this for you.
+ pub fn raw_secret_bytes(&self) -> &FieldBytes<C> {
+ &self.secret_bytes
+ }
+}
+
+impl<C: Curve> From<FieldBytes<C>> for SharedSecret<C> {
+ /// NOTE: this impl is intended to be used by curve implementations to
+ /// instantiate a [`SharedSecret`] value from their respective
+ /// [`AffinePoint`] type.
+ ///
+ /// Curve implementations should provide the field element representing
+ /// the affine x-coordinate as `secret_bytes`.
+ fn from(secret_bytes: FieldBytes<C>) -> Self {
+ Self { secret_bytes }
+ }
+}
+
+impl<C: Curve> ZeroizeOnDrop for SharedSecret<C> {}
+
+impl<C: Curve> Drop for SharedSecret<C> {
+ fn drop(&mut self) {
+ self.secret_bytes.zeroize()
+ }
+}
diff --git a/vendor/elliptic-curve/src/error.rs b/vendor/elliptic-curve/src/error.rs
new file mode 100644
index 0000000..53f5b17
--- /dev/null
+++ b/vendor/elliptic-curve/src/error.rs
@@ -0,0 +1,42 @@
+//! Error type.
+
+use core::fmt::{self, Display};
+
+#[cfg(feature = "pkcs8")]
+use crate::pkcs8;
+
+/// Result type with the `elliptic-curve` crate's [`Error`] type.
+pub type Result<T> = core::result::Result<T, Error>;
+
+/// Elliptic curve errors.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Error;
+
+impl Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("crypto error")
+ }
+}
+
+impl From<base16ct::Error> for Error {
+ fn from(_: base16ct::Error) -> Error {
+ Error
+ }
+}
+
+#[cfg(feature = "pkcs8")]
+impl From<pkcs8::Error> for Error {
+ fn from(_: pkcs8::Error) -> Error {
+ Error
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl From<sec1::Error> for Error {
+ fn from(_: sec1::Error) -> Error {
+ Error
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
diff --git a/vendor/elliptic-curve/src/field.rs b/vendor/elliptic-curve/src/field.rs
new file mode 100644
index 0000000..66055ab
--- /dev/null
+++ b/vendor/elliptic-curve/src/field.rs
@@ -0,0 +1,51 @@
+//! Field elements.
+
+use crate::{
+ bigint::{ArrayEncoding, ByteArray, Integer},
+ Curve,
+};
+use generic_array::{typenum::Unsigned, GenericArray};
+
+/// Size of serialized field elements of this elliptic curve.
+pub type FieldBytesSize<C> = <C as Curve>::FieldBytesSize;
+
+/// Byte representation of a base/scalar field element of a given curve.
+pub type FieldBytes<C> = GenericArray<u8, FieldBytesSize<C>>;
+
+/// Trait for decoding/encoding `Curve::Uint` from/to [`FieldBytes`] using
+/// curve-specific rules.
+///
+/// Namely a curve's modulus may be smaller than the big integer type used to
+/// internally represent field elements (since the latter are multiples of the
+/// limb size), such as in the case of curves like NIST P-224 and P-521, and so
+/// it may need to be padded/truncated to the right length.
+///
+/// Additionally, different curves have different endianness conventions, also
+/// captured here.
+pub trait FieldBytesEncoding<C>: ArrayEncoding + Integer
+where
+ C: Curve,
+{
+ /// Decode unsigned integer from serialized field element.
+ ///
+ /// The default implementation assumes a big endian encoding.
+ fn decode_field_bytes(field_bytes: &FieldBytes<C>) -> Self {
+ debug_assert!(field_bytes.len() <= Self::ByteSize::USIZE);
+ let mut byte_array = ByteArray::<Self>::default();
+ let offset = Self::ByteSize::USIZE.saturating_sub(field_bytes.len());
+ byte_array[offset..].copy_from_slice(field_bytes);
+ Self::from_be_byte_array(byte_array)
+ }
+
+ /// Encode unsigned integer into serialized field element.
+ ///
+ /// The default implementation assumes a big endian encoding.
+ fn encode_field_bytes(&self) -> FieldBytes<C> {
+ let mut field_bytes = FieldBytes::<C>::default();
+ debug_assert!(field_bytes.len() <= Self::ByteSize::USIZE);
+
+ let offset = Self::ByteSize::USIZE.saturating_sub(field_bytes.len());
+ field_bytes.copy_from_slice(&self.to_be_byte_array()[offset..]);
+ field_bytes
+ }
+}
diff --git a/vendor/elliptic-curve/src/hash2curve.rs b/vendor/elliptic-curve/src/hash2curve.rs
new file mode 100644
index 0000000..3df394f
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve.rs
@@ -0,0 +1,15 @@
+//! Traits for hashing byte sequences to curve points.
+//!
+//! <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve>
+
+mod group_digest;
+mod hash2field;
+mod isogeny;
+mod map2curve;
+mod osswu;
+
+pub use group_digest::*;
+pub use hash2field::*;
+pub use isogeny::*;
+pub use map2curve::*;
+pub use osswu::*;
diff --git a/vendor/elliptic-curve/src/hash2curve/group_digest.rs b/vendor/elliptic-curve/src/hash2curve/group_digest.rs
new file mode 100644
index 0000000..ea7f047
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/group_digest.rs
@@ -0,0 +1,123 @@
+//! Traits for handling hash to curve.
+
+use super::{hash_to_field, ExpandMsg, FromOkm, MapToCurve};
+use crate::{CurveArithmetic, ProjectivePoint, Result};
+use group::cofactor::CofactorGroup;
+
+/// Adds hashing arbitrary byte sequences to a valid group element
+pub trait GroupDigest: CurveArithmetic
+where
+ ProjectivePoint<Self>: CofactorGroup,
+{
+ /// The field element representation for a group value with multiple elements
+ type FieldElement: FromOkm + MapToCurve<Output = ProjectivePoint<Self>> + Default + Copy;
+
+ /// Computes the hash to curve routine.
+ ///
+ /// From <https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html>:
+ ///
+ /// > Uniform encoding from byte strings to points in G.
+ /// > That is, the distribution of its output is statistically close
+ /// > to uniform in G.
+ /// > This function is suitable for most applications requiring a random
+ /// > oracle returning points in G assuming a cryptographically secure
+ /// > hash function is used.
+ ///
+ /// # Examples
+ ///
+ /// ## Using a fixed size hash function
+ ///
+ /// ```ignore
+ /// let pt = ProjectivePoint::hash_from_bytes::<ExpandMsgXmd<sha2::Sha256>>(b"test data", b"CURVE_XMD:SHA-256_SSWU_RO_");
+ /// ```
+ ///
+ /// ## Using an extendable output function
+ ///
+ /// ```ignore
+ /// let pt = ProjectivePoint::hash_from_bytes::<ExpandMsgXof<sha3::Shake256>>(b"test data", b"CURVE_XOF:SHAKE-256_SSWU_RO_");
+ /// ```
+ ///
+ /// # Errors
+ /// See implementors of [`ExpandMsg`] for errors:
+ /// - [`ExpandMsgXmd`]
+ /// - [`ExpandMsgXof`]
+ ///
+ /// `len_in_bytes = <Self::FieldElement as FromOkm>::Length * 2`
+ ///
+ /// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd
+ /// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof
+ fn hash_from_bytes<'a, X: ExpandMsg<'a>>(
+ msgs: &[&[u8]],
+ dsts: &'a [&'a [u8]],
+ ) -> Result<ProjectivePoint<Self>> {
+ let mut u = [Self::FieldElement::default(), Self::FieldElement::default()];
+ hash_to_field::<X, _>(msgs, dsts, &mut u)?;
+ let q0 = u[0].map_to_curve();
+ let q1 = u[1].map_to_curve();
+ // Ideally we could add and then clear cofactor once
+ // thus saving a call but the field elements may not
+ // add properly due to the underlying implementation
+ // which could result in an incorrect subgroup.
+ // This is caused curve coefficients being different than
+ // what is usually implemented.
+ // FieldElement expects the `a` and `b` to be the original values
+ // isogenies are different with curves like k256 and bls12-381.
+ // This problem doesn't manifest for curves with no isogeny like p256.
+ // For k256 and p256 clear_cofactor doesn't do anything anyway so it will be a no-op.
+ Ok(q0.clear_cofactor().into() + q1.clear_cofactor())
+ }
+
+ /// Computes the encode to curve routine.
+ ///
+ /// From <https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html>:
+ ///
+ /// > Nonuniform encoding from byte strings to
+ /// > points in G. That is, the distribution of its output is not
+ /// > uniformly random in G: the set of possible outputs of
+ /// > encode_to_curve is only a fraction of the points in G, and some
+ /// > points in this set are more likely to be output than others.
+ ///
+ /// # Errors
+ /// See implementors of [`ExpandMsg`] for errors:
+ /// - [`ExpandMsgXmd`]
+ /// - [`ExpandMsgXof`]
+ ///
+ /// `len_in_bytes = <Self::FieldElement as FromOkm>::Length`
+ ///
+ /// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd
+ /// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof
+ fn encode_from_bytes<'a, X: ExpandMsg<'a>>(
+ msgs: &[&[u8]],
+ dsts: &'a [&'a [u8]],
+ ) -> Result<ProjectivePoint<Self>> {
+ let mut u = [Self::FieldElement::default()];
+ hash_to_field::<X, _>(msgs, dsts, &mut u)?;
+ let q0 = u[0].map_to_curve();
+ Ok(q0.clear_cofactor().into())
+ }
+
+ /// Computes the hash to field routine according to
+ /// <https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5>
+ /// and returns a scalar.
+ ///
+ /// # Errors
+ /// See implementors of [`ExpandMsg`] for errors:
+ /// - [`ExpandMsgXmd`]
+ /// - [`ExpandMsgXof`]
+ ///
+ /// `len_in_bytes = <Self::Scalar as FromOkm>::Length`
+ ///
+ /// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd
+ /// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof
+ fn hash_to_scalar<'a, X: ExpandMsg<'a>>(
+ msgs: &[&[u8]],
+ dsts: &'a [&'a [u8]],
+ ) -> Result<Self::Scalar>
+ where
+ Self::Scalar: FromOkm,
+ {
+ let mut u = [Self::Scalar::default()];
+ hash_to_field::<X, _>(msgs, dsts, &mut u)?;
+ Ok(u[0])
+ }
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/hash2field.rs b/vendor/elliptic-curve/src/hash2curve/hash2field.rs
new file mode 100644
index 0000000..67ede11
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field.rs
@@ -0,0 +1,48 @@
+//! Traits for hashing to field elements.
+//!
+//! <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve>
+
+mod expand_msg;
+
+pub use expand_msg::{xmd::*, xof::*, *};
+
+use crate::{Error, Result};
+use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
+
+/// The trait for helping to convert to a field element.
+pub trait FromOkm {
+ /// The number of bytes needed to convert to a field element.
+ type Length: ArrayLength<u8>;
+
+ /// Convert a byte sequence into a field element.
+ fn from_okm(data: &GenericArray<u8, Self::Length>) -> Self;
+}
+
+/// Convert an arbitrary byte sequence into a field element.
+///
+/// <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3>
+///
+/// # Errors
+/// See implementors of [`ExpandMsg`] for errors:
+/// - [`ExpandMsgXmd`]
+/// - [`ExpandMsgXof`]
+///
+/// `len_in_bytes = T::Length * out.len()`
+///
+/// [`ExpandMsgXmd`]: crate::hash2field::ExpandMsgXmd
+/// [`ExpandMsgXof`]: crate::hash2field::ExpandMsgXof
+#[doc(hidden)]
+pub fn hash_to_field<'a, E, T>(data: &[&[u8]], domain: &'a [&'a [u8]], out: &mut [T]) -> Result<()>
+where
+ E: ExpandMsg<'a>,
+ T: FromOkm + Default,
+{
+ let len_in_bytes = T::Length::to_usize().checked_mul(out.len()).ok_or(Error)?;
+ let mut tmp = GenericArray::<u8, <T as FromOkm>::Length>::default();
+ let mut expander = E::expand_message(data, domain, len_in_bytes)?;
+ for o in out.iter_mut() {
+ expander.fill_bytes(&mut tmp);
+ *o = T::from_okm(&tmp);
+ }
+ Ok(())
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs
new file mode 100644
index 0000000..96a659b
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs
@@ -0,0 +1,145 @@
+//! `expand_message` interface `for hash_to_field`.
+
+pub(super) mod xmd;
+pub(super) mod xof;
+
+use crate::{Error, Result};
+use digest::{Digest, ExtendableOutput, Update, XofReader};
+use generic_array::typenum::{IsLess, U256};
+use generic_array::{ArrayLength, GenericArray};
+
+/// Salt when the DST is too long
+const OVERSIZE_DST_SALT: &[u8] = b"H2C-OVERSIZE-DST-";
+/// Maximum domain separation tag length
+const MAX_DST_LEN: usize = 255;
+
+/// Trait for types implementing expand_message interface for `hash_to_field`.
+///
+/// # Errors
+/// See implementors of [`ExpandMsg`] for errors.
+pub trait ExpandMsg<'a> {
+ /// Type holding data for the [`Expander`].
+ type Expander: Expander + Sized;
+
+ /// Expands `msg` to the required number of bytes.
+ ///
+ /// Returns an expander that can be used to call `read` until enough
+ /// bytes have been consumed
+ fn expand_message(
+ msgs: &[&[u8]],
+ dsts: &'a [&'a [u8]],
+ len_in_bytes: usize,
+ ) -> Result<Self::Expander>;
+}
+
+/// Expander that, call `read` until enough bytes have been consumed.
+pub trait Expander {
+ /// Fill the array with the expanded bytes
+ fn fill_bytes(&mut self, okm: &mut [u8]);
+}
+
+/// The domain separation tag
+///
+/// Implements [section 5.4.3 of `draft-irtf-cfrg-hash-to-curve-13`][dst].
+///
+/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-13#section-5.4.3
+pub(crate) enum Domain<'a, L>
+where
+ L: ArrayLength<u8> + IsLess<U256>,
+{
+ /// > 255
+ Hashed(GenericArray<u8, L>),
+ /// <= 255
+ Array(&'a [&'a [u8]]),
+}
+
+impl<'a, L> Domain<'a, L>
+where
+ L: ArrayLength<u8> + IsLess<U256>,
+{
+ pub fn xof<X>(dsts: &'a [&'a [u8]]) -> Result<Self>
+ where
+ X: Default + ExtendableOutput + Update,
+ {
+ if dsts.is_empty() {
+ Err(Error)
+ } else if dsts.iter().map(|dst| dst.len()).sum::<usize>() > MAX_DST_LEN {
+ let mut data = GenericArray::<u8, L>::default();
+ let mut hash = X::default();
+ hash.update(OVERSIZE_DST_SALT);
+
+ for dst in dsts {
+ hash.update(dst);
+ }
+
+ hash.finalize_xof().read(&mut data);
+
+ Ok(Self::Hashed(data))
+ } else {
+ Ok(Self::Array(dsts))
+ }
+ }
+
+ pub fn xmd<X>(dsts: &'a [&'a [u8]]) -> Result<Self>
+ where
+ X: Digest<OutputSize = L>,
+ {
+ if dsts.is_empty() {
+ Err(Error)
+ } else if dsts.iter().map(|dst| dst.len()).sum::<usize>() > MAX_DST_LEN {
+ Ok(Self::Hashed({
+ let mut hash = X::new();
+ hash.update(OVERSIZE_DST_SALT);
+
+ for dst in dsts {
+ hash.update(dst);
+ }
+
+ hash.finalize()
+ }))
+ } else {
+ Ok(Self::Array(dsts))
+ }
+ }
+
+ pub fn update_hash<HashT: Update>(&self, hash: &mut HashT) {
+ match self {
+ Self::Hashed(d) => hash.update(d),
+ Self::Array(d) => {
+ for d in d.iter() {
+ hash.update(d)
+ }
+ }
+ }
+ }
+
+ pub fn len(&self) -> u8 {
+ match self {
+ // Can't overflow because it's enforced on a type level.
+ Self::Hashed(_) => L::to_u8(),
+ // Can't overflow because it's checked on creation.
+ Self::Array(d) => {
+ u8::try_from(d.iter().map(|d| d.len()).sum::<usize>()).expect("length overflow")
+ }
+ }
+ }
+
+ #[cfg(test)]
+ pub fn assert(&self, bytes: &[u8]) {
+ let data = match self {
+ Domain::Hashed(d) => d.to_vec(),
+ Domain::Array(d) => d.iter().copied().flatten().copied().collect(),
+ };
+ assert_eq!(data, bytes);
+ }
+
+ #[cfg(test)]
+ pub fn assert_dst(&self, bytes: &[u8]) {
+ let data = match self {
+ Domain::Hashed(d) => d.to_vec(),
+ Domain::Array(d) => d.iter().copied().flatten().copied().collect(),
+ };
+ assert_eq!(data, &bytes[..bytes.len() - 1]);
+ assert_eq!(self.len(), bytes[bytes.len() - 1]);
+ }
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs
new file mode 100644
index 0000000..50edb64
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs
@@ -0,0 +1,453 @@
+//! `expand_message_xmd` based on a hash function.
+
+// TODO(tarcieri): checked arithmetic
+#![allow(clippy::integer_arithmetic)]
+
+use core::marker::PhantomData;
+
+use super::{Domain, ExpandMsg, Expander};
+use crate::{Error, Result};
+use digest::{
+ core_api::BlockSizeUser,
+ generic_array::{
+ typenum::{IsLess, IsLessOrEqual, Unsigned, U256},
+ GenericArray,
+ },
+ FixedOutput, HashMarker,
+};
+
+/// Placeholder type for implementing `expand_message_xmd` based on a hash function
+///
+/// # Errors
+/// - `dst.is_empty()`
+/// - `len_in_bytes == 0`
+/// - `len_in_bytes > u16::MAX`
+/// - `len_in_bytes > 255 * HashT::OutputSize`
+pub struct ExpandMsgXmd<HashT>(PhantomData<HashT>)
+where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ HashT::OutputSize: IsLess<U256>,
+ HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>;
+
+/// ExpandMsgXmd implements expand_message_xmd for the ExpandMsg trait
+impl<'a, HashT> ExpandMsg<'a> for ExpandMsgXmd<HashT>
+where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ // If `len_in_bytes` is bigger then 256, length of the `DST` will depend on
+ // the output size of the hash, which is still not allowed to be bigger then 256:
+ // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5.4.1-6
+ HashT::OutputSize: IsLess<U256>,
+ // Constraint set by `expand_message_xmd`:
+ // https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5.4.1-4
+ HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
+{
+ type Expander = ExpanderXmd<'a, HashT>;
+
+ fn expand_message(
+ msgs: &[&[u8]],
+ dsts: &'a [&'a [u8]],
+ len_in_bytes: usize,
+ ) -> Result<Self::Expander> {
+ if len_in_bytes == 0 {
+ return Err(Error);
+ }
+
+ let len_in_bytes_u16 = u16::try_from(len_in_bytes).map_err(|_| Error)?;
+
+ let b_in_bytes = HashT::OutputSize::to_usize();
+ let ell = u8::try_from((len_in_bytes + b_in_bytes - 1) / b_in_bytes).map_err(|_| Error)?;
+
+ let domain = Domain::xmd::<HashT>(dsts)?;
+ let mut b_0 = HashT::default();
+ b_0.update(&GenericArray::<u8, HashT::BlockSize>::default());
+
+ for msg in msgs {
+ b_0.update(msg);
+ }
+
+ b_0.update(&len_in_bytes_u16.to_be_bytes());
+ b_0.update(&[0]);
+ domain.update_hash(&mut b_0);
+ b_0.update(&[domain.len()]);
+ let b_0 = b_0.finalize_fixed();
+
+ let mut b_vals = HashT::default();
+ b_vals.update(&b_0[..]);
+ b_vals.update(&[1u8]);
+ domain.update_hash(&mut b_vals);
+ b_vals.update(&[domain.len()]);
+ let b_vals = b_vals.finalize_fixed();
+
+ Ok(ExpanderXmd {
+ b_0,
+ b_vals,
+ domain,
+ index: 1,
+ offset: 0,
+ ell,
+ })
+ }
+}
+
+/// [`Expander`] type for [`ExpandMsgXmd`].
+pub struct ExpanderXmd<'a, HashT>
+where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ HashT::OutputSize: IsLess<U256>,
+ HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
+{
+ b_0: GenericArray<u8, HashT::OutputSize>,
+ b_vals: GenericArray<u8, HashT::OutputSize>,
+ domain: Domain<'a, HashT::OutputSize>,
+ index: u8,
+ offset: usize,
+ ell: u8,
+}
+
+impl<'a, HashT> ExpanderXmd<'a, HashT>
+where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ HashT::OutputSize: IsLess<U256>,
+ HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
+{
+ fn next(&mut self) -> bool {
+ if self.index < self.ell {
+ self.index += 1;
+ self.offset = 0;
+ // b_0 XOR b_(idx - 1)
+ let mut tmp = GenericArray::<u8, HashT::OutputSize>::default();
+ self.b_0
+ .iter()
+ .zip(&self.b_vals[..])
+ .enumerate()
+ .for_each(|(j, (b0val, bi1val))| tmp[j] = b0val ^ bi1val);
+ let mut b_vals = HashT::default();
+ b_vals.update(&tmp);
+ b_vals.update(&[self.index]);
+ self.domain.update_hash(&mut b_vals);
+ b_vals.update(&[self.domain.len()]);
+ self.b_vals = b_vals.finalize_fixed();
+ true
+ } else {
+ false
+ }
+ }
+}
+
+impl<'a, HashT> Expander for ExpanderXmd<'a, HashT>
+where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ HashT::OutputSize: IsLess<U256>,
+ HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
+{
+ fn fill_bytes(&mut self, okm: &mut [u8]) {
+ for b in okm {
+ if self.offset == self.b_vals.len() && !self.next() {
+ return;
+ }
+ *b = self.b_vals[self.offset];
+ self.offset += 1;
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use core::mem;
+ use generic_array::{
+ typenum::{U128, U32},
+ ArrayLength,
+ };
+ use hex_literal::hex;
+ use sha2::Sha256;
+
+ fn assert_message<HashT>(
+ msg: &[u8],
+ domain: &Domain<'_, HashT::OutputSize>,
+ len_in_bytes: u16,
+ bytes: &[u8],
+ ) where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ HashT::OutputSize: IsLess<U256>,
+ {
+ let block = HashT::BlockSize::to_usize();
+ assert_eq!(
+ GenericArray::<u8, HashT::BlockSize>::default().as_slice(),
+ &bytes[..block]
+ );
+
+ let msg_len = block + msg.len();
+ assert_eq!(msg, &bytes[block..msg_len]);
+
+ let l = msg_len + mem::size_of::<u16>();
+ assert_eq!(len_in_bytes.to_be_bytes(), &bytes[msg_len..l]);
+
+ let pad = l + mem::size_of::<u8>();
+ assert_eq!([0], &bytes[l..pad]);
+
+ let dst = pad + usize::from(domain.len());
+ domain.assert(&bytes[pad..dst]);
+
+ let dst_len = dst + mem::size_of::<u8>();
+ assert_eq!([domain.len()], &bytes[dst..dst_len]);
+
+ assert_eq!(dst_len, bytes.len());
+ }
+
+ struct TestVector {
+ msg: &'static [u8],
+ msg_prime: &'static [u8],
+ uniform_bytes: &'static [u8],
+ }
+
+ impl TestVector {
+ fn assert<HashT, L: ArrayLength<u8>>(
+ &self,
+ dst: &'static [u8],
+ domain: &Domain<'_, HashT::OutputSize>,
+ ) -> Result<()>
+ where
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
+ HashT::OutputSize: IsLess<U256> + IsLessOrEqual<HashT::BlockSize>,
+ {
+ assert_message::<HashT>(self.msg, domain, L::to_u16(), self.msg_prime);
+
+ let dst = [dst];
+ let mut expander =
+ ExpandMsgXmd::<HashT>::expand_message(&[self.msg], &dst, L::to_usize())?;
+
+ let mut uniform_bytes = GenericArray::<u8, L>::default();
+ expander.fill_bytes(&mut uniform_bytes);
+
+ assert_eq!(uniform_bytes.as_slice(), self.uniform_bytes);
+ Ok(())
+ }
+ }
+
+ #[test]
+ fn expand_message_xmd_sha_256() -> Result<()> {
+ const DST: &[u8] = b"QUUX-V01-CS02-with-expander-SHA256-128";
+ const DST_PRIME: &[u8] =
+ &hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826");
+
+ let dst_prime = Domain::xmd::<Sha256>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
+
+ const TEST_VECTORS_32: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("68a985b87eb6b46952128911f2a4412bbc302a9d759667f87f7a21d803f07235"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("d8ccab23b5985ccea865c6c97b6e5b8350e794e603b4b97902f53a8a0d605615"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("eff31487c770a893cfb36f912fbfcbff40d5661771ca4b2cb4eafe524333f5c1"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("b23a1d2b4d97b2ef7785562a7e8bac7eed54ed6e97e29aa51bfe3f12ddad1ff9"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("4623227bcc01293b8c130bf771da8c298dede7383243dc0993d2d94823958c4c"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_32 {
+ test_vector.assert::<Sha256, U32>(DST, &dst_prime)?;
+ }
+
+ const TEST_VECTORS_128: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("af84c27ccfd45d41914fdff5df25293e221afc53d8ad2ac06d5e3e29485dadbee0d121587713a3e0dd4d5e69e93eb7cd4f5df4cd103e188cf60cb02edc3edf18eda8576c412b18ffb658e3dd6ec849469b979d444cf7b26911a08e63cf31f9dcc541708d3491184472c2c29bb749d4286b004ceb5ee6b9a7fa5b646c993f0ced"),
+ }, TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("abba86a6129e366fc877aab32fc4ffc70120d8996c88aee2fe4b32d6c7b6437a647e6c3163d40b76a73cf6a5674ef1d890f95b664ee0afa5359a5c4e07985635bbecbac65d747d3d2da7ec2b8221b17b0ca9dc8a1ac1c07ea6a1e60583e2cb00058e77b7b72a298425cd1b941ad4ec65e8afc50303a22c0f99b0509b4c895f40"),
+ }, TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("ef904a29bffc4cf9ee82832451c946ac3c8f8058ae97d8d629831a74c6572bd9ebd0df635cd1f208e2038e760c4994984ce73f0d55ea9f22af83ba4734569d4bc95e18350f740c07eef653cbb9f87910d833751825f0ebefa1abe5420bb52be14cf489b37fe1a72f7de2d10be453b2c9d9eb20c7e3f6edc5a60629178d9478df"),
+ }, TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("80be107d0884f0d881bb460322f0443d38bd222db8bd0b0a5312a6fedb49c1bbd88fd75d8b9a09486c60123dfa1d73c1cc3169761b17476d3c6b7cbbd727acd0e2c942f4dd96ae3da5de368d26b32286e32de7e5a8cb2949f866a0b80c58116b29fa7fabb3ea7d520ee603e0c25bcaf0b9a5e92ec6a1fe4e0391d1cdbce8c68a"),
+ }, TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826"),
+ uniform_bytes: &hex!("546aff5444b5b79aa6148bd81728704c32decb73a3ba76e9e75885cad9def1d06d6792f8a7d12794e90efed817d96920d728896a4510864370c207f99bd4a608ea121700ef01ed879745ee3e4ceef777eda6d9e5e38b90c86ea6fb0b36504ba4a45d22e86f6db5dd43d98a294bebb9125d5b794e9d2a81181066eb954966a487"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_128 {
+ test_vector.assert::<Sha256, U128>(DST, &dst_prime)?;
+ }
+
+ Ok(())
+ }
+
+ #[test]
+ fn expand_message_xmd_sha_256_long() -> Result<()> {
+ const DST: &[u8] = b"QUUX-V01-CS02-with-expander-SHA256-128-long-DST-1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
+ const DST_PRIME: &[u8] =
+ &hex!("412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620");
+
+ let dst_prime = Domain::xmd::<Sha256>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
+
+ const TEST_VECTORS_32: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("e8dc0c8b686b7ef2074086fbdd2f30e3f8bfbd3bdf177f73f04b97ce618a3ed3"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("52dbf4f36cf560fca57dedec2ad924ee9c266341d8f3d6afe5171733b16bbb12"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("35387dcf22618f3728e6c686490f8b431f76550b0b2c61cbc1ce7001536f4521"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("01b637612bb18e840028be900a833a74414140dde0c4754c198532c3a0ba42bc"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161002000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("20cce7033cabc5460743180be6fa8aac5a103f56d481cf369a8accc0c374431b"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_32 {
+ test_vector.assert::<Sha256, U32>(DST, &dst_prime)?;
+ }
+
+ const TEST_VECTORS_128: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("14604d85432c68b757e485c8894db3117992fc57e0e136f71ad987f789a0abc287c47876978e2388a02af86b1e8d1342e5ce4f7aaa07a87321e691f6fba7e0072eecc1218aebb89fb14a0662322d5edbd873f0eb35260145cd4e64f748c5dfe60567e126604bcab1a3ee2dc0778102ae8a5cfd1429ebc0fa6bf1a53c36f55dfc"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("1a30a5e36fbdb87077552b9d18b9f0aee16e80181d5b951d0471d55b66684914aef87dbb3626eaabf5ded8cd0686567e503853e5c84c259ba0efc37f71c839da2129fe81afdaec7fbdc0ccd4c794727a17c0d20ff0ea55e1389d6982d1241cb8d165762dbc39fb0cee4474d2cbbd468a835ae5b2f20e4f959f56ab24cd6fe267"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("d2ecef3635d2397f34a9f86438d772db19ffe9924e28a1caf6f1c8f15603d4028f40891044e5c7e39ebb9b31339979ff33a4249206f67d4a1e7c765410bcd249ad78d407e303675918f20f26ce6d7027ed3774512ef5b00d816e51bfcc96c3539601fa48ef1c07e494bdc37054ba96ecb9dbd666417e3de289d4f424f502a982"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("ed6e8c036df90111410431431a232d41a32c86e296c05d426e5f44e75b9a50d335b2412bc6c91e0a6dc131de09c43110d9180d0a70f0d6289cb4e43b05f7ee5e9b3f42a1fad0f31bac6a625b3b5c50e3a83316783b649e5ecc9d3b1d9471cb5024b7ccf40d41d1751a04ca0356548bc6e703fca02ab521b505e8e45600508d32"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620"),
+ uniform_bytes: &hex!("78b53f2413f3c688f07732c10e5ced29a17c6a16f717179ffbe38d92d6c9ec296502eb9889af83a1928cd162e845b0d3c5424e83280fed3d10cffb2f8431f14e7a23f4c68819d40617589e4c41169d0b56e0e3535be1fd71fbb08bb70c5b5ffed953d6c14bf7618b35fc1f4c4b30538236b4b08c9fbf90462447a8ada60be495"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_128 {
+ test_vector.assert::<Sha256, U128>(DST, &dst_prime)?;
+ }
+
+ Ok(())
+ }
+
+ #[test]
+ fn expand_message_xmd_sha_512() -> Result<()> {
+ use sha2::Sha512;
+
+ const DST: &[u8] = b"QUUX-V01-CS02-with-expander-SHA512-256";
+ const DST_PRIME: &[u8] =
+ &hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626");
+
+ let dst_prime = Domain::xmd::<Sha512>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
+
+ const TEST_VECTORS_32: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("6b9a7312411d92f921c6f68ca0b6380730a1a4d982c507211a90964c394179ba"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("0da749f12fbe5483eb066a5f595055679b976e93abe9be6f0f6318bce7aca8dc"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("087e45a86e2939ee8b91100af1583c4938e0f5fc6c9db4b107b83346bc967f58"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("7336234ee9983902440f6bc35b348352013becd88938d2afec44311caf8356b3"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161002000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("57b5f7e766d5be68a6bfe1768e3c2b7f1228b3e4b3134956dd73a59b954c66f4"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_32 {
+ test_vector.assert::<Sha512, U32>(DST, &dst_prime)?;
+ }
+
+ const TEST_VECTORS_128: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("41b037d1734a5f8df225dd8c7de38f851efdb45c372887be655212d07251b921b052b62eaed99b46f72f2ef4cc96bfaf254ebbbec091e1a3b9e4fb5e5b619d2e0c5414800a1d882b62bb5cd1778f098b8eb6cb399d5d9d18f5d5842cf5d13d7eb00a7cff859b605da678b318bd0e65ebff70bec88c753b159a805d2c89c55961"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("7f1dddd13c08b543f2e2037b14cefb255b44c83cc397c1786d975653e36a6b11bdd7732d8b38adb4a0edc26a0cef4bb45217135456e58fbca1703cd6032cb1347ee720b87972d63fbf232587043ed2901bce7f22610c0419751c065922b488431851041310ad659e4b23520e1772ab29dcdeb2002222a363f0c2b1c972b3efe1"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("3f721f208e6199fe903545abc26c837ce59ac6fa45733f1baaf0222f8b7acb0424814fcb5eecf6c1d38f06e9d0a6ccfbf85ae612ab8735dfdf9ce84c372a77c8f9e1c1e952c3a61b7567dd0693016af51d2745822663d0c2367e3f4f0bed827feecc2aaf98c949b5ed0d35c3f1023d64ad1407924288d366ea159f46287e61ac"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("b799b045a58c8d2b4334cf54b78260b45eec544f9f2fb5bd12fb603eaee70db7317bf807c406e26373922b7b8920fa29142703dd52bdf280084fb7ef69da78afdf80b3586395b433dc66cde048a258e476a561e9deba7060af40adf30c64249ca7ddea79806ee5beb9a1422949471d267b21bc88e688e4014087a0b592b695ed"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626"),
+ uniform_bytes: &hex!("05b0bfef265dcee87654372777b7c44177e2ae4c13a27f103340d9cd11c86cb2426ffcad5bd964080c2aee97f03be1ca18e30a1f14e27bc11ebbd650f305269cc9fb1db08bf90bfc79b42a952b46daf810359e7bc36452684784a64952c343c52e5124cd1f71d474d5197fefc571a92929c9084ffe1112cf5eea5192ebff330b"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_128 {
+ test_vector.assert::<Sha512, U128>(DST, &dst_prime)?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs
new file mode 100644
index 0000000..9a5ff19
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs
@@ -0,0 +1,352 @@
+//! `expand_message_xof` for the `ExpandMsg` trait
+
+use super::{Domain, ExpandMsg, Expander};
+use crate::{Error, Result};
+use digest::{ExtendableOutput, Update, XofReader};
+use generic_array::typenum::U32;
+
+/// Placeholder type for implementing `expand_message_xof` based on an extendable output function
+///
+/// # Errors
+/// - `dst.is_empty()`
+/// - `len_in_bytes == 0`
+/// - `len_in_bytes > u16::MAX`
+pub struct ExpandMsgXof<HashT>
+where
+ HashT: Default + ExtendableOutput + Update,
+{
+ reader: <HashT as ExtendableOutput>::Reader,
+}
+
+/// ExpandMsgXof implements `expand_message_xof` for the [`ExpandMsg`] trait
+impl<'a, HashT> ExpandMsg<'a> for ExpandMsgXof<HashT>
+where
+ HashT: Default + ExtendableOutput + Update,
+{
+ type Expander = Self;
+
+ fn expand_message(
+ msgs: &[&[u8]],
+ dsts: &'a [&'a [u8]],
+ len_in_bytes: usize,
+ ) -> Result<Self::Expander> {
+ if len_in_bytes == 0 {
+ return Err(Error);
+ }
+
+ let len_in_bytes = u16::try_from(len_in_bytes).map_err(|_| Error)?;
+
+ let domain = Domain::<U32>::xof::<HashT>(dsts)?;
+ let mut reader = HashT::default();
+
+ for msg in msgs {
+ reader = reader.chain(msg);
+ }
+
+ reader.update(&len_in_bytes.to_be_bytes());
+ domain.update_hash(&mut reader);
+ reader.update(&[domain.len()]);
+ let reader = reader.finalize_xof();
+ Ok(Self { reader })
+ }
+}
+
+impl<HashT> Expander for ExpandMsgXof<HashT>
+where
+ HashT: Default + ExtendableOutput + Update,
+{
+ fn fill_bytes(&mut self, okm: &mut [u8]) {
+ self.reader.read(okm);
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use core::mem;
+ use generic_array::{
+ typenum::{U128, U32},
+ ArrayLength, GenericArray,
+ };
+ use hex_literal::hex;
+ use sha3::Shake128;
+
+ fn assert_message<HashT>(
+ msg: &[u8],
+ domain: &Domain<'_, U32>,
+ len_in_bytes: u16,
+ bytes: &[u8],
+ ) {
+ let msg_len = msg.len();
+ assert_eq!(msg, &bytes[..msg_len]);
+
+ let len_in_bytes_len = msg_len + mem::size_of::<u16>();
+ assert_eq!(
+ len_in_bytes.to_be_bytes(),
+ &bytes[msg_len..len_in_bytes_len]
+ );
+
+ let dst = len_in_bytes_len + usize::from(domain.len());
+ domain.assert(&bytes[len_in_bytes_len..dst]);
+
+ let dst_len = dst + mem::size_of::<u8>();
+ assert_eq!([domain.len()], &bytes[dst..dst_len]);
+
+ assert_eq!(dst_len, bytes.len());
+ }
+
+ struct TestVector {
+ msg: &'static [u8],
+ msg_prime: &'static [u8],
+ uniform_bytes: &'static [u8],
+ }
+
+ impl TestVector {
+ fn assert<HashT, L>(&self, dst: &'static [u8], domain: &Domain<'_, U32>) -> Result<()>
+ where
+ HashT: Default + ExtendableOutput + Update,
+ L: ArrayLength<u8>,
+ {
+ assert_message::<HashT>(self.msg, domain, L::to_u16(), self.msg_prime);
+
+ let mut expander =
+ ExpandMsgXof::<HashT>::expand_message(&[self.msg], &[dst], L::to_usize())?;
+
+ let mut uniform_bytes = GenericArray::<u8, L>::default();
+ expander.fill_bytes(&mut uniform_bytes);
+
+ assert_eq!(uniform_bytes.as_slice(), self.uniform_bytes);
+ Ok(())
+ }
+ }
+
+ #[test]
+ fn expand_message_xof_shake_128() -> Result<()> {
+ const DST: &[u8] = b"QUUX-V01-CS02-with-expander-SHAKE128";
+ const DST_PRIME: &[u8] =
+ &hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824");
+
+ let dst_prime = Domain::<U32>::xof::<Shake128>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
+
+ const TEST_VECTORS_32: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("86518c9cd86581486e9485aa74ab35ba150d1c75c88e26b7043e44e2acd735a2"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("6162630020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("8696af52a4d862417c0763556073f47bc9b9ba43c99b505305cb1ec04a9ab468"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("616263646566303132333435363738390020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("912c58deac4821c3509dbefa094df54b34b8f5d01a191d1d3108a2c89077acca"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("1adbcc448aef2a0cebc71dac9f756b22e51839d348e031e63b33ebb50faeaf3f"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("df3447cc5f3e9a77da10f819218ddf31342c310778e0e4ef72bbaecee786a4fe"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_32 {
+ test_vector.assert::<Shake128, U32>(DST, &dst_prime)?;
+ }
+
+ const TEST_VECTORS_128: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("7314ff1a155a2fb99a0171dc71b89ab6e3b2b7d59e38e64419b8b6294d03ffee42491f11370261f436220ef787f8f76f5b26bdcd850071920ce023f3ac46847744f4612b8714db8f5db83205b2e625d95afd7d7b4d3094d3bdde815f52850bb41ead9822e08f22cf41d615a303b0d9dde73263c049a7b9898208003a739a2e57"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("6162630080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("c952f0c8e529ca8824acc6a4cab0e782fc3648c563ddb00da7399f2ae35654f4860ec671db2356ba7baa55a34a9d7f79197b60ddae6e64768a37d699a78323496db3878c8d64d909d0f8a7de4927dcab0d3dbbc26cb20a49eceb0530b431cdf47bc8c0fa3e0d88f53b318b6739fbed7d7634974f1b5c386d6230c76260d5337a"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("616263646566303132333435363738390080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("19b65ee7afec6ac06a144f2d6134f08eeec185f1a890fe34e68f0e377b7d0312883c048d9b8a1d6ecc3b541cb4987c26f45e0c82691ea299b5e6889bbfe589153016d8131717ba26f07c3c14ffbef1f3eff9752e5b6183f43871a78219a75e7000fbac6a7072e2b83c790a3a5aecd9d14be79f9fd4fb180960a3772e08680495"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("ca1b56861482b16eae0f4a26212112362fcc2d76dcc80c93c4182ed66c5113fe41733ed68be2942a3487394317f3379856f4822a611735e50528a60e7ade8ec8c71670fec6661e2c59a09ed36386513221688b35dc47e3c3111ee8c67ff49579089d661caa29db1ef10eb6eace575bf3dc9806e7c4016bd50f3c0e2a6481ee6d"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824"),
+ uniform_bytes: &hex!("9d763a5ce58f65c91531b4100c7266d479a5d9777ba761693d052acd37d149e7ac91c796a10b919cd74a591a1e38719fb91b7203e2af31eac3bff7ead2c195af7d88b8bc0a8adf3d1e90ab9bed6ddc2b7f655dd86c730bdeaea884e73741097142c92f0e3fc1811b699ba593c7fbd81da288a29d423df831652e3a01a9374999"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_128 {
+ test_vector.assert::<Shake128, U128>(DST, &dst_prime)?;
+ }
+
+ Ok(())
+ }
+
+ #[test]
+ fn expand_message_xof_shake_128_long() -> Result<()> {
+ const DST: &[u8] = b"QUUX-V01-CS02-with-expander-SHAKE128-long-DST-111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
+ const DST_PRIME: &[u8] =
+ &hex!("acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20");
+
+ let dst_prime = Domain::<U32>::xof::<Shake128>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
+
+ const TEST_VECTORS_32: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("827c6216330a122352312bccc0c8d6e7a146c5257a776dbd9ad9d75cd880fc53"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("6162630020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("690c8d82c7213b4282c6cb41c00e31ea1d3e2005f93ad19bbf6da40f15790c5c"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("616263646566303132333435363738390020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("979e3a15064afbbcf99f62cc09fa9c85028afcf3f825eb0711894dcfc2f57057"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("c5a9220962d9edc212c063f4f65b609755a1ed96e62f9db5d1fd6adb5a8dc52b"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610020acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("f7b96a5901af5d78ce1d071d9c383cac66a1dfadb508300ec6aeaea0d62d5d62"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_32 {
+ test_vector.assert::<Shake128, U32>(DST, &dst_prime)?;
+ }
+
+ const TEST_VECTORS_128: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("3890dbab00a2830be398524b71c2713bbef5f4884ac2e6f070b092effdb19208c7df943dc5dcbaee3094a78c267ef276632ee2c8ea0c05363c94b6348500fae4208345dd3475fe0c834c2beac7fa7bc181692fb728c0a53d809fc8111495222ce0f38468b11becb15b32060218e285c57a60162c2c8bb5b6bded13973cd41819"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("6162630080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("41b7ffa7a301b5c1441495ebb9774e2a53dbbf4e54b9a1af6a20fd41eafd69ef7b9418599c5545b1ee422f363642b01d4a53449313f68da3e49dddb9cd25b97465170537d45dcbdf92391b5bdff344db4bd06311a05bca7dcd360b6caec849c299133e5c9194f4e15e3e23cfaab4003fab776f6ac0bfae9144c6e2e1c62e7d57"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("616263646566303132333435363738390080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("55317e4a21318472cd2290c3082957e1242241d9e0d04f47026f03401643131401071f01aa03038b2783e795bdfa8a3541c194ad5de7cb9c225133e24af6c86e748deb52e560569bd54ef4dac03465111a3a44b0ea490fb36777ff8ea9f1a8a3e8e0de3cf0880b4b2f8dd37d3a85a8b82375aee4fa0e909f9763319b55778e71"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("19fdd2639f082e31c77717ac9bb032a22ff0958382b2dbb39020cdc78f0da43305414806abf9a561cb2d0067eb2f7bc544482f75623438ed4b4e39dd9e6e2909dd858bd8f1d57cd0fce2d3150d90aa67b4498bdf2df98c0100dd1a173436ba5d0df6be1defb0b2ce55ccd2f4fc05eb7cb2c019c35d5398b85adc676da4238bc7"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610080acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20"),
+ uniform_bytes: &hex!("945373f0b3431a103333ba6a0a34f1efab2702efde41754c4cb1d5216d5b0a92a67458d968562bde7fa6310a83f53dda1383680a276a283438d58ceebfa7ab7ba72499d4a3eddc860595f63c93b1c5e823ea41fc490d938398a26db28f61857698553e93f0574eb8c5017bfed6249491f9976aaa8d23d9485339cc85ca329308"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_128 {
+ test_vector.assert::<Shake128, U128>(DST, &dst_prime)?;
+ }
+
+ Ok(())
+ }
+
+ #[test]
+ fn expand_message_xof_shake_256() -> Result<()> {
+ use sha3::Shake256;
+
+ const DST: &[u8] = b"QUUX-V01-CS02-with-expander-SHAKE256";
+ const DST_PRIME: &[u8] =
+ &hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624");
+
+ let dst_prime = Domain::<U32>::xof::<Shake256>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
+
+ const TEST_VECTORS_32: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("2ffc05c48ed32b95d72e807f6eab9f7530dd1c2f013914c8fed38c5ccc15ad76"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("6162630020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("b39e493867e2767216792abce1f2676c197c0692aed061560ead251821808e07"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("616263646566303132333435363738390020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("245389cf44a13f0e70af8665fe5337ec2dcd138890bb7901c4ad9cfceb054b65"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("719b3911821e6428a5ed9b8e600f2866bcf23c8f0515e52d6c6c019a03f16f0e"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610020515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("9181ead5220b1963f1b5951f35547a5ea86a820562287d6ca4723633d17ccbbc"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_32 {
+ test_vector.assert::<Shake256, U32>(DST, &dst_prime)?;
+ }
+
+ const TEST_VECTORS_128: &[TestVector] = &[
+ TestVector {
+ msg: b"",
+ msg_prime: &hex!("0080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("7a1361d2d7d82d79e035b8880c5a3c86c5afa719478c007d96e6c88737a3f631dd74a2c88df79a4cb5e5d9f7504957c70d669ec6bfedc31e01e2bacc4ff3fdf9b6a00b17cc18d9d72ace7d6b81c2e481b4f73f34f9a7505dccbe8f5485f3d20c5409b0310093d5d6492dea4e18aa6979c23c8ea5de01582e9689612afbb353df"),
+ },
+ TestVector {
+ msg: b"abc",
+ msg_prime: &hex!("6162630080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("a54303e6b172909783353ab05ef08dd435a558c3197db0c132134649708e0b9b4e34fb99b92a9e9e28fc1f1d8860d85897a8e021e6382f3eea10577f968ff6df6c45fe624ce65ca25932f679a42a404bc3681efe03fcd45ef73bb3a8f79ba784f80f55ea8a3c367408f30381299617f50c8cf8fbb21d0f1e1d70b0131a7b6fbe"),
+ },
+ TestVector {
+ msg: b"abcdef0123456789",
+ msg_prime: &hex!("616263646566303132333435363738390080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("e42e4d9538a189316e3154b821c1bafb390f78b2f010ea404e6ac063deb8c0852fcd412e098e231e43427bd2be1330bb47b4039ad57b30ae1fc94e34993b162ff4d695e42d59d9777ea18d3848d9d336c25d2acb93adcad009bcfb9cde12286df267ada283063de0bb1505565b2eb6c90e31c48798ecdc71a71756a9110ff373"),
+ },
+ TestVector {
+ msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
+ msg_prime: &hex!("713132385f71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171710080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("4ac054dda0a38a65d0ecf7afd3c2812300027c8789655e47aecf1ecc1a2426b17444c7482c99e5907afd9c25b991990490bb9c686f43e79b4471a23a703d4b02f23c669737a886a7ec28bddb92c3a98de63ebf878aa363a501a60055c048bea11840c4717beae7eee28c3cfa42857b3d130188571943a7bd747de831bd6444e0"),
+ },
+ TestVector {
+ msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ msg_prime: &hex!("613531325f61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161610080515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624"),
+ uniform_bytes: &hex!("09afc76d51c2cccbc129c2315df66c2be7295a231203b8ab2dd7f95c2772c68e500bc72e20c602abc9964663b7a03a389be128c56971ce81001a0b875e7fd17822db9d69792ddf6a23a151bf470079c518279aef3e75611f8f828994a9988f4a8a256ddb8bae161e658d5a2a09bcfe839c6396dc06ee5c8ff3c22d3b1f9deb7e"),
+ },
+ ];
+
+ for test_vector in TEST_VECTORS_128 {
+ test_vector.assert::<Shake256, U128>(DST, &dst_prime)?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/isogeny.rs b/vendor/elliptic-curve/src/hash2curve/isogeny.rs
new file mode 100644
index 0000000..7a28983
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/isogeny.rs
@@ -0,0 +1,58 @@
+//! Traits for mapping an isogeny to another curve
+//!
+//! <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve>
+
+use core::ops::{AddAssign, Mul};
+use ff::Field;
+use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
+
+/// The coefficients for mapping from one isogenous curve to another
+pub struct IsogenyCoefficients<F: Field + AddAssign + Mul<Output = F>> {
+ /// The coefficients for the x numerator
+ pub xnum: &'static [F],
+ /// The coefficients for the x denominator
+ pub xden: &'static [F],
+ /// The coefficients for the y numerator
+ pub ynum: &'static [F],
+ /// The coefficients for the x denominator
+ pub yden: &'static [F],
+}
+
+/// The [`Isogeny`] methods to map to another curve.
+pub trait Isogeny: Field + AddAssign + Mul<Output = Self> {
+ /// The maximum number of coefficients
+ type Degree: ArrayLength<Self>;
+ /// The isogeny coefficients
+ const COEFFICIENTS: IsogenyCoefficients<Self>;
+
+ /// Map from the isogeny points to the main curve
+ #[allow(clippy::integer_arithmetic)]
+ fn isogeny(x: Self, y: Self) -> (Self, Self) {
+ let mut xs = GenericArray::<Self, Self::Degree>::default();
+ xs[0] = Self::ONE;
+ xs[1] = x;
+ xs[2] = x.square();
+ for i in 3..Self::Degree::to_usize() {
+ xs[i] = xs[i - 1] * x;
+ }
+ let x_num = Self::compute_iso(&xs, Self::COEFFICIENTS.xnum);
+ let x_den = Self::compute_iso(&xs, Self::COEFFICIENTS.xden)
+ .invert()
+ .unwrap();
+ let y_num = Self::compute_iso(&xs, Self::COEFFICIENTS.ynum) * y;
+ let y_den = Self::compute_iso(&xs, Self::COEFFICIENTS.yden)
+ .invert()
+ .unwrap();
+
+ (x_num * x_den, y_num * y_den)
+ }
+
+ /// Compute the ISO transform
+ fn compute_iso(xxs: &[Self], k: &[Self]) -> Self {
+ let mut xx = Self::ZERO;
+ for (xi, ki) in xxs.iter().zip(k.iter()) {
+ xx += *xi * ki;
+ }
+ xx
+ }
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/map2curve.rs b/vendor/elliptic-curve/src/hash2curve/map2curve.rs
new file mode 100644
index 0000000..6092e57
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/map2curve.rs
@@ -0,0 +1,12 @@
+//! Traits for mapping field elements to points on the curve.
+
+/// Trait for converting field elements into a point
+/// via a mapping method like Simplified Shallue-van de Woestijne-Ulas
+/// or Elligator
+pub trait MapToCurve {
+ /// The output point
+ type Output;
+
+ /// Map a field element into a point
+ fn map_to_curve(&self) -> Self::Output;
+}
diff --git a/vendor/elliptic-curve/src/hash2curve/osswu.rs b/vendor/elliptic-curve/src/hash2curve/osswu.rs
new file mode 100644
index 0000000..3c3669a
--- /dev/null
+++ b/vendor/elliptic-curve/src/hash2curve/osswu.rs
@@ -0,0 +1,130 @@
+//! Optimized simplified Shallue-van de Woestijne-Ulas methods.
+//!
+//! <https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-16.html#straightline-sswu>
+
+use ff::Field;
+use subtle::Choice;
+use subtle::ConditionallySelectable;
+use subtle::ConstantTimeEq;
+
+/// The Optimized Simplified Shallue-van de Woestijne-Ulas parameters
+pub struct OsswuMapParams<F>
+where
+ F: Field,
+{
+ /// The first constant term
+ pub c1: &'static [u64],
+ /// The second constant term
+ pub c2: F,
+ /// The ISO A variable or Curve A variable
+ pub map_a: F,
+ /// The ISO A variable or Curve A variable
+ pub map_b: F,
+ /// The Z parameter
+ pub z: F,
+}
+
+/// Trait for determining the parity of the field
+pub trait Sgn0 {
+ /// Return the parity of the field
+ /// 1 == negative
+ /// 0 == non-negative
+ fn sgn0(&self) -> Choice;
+}
+
+/// The optimized simplified Shallue-van de Woestijne-Ulas method
+/// for mapping elliptic curve scalars to affine points.
+pub trait OsswuMap: Field + Sgn0 {
+ /// The OSSWU parameters for mapping the field to affine points.
+ /// For Weierstrass curves having A==0 or B==0, the parameters
+ /// should be for isogeny where A≠0 and B≠0.
+ const PARAMS: OsswuMapParams<Self>;
+
+ /// Optimized sqrt_ratio for q = 3 mod 4.
+ fn sqrt_ratio_3mod4(u: Self, v: Self) -> (Choice, Self) {
+ // 1. tv1 = v^2
+ let tv1 = v.square();
+ // 2. tv2 = u * v
+ let tv2 = u * v;
+ // 3. tv1 = tv1 * tv2
+ let tv1 = tv1 * tv2;
+ // 4. y1 = tv1^c1
+ let y1 = tv1.pow_vartime(Self::PARAMS.c1);
+ // 5. y1 = y1 * tv2
+ let y1 = y1 * tv2;
+ // 6. y2 = y1 * c2
+ let y2 = y1 * Self::PARAMS.c2;
+ // 7. tv3 = y1^2
+ let tv3 = y1.square();
+ // 8. tv3 = tv3 * v
+ let tv3 = tv3 * v;
+ // 9. isQR = tv3 == u
+ let is_qr = tv3.ct_eq(&u);
+ // 10. y = CMOV(y2, y1, isQR)
+ let y = ConditionallySelectable::conditional_select(&y2, &y1, is_qr);
+ // 11. return (isQR, y)
+ (is_qr, y)
+ }
+
+ /// Convert this field element into an affine point on the elliptic curve
+ /// returning (X, Y). For Weierstrass curves having A==0 or B==0
+ /// the result is a point on an isogeny.
+ fn osswu(&self) -> (Self, Self) {
+ // 1. tv1 = u^2
+ let tv1 = self.square();
+ // 2. tv1 = Z * tv1
+ let tv1 = Self::PARAMS.z * tv1;
+ // 3. tv2 = tv1^2
+ let tv2 = tv1.square();
+ // 4. tv2 = tv2 + tv1
+ let tv2 = tv2 + tv1;
+ // 5. tv3 = tv2 + 1
+ let tv3 = tv2 + Self::ONE;
+ // 6. tv3 = B * tv3
+ let tv3 = Self::PARAMS.map_b * tv3;
+ // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
+ let tv4 = ConditionallySelectable::conditional_select(
+ &Self::PARAMS.z,
+ &-tv2,
+ !Field::is_zero(&tv2),
+ );
+ // 8. tv4 = A * tv4
+ let tv4 = Self::PARAMS.map_a * tv4;
+ // 9. tv2 = tv3^2
+ let tv2 = tv3.square();
+ // 10. tv6 = tv4^2
+ let tv6 = tv4.square();
+ // 11. tv5 = A * tv6
+ let tv5 = Self::PARAMS.map_a * tv6;
+ // 12. tv2 = tv2 + tv5
+ let tv2 = tv2 + tv5;
+ // 13. tv2 = tv2 * tv3
+ let tv2 = tv2 * tv3;
+ // 14. tv6 = tv6 * tv4
+ let tv6 = tv6 * tv4;
+ // 15. tv5 = B * tv6
+ let tv5 = Self::PARAMS.map_b * tv6;
+ // 16. tv2 = tv2 + tv5
+ let tv2 = tv2 + tv5;
+ // 17. x = tv1 * tv3
+ let x = tv1 * tv3;
+ // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
+ let (is_gx1_square, y1) = Self::sqrt_ratio_3mod4(tv2, tv6);
+ // 19. y = tv1 * u
+ let y = tv1 * self;
+ // 20. y = y * y1
+ let y = y * y1;
+ // 21. x = CMOV(x, tv3, is_gx1_square)
+ let x = ConditionallySelectable::conditional_select(&x, &tv3, is_gx1_square);
+ // 22. y = CMOV(y, y1, is_gx1_square)
+ let y = ConditionallySelectable::conditional_select(&y, &y1, is_gx1_square);
+ // 23. e1 = sgn0(u) == sgn0(y)
+ let e1 = self.sgn0().ct_eq(&y.sgn0());
+ // 24. y = CMOV(-y, y, e1)
+ let y = ConditionallySelectable::conditional_select(&-y, &y, e1);
+ // 25. x = x / tv4
+ let x = x * tv4.invert().unwrap();
+ // 26. return (x, y)
+ (x, y)
+ }
+}
diff --git a/vendor/elliptic-curve/src/jwk.rs b/vendor/elliptic-curve/src/jwk.rs
new file mode 100644
index 0000000..e0233cc
--- /dev/null
+++ b/vendor/elliptic-curve/src/jwk.rs
@@ -0,0 +1,674 @@
+//! JSON Web Key (JWK) Support.
+//!
+//! Specified in RFC 7518 Section 6: Cryptographic Algorithms for Keys:
+//! <https://tools.ietf.org/html/rfc7518#section-6>
+
+use crate::{
+ sec1::{Coordinates, EncodedPoint, ModulusSize, ValidatePublicKey},
+ secret_key::SecretKey,
+ Curve, Error, FieldBytes, FieldBytesSize, Result,
+};
+use alloc::{
+ borrow::ToOwned,
+ format,
+ string::{String, ToString},
+};
+use base64ct::{Base64UrlUnpadded as Base64Url, Encoding};
+use core::{
+ fmt::{self, Debug},
+ marker::PhantomData,
+ str::{self, FromStr},
+};
+use serdect::serde::{de, ser, Deserialize, Serialize};
+use zeroize::{Zeroize, ZeroizeOnDrop};
+
+#[cfg(feature = "arithmetic")]
+use crate::{
+ public_key::PublicKey,
+ sec1::{FromEncodedPoint, ToEncodedPoint},
+ AffinePoint, CurveArithmetic,
+};
+
+/// Key Type (`kty`) for elliptic curve keys.
+pub const EC_KTY: &str = "EC";
+
+/// Deserialization error message.
+const DE_ERROR_MSG: &str = "struct JwkEcKey with 5 elements";
+
+/// Name of the JWK type
+const JWK_TYPE_NAME: &str = "JwkEcKey";
+
+/// Field names
+const FIELDS: &[&str] = &["kty", "crv", "x", "y", "d"];
+
+/// Elliptic curve parameters used by JSON Web Keys.
+pub trait JwkParameters: Curve {
+ /// The `crv` parameter which identifies a particular elliptic curve
+ /// as defined in RFC 7518 Section 6.2.1.1:
+ /// <https://tools.ietf.org/html/rfc7518#section-6.2.1.1>
+ ///
+ /// Curve values are registered in the IANA "JSON Web Key Elliptic Curve"
+ /// registry defined in RFC 7518 Section 7.6:
+ /// <https://tools.ietf.org/html/rfc7518#section-7.6>
+ const CRV: &'static str;
+}
+
+/// JSON Web Key (JWK) with a `kty` of `"EC"` (elliptic curve).
+///
+/// Specified in [RFC 7518 Section 6: Cryptographic Algorithms for Keys][1].
+///
+/// This type can represent either a public/private keypair, or just a
+/// public key, depending on whether or not the `d` parameter is present.
+///
+/// [1]: https://tools.ietf.org/html/rfc7518#section-6
+// TODO(tarcieri): eagerly decode or validate `x`, `y`, and `d` as Base64
+#[derive(Clone)]
+pub struct JwkEcKey {
+ /// The `crv` parameter which identifies a particular elliptic curve
+ /// as defined in RFC 7518 Section 6.2.1.1:
+ /// <https://tools.ietf.org/html/rfc7518#section-6.2.1.1>
+ crv: String,
+
+ /// The x-coordinate of the elliptic curve point which is the public key
+ /// value associated with this JWK as defined in RFC 7518 6.2.1.2:
+ /// <https://tools.ietf.org/html/rfc7518#section-6.2.1.2>
+ x: String,
+
+ /// The y-coordinate of the elliptic curve point which is the public key
+ /// value associated with this JWK as defined in RFC 7518 6.2.1.3:
+ /// <https://tools.ietf.org/html/rfc7518#section-6.2.1.3>
+ y: String,
+
+ /// The `d` ECC private key parameter as described in RFC 7518 6.2.2.1:
+ /// <https://tools.ietf.org/html/rfc7518#section-6.2.2.1>
+ ///
+ /// Value is optional and if omitted, this JWK represents a private key.
+ ///
+ /// Inner value is encoded according to the `Integer-to-Octet-String`
+ /// conversion as defined in SEC1 section 2.3.7:
+ /// <https://www.secg.org/sec1-v2.pdf>
+ d: Option<String>,
+}
+
+impl JwkEcKey {
+ /// Get the `crv` parameter for this JWK.
+ pub fn crv(&self) -> &str {
+ &self.crv
+ }
+
+ /// Is this JWK a keypair that includes a private key?
+ pub fn is_keypair(&self) -> bool {
+ self.d.is_some()
+ }
+
+ /// Does this JWK contain only a public key?
+ pub fn is_public_key(&self) -> bool {
+ self.d.is_none()
+ }
+
+ /// Decode a JWK into a [`PublicKey`].
+ #[cfg(feature = "arithmetic")]
+ pub fn to_public_key<C>(&self) -> Result<PublicKey<C>>
+ where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ PublicKey::from_sec1_bytes(self.to_encoded_point::<C>()?.as_bytes())
+ }
+
+ /// Create a JWK from a SEC1 [`EncodedPoint`].
+ pub fn from_encoded_point<C>(point: &EncodedPoint<C>) -> Option<Self>
+ where
+ C: Curve + JwkParameters,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ match point.coordinates() {
+ Coordinates::Uncompressed { x, y } => Some(JwkEcKey {
+ crv: C::CRV.to_owned(),
+ x: Base64Url::encode_string(x),
+ y: Base64Url::encode_string(y),
+ d: None,
+ }),
+ _ => None,
+ }
+ }
+
+ /// Get the public key component of this JWK as a SEC1 [`EncodedPoint`].
+ pub fn to_encoded_point<C>(&self) -> Result<EncodedPoint<C>>
+ where
+ C: Curve + JwkParameters,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ if self.crv != C::CRV {
+ return Err(Error);
+ }
+
+ let x = decode_base64url_fe::<C>(&self.x)?;
+ let y = decode_base64url_fe::<C>(&self.y)?;
+ Ok(EncodedPoint::<C>::from_affine_coordinates(&x, &y, false))
+ }
+
+ /// Decode a JWK into a [`SecretKey`].
+ #[cfg(feature = "arithmetic")]
+ pub fn to_secret_key<C>(&self) -> Result<SecretKey<C>>
+ where
+ C: Curve + JwkParameters + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ self.try_into()
+ }
+}
+
+impl FromStr for JwkEcKey {
+ type Err = Error;
+
+ fn from_str(s: &str) -> Result<Self> {
+ serde_json::from_str(s).map_err(|_| Error)
+ }
+}
+
+impl ToString for JwkEcKey {
+ fn to_string(&self) -> String {
+ serde_json::to_string(self).expect("JWK encoding error")
+ }
+}
+
+impl<C> TryFrom<JwkEcKey> for SecretKey<C>
+where
+ C: Curve + JwkParameters + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = Error;
+
+ fn try_from(jwk: JwkEcKey) -> Result<SecretKey<C>> {
+ (&jwk).try_into()
+ }
+}
+
+impl<C> TryFrom<&JwkEcKey> for SecretKey<C>
+where
+ C: Curve + JwkParameters + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = Error;
+
+ fn try_from(jwk: &JwkEcKey) -> Result<SecretKey<C>> {
+ if let Some(d_base64) = &jwk.d {
+ let pk = jwk.to_encoded_point::<C>()?;
+ let mut d_bytes = decode_base64url_fe::<C>(d_base64)?;
+ let result = SecretKey::from_slice(&d_bytes);
+ d_bytes.zeroize();
+
+ result.and_then(|secret_key| {
+ C::validate_public_key(&secret_key, &pk)?;
+ Ok(secret_key)
+ })
+ } else {
+ Err(Error)
+ }
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> From<SecretKey<C>> for JwkEcKey
+where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(sk: SecretKey<C>) -> JwkEcKey {
+ (&sk).into()
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> From<&SecretKey<C>> for JwkEcKey
+where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(sk: &SecretKey<C>) -> JwkEcKey {
+ let mut jwk = sk.public_key().to_jwk();
+ let mut d = sk.to_bytes();
+ jwk.d = Some(Base64Url::encode_string(&d));
+ d.zeroize();
+ jwk
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> TryFrom<JwkEcKey> for PublicKey<C>
+where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = Error;
+
+ fn try_from(jwk: JwkEcKey) -> Result<PublicKey<C>> {
+ (&jwk).try_into()
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> TryFrom<&JwkEcKey> for PublicKey<C>
+where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = Error;
+
+ fn try_from(jwk: &JwkEcKey) -> Result<PublicKey<C>> {
+ PublicKey::from_sec1_bytes(jwk.to_encoded_point::<C>()?.as_bytes())
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> From<PublicKey<C>> for JwkEcKey
+where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(pk: PublicKey<C>) -> JwkEcKey {
+ (&pk).into()
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> From<&PublicKey<C>> for JwkEcKey
+where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(pk: &PublicKey<C>) -> JwkEcKey {
+ Self::from_encoded_point::<C>(&pk.to_encoded_point(false)).expect("JWK encoding error")
+ }
+}
+
+impl Debug for JwkEcKey {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let d = if self.d.is_some() {
+ "Some(...)"
+ } else {
+ "None"
+ };
+
+ // NOTE: this implementation omits the `d` private key parameter
+ f.debug_struct(JWK_TYPE_NAME)
+ .field("crv", &self.crv)
+ .field("x", &self.x)
+ .field("y", &self.y)
+ .field("d", &d)
+ .finish()
+ }
+}
+
+impl PartialEq for JwkEcKey {
+ fn eq(&self, other: &Self) -> bool {
+ use subtle::ConstantTimeEq;
+
+ // Compare private key in constant time
+ let d_eq = match &self.d {
+ Some(d1) => match &other.d {
+ Some(d2) => d1.as_bytes().ct_eq(d2.as_bytes()).into(),
+ None => other.d.is_none(),
+ },
+ None => other.d.is_none(),
+ };
+
+ self.crv == other.crv && self.x == other.x && self.y == other.y && d_eq
+ }
+}
+
+impl Eq for JwkEcKey {}
+
+impl ZeroizeOnDrop for JwkEcKey {}
+
+impl Drop for JwkEcKey {
+ fn drop(&mut self) {
+ self.zeroize();
+ }
+}
+
+impl Zeroize for JwkEcKey {
+ fn zeroize(&mut self) {
+ if let Some(d) = &mut self.d {
+ d.zeroize();
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for JwkEcKey {
+ fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ /// Field positions
+ enum Field {
+ Kty,
+ Crv,
+ X,
+ Y,
+ D,
+ }
+
+ /// Field visitor
+ struct FieldVisitor;
+
+ impl<'de> de::Visitor<'de> for FieldVisitor {
+ type Value = Field;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Formatter::write_str(formatter, "field identifier")
+ }
+
+ fn visit_u64<E>(self, value: u64) -> core::result::Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ match value {
+ 0 => Ok(Field::Kty),
+ 1 => Ok(Field::Crv),
+ 2 => Ok(Field::X),
+ 3 => Ok(Field::Y),
+ 4 => Ok(Field::D),
+ _ => Err(de::Error::invalid_value(
+ de::Unexpected::Unsigned(value),
+ &"field index 0 <= i < 5",
+ )),
+ }
+ }
+
+ fn visit_str<E>(self, value: &str) -> core::result::Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ self.visit_bytes(value.as_bytes())
+ }
+
+ fn visit_bytes<E>(self, value: &[u8]) -> core::result::Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ match value {
+ b"kty" => Ok(Field::Kty),
+ b"crv" => Ok(Field::Crv),
+ b"x" => Ok(Field::X),
+ b"y" => Ok(Field::Y),
+ b"d" => Ok(Field::D),
+ _ => Err(de::Error::unknown_field(
+ &String::from_utf8_lossy(value),
+ FIELDS,
+ )),
+ }
+ }
+ }
+
+ impl<'de> Deserialize<'de> for Field {
+ #[inline]
+ fn deserialize<D>(__deserializer: D) -> core::result::Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ de::Deserializer::deserialize_identifier(__deserializer, FieldVisitor)
+ }
+ }
+
+ struct Visitor<'de> {
+ marker: PhantomData<JwkEcKey>,
+ lifetime: PhantomData<&'de ()>,
+ }
+
+ impl<'de> de::Visitor<'de> for Visitor<'de> {
+ type Value = JwkEcKey;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Formatter::write_str(formatter, "struct JwkEcKey")
+ }
+
+ #[inline]
+ fn visit_seq<A>(self, mut seq: A) -> core::result::Result<Self::Value, A::Error>
+ where
+ A: de::SeqAccess<'de>,
+ {
+ let kty = de::SeqAccess::next_element::<String>(&mut seq)?
+ .ok_or_else(|| de::Error::invalid_length(0, &DE_ERROR_MSG))?;
+
+ if kty != EC_KTY {
+ return Err(de::Error::custom(format!("unsupported JWK kty: {kty:?}")));
+ }
+
+ let crv = de::SeqAccess::next_element::<String>(&mut seq)?
+ .ok_or_else(|| de::Error::invalid_length(1, &DE_ERROR_MSG))?;
+
+ let x = de::SeqAccess::next_element::<String>(&mut seq)?
+ .ok_or_else(|| de::Error::invalid_length(2, &DE_ERROR_MSG))?;
+
+ let y = de::SeqAccess::next_element::<String>(&mut seq)?
+ .ok_or_else(|| de::Error::invalid_length(3, &DE_ERROR_MSG))?;
+
+ let d = de::SeqAccess::next_element::<Option<String>>(&mut seq)?
+ .ok_or_else(|| de::Error::invalid_length(4, &DE_ERROR_MSG))?;
+
+ Ok(JwkEcKey { crv, x, y, d })
+ }
+
+ #[inline]
+ fn visit_map<A>(self, mut map: A) -> core::result::Result<Self::Value, A::Error>
+ where
+ A: de::MapAccess<'de>,
+ {
+ let mut kty: Option<String> = None;
+ let mut crv: Option<String> = None;
+ let mut x: Option<String> = None;
+ let mut y: Option<String> = None;
+ let mut d: Option<String> = None;
+
+ while let Some(key) = de::MapAccess::next_key::<Field>(&mut map)? {
+ match key {
+ Field::Kty => {
+ if kty.is_none() {
+ kty = Some(de::MapAccess::next_value::<String>(&mut map)?);
+ } else {
+ return Err(de::Error::duplicate_field(FIELDS[0]));
+ }
+ }
+ Field::Crv => {
+ if crv.is_none() {
+ crv = Some(de::MapAccess::next_value::<String>(&mut map)?);
+ } else {
+ return Err(de::Error::duplicate_field(FIELDS[1]));
+ }
+ }
+ Field::X => {
+ if x.is_none() {
+ x = Some(de::MapAccess::next_value::<String>(&mut map)?);
+ } else {
+ return Err(de::Error::duplicate_field(FIELDS[2]));
+ }
+ }
+ Field::Y => {
+ if y.is_none() {
+ y = Some(de::MapAccess::next_value::<String>(&mut map)?);
+ } else {
+ return Err(de::Error::duplicate_field(FIELDS[3]));
+ }
+ }
+ Field::D => {
+ if d.is_none() {
+ d = de::MapAccess::next_value::<Option<String>>(&mut map)?;
+ } else {
+ return Err(de::Error::duplicate_field(FIELDS[4]));
+ }
+ }
+ }
+ }
+
+ let kty = kty.ok_or_else(|| de::Error::missing_field("kty"))?;
+
+ if kty != EC_KTY {
+ return Err(de::Error::custom(format!("unsupported JWK kty: {kty}")));
+ }
+
+ let crv = crv.ok_or_else(|| de::Error::missing_field("crv"))?;
+ let x = x.ok_or_else(|| de::Error::missing_field("x"))?;
+ let y = y.ok_or_else(|| de::Error::missing_field("y"))?;
+
+ Ok(JwkEcKey { crv, x, y, d })
+ }
+ }
+
+ de::Deserializer::deserialize_struct(
+ deserializer,
+ JWK_TYPE_NAME,
+ FIELDS,
+ Visitor {
+ marker: PhantomData::<JwkEcKey>,
+ lifetime: PhantomData,
+ },
+ )
+ }
+}
+
+impl Serialize for JwkEcKey {
+ fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
+ where
+ S: ser::Serializer,
+ {
+ use ser::SerializeStruct;
+
+ let mut state = serializer.serialize_struct(JWK_TYPE_NAME, 5)?;
+
+ for (i, field) in [EC_KTY, &self.crv, &self.x, &self.y].iter().enumerate() {
+ state.serialize_field(FIELDS[i], field)?;
+ }
+
+ if let Some(d) = &self.d {
+ state.serialize_field("d", d)?;
+ }
+
+ ser::SerializeStruct::end(state)
+ }
+}
+
+/// Decode a Base64url-encoded field element
+fn decode_base64url_fe<C: Curve>(s: &str) -> Result<FieldBytes<C>> {
+ let mut result = FieldBytes::<C>::default();
+ Base64Url::decode(s, &mut result).map_err(|_| Error)?;
+ Ok(result)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[cfg(feature = "dev")]
+ use crate::dev::MockCurve;
+
+ /// Example private key. From RFC 7518 Appendix C:
+ /// <https://tools.ietf.org/html/rfc7518#appendix-C>
+ const JWK_PRIVATE_KEY: &str = r#"
+ {
+ "kty":"EC",
+ "crv":"P-256",
+ "x":"gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0",
+ "y":"SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps",
+ "d":"0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo"
+ }
+ "#;
+
+ /// Example public key.
+ const JWK_PUBLIC_KEY: &str = r#"
+ {
+ "kty":"EC",
+ "crv":"P-256",
+ "x":"gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0",
+ "y":"SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps"
+ }
+ "#;
+
+ /// Example unsupported JWK (RSA key)
+ const UNSUPPORTED_JWK: &str = r#"
+ {
+ "kty":"RSA",
+ "kid":"cc34c0a0-bd5a-4a3c-a50d-a2a7db7643df",
+ "use":"sig",
+ "n":"pjdss8ZaDfEH6K6U7GeW2nxDqR4IP049fk1fK0lndimbMMVBdPv_hSpm8T8EtBDxrUdi1OHZfMhUixGaut-3nQ4GG9nM249oxhCtxqqNvEXrmQRGqczyLxuh-fKn9Fg--hS9UpazHpfVAFnB5aCfXoNhPuI8oByyFKMKaOVgHNqP5NBEqabiLftZD3W_lsFCPGuzr4Vp0YS7zS2hDYScC2oOMu4rGU1LcMZf39p3153Cq7bS2Xh6Y-vw5pwzFYZdjQxDn8x8BG3fJ6j8TGLXQsbKH1218_HcUJRvMwdpbUQG5nvA2GXVqLqdwp054Lzk9_B_f1lVrmOKuHjTNHq48w",
+ "e":"AQAB",
+ "d":"ksDmucdMJXkFGZxiomNHnroOZxe8AmDLDGO1vhs-POa5PZM7mtUPonxwjVmthmpbZzla-kg55OFfO7YcXhg-Hm2OWTKwm73_rLh3JavaHjvBqsVKuorX3V3RYkSro6HyYIzFJ1Ek7sLxbjDRcDOj4ievSX0oN9l-JZhaDYlPlci5uJsoqro_YrE0PRRWVhtGynd-_aWgQv1YzkfZuMD-hJtDi1Im2humOWxA4eZrFs9eG-whXcOvaSwO4sSGbS99ecQZHM2TcdXeAs1PvjVgQ_dKnZlGN3lTWoWfQP55Z7Tgt8Nf1q4ZAKd-NlMe-7iqCFfsnFwXjSiaOa2CRGZn-Q",
+ "p":"4A5nU4ahEww7B65yuzmGeCUUi8ikWzv1C81pSyUKvKzu8CX41hp9J6oRaLGesKImYiuVQK47FhZ--wwfpRwHvSxtNU9qXb8ewo-BvadyO1eVrIk4tNV543QlSe7pQAoJGkxCia5rfznAE3InKF4JvIlchyqs0RQ8wx7lULqwnn0",
+ "q":"ven83GM6SfrmO-TBHbjTk6JhP_3CMsIvmSdo4KrbQNvp4vHO3w1_0zJ3URkmkYGhz2tgPlfd7v1l2I6QkIh4Bumdj6FyFZEBpxjE4MpfdNVcNINvVj87cLyTRmIcaGxmfylY7QErP8GFA-k4UoH_eQmGKGK44TRzYj5hZYGWIC8",
+ "dp":"lmmU_AG5SGxBhJqb8wxfNXDPJjf__i92BgJT2Vp4pskBbr5PGoyV0HbfUQVMnw977RONEurkR6O6gxZUeCclGt4kQlGZ-m0_XSWx13v9t9DIbheAtgVJ2mQyVDvK4m7aRYlEceFh0PsX8vYDS5o1txgPwb3oXkPTtrmbAGMUBpE",
+ "dq":"mxRTU3QDyR2EnCv0Nl0TCF90oliJGAHR9HJmBe__EjuCBbwHfcT8OG3hWOv8vpzokQPRl5cQt3NckzX3fs6xlJN4Ai2Hh2zduKFVQ2p-AF2p6Yfahscjtq-GY9cB85NxLy2IXCC0PF--Sq9LOrTE9QV988SJy_yUrAjcZ5MmECk",
+ "qi":"ldHXIrEmMZVaNwGzDF9WG8sHj2mOZmQpw9yrjLK9hAsmsNr5LTyqWAqJIYZSwPTYWhY4nu2O0EY9G9uYiqewXfCKw_UngrJt8Xwfq1Zruz0YY869zPN4GiE9-9rzdZB33RBw8kIOquY3MK74FMwCihYx_LiU2YTHkaoJ3ncvtvg"
+ }
+ "#;
+
+ #[test]
+ fn parse_private_key() {
+ let jwk = JwkEcKey::from_str(JWK_PRIVATE_KEY).unwrap();
+ assert_eq!(jwk.crv, "P-256");
+ assert_eq!(jwk.x, "gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0");
+ assert_eq!(jwk.y, "SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps");
+ assert_eq!(
+ jwk.d.as_ref().unwrap(),
+ "0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo"
+ );
+ }
+
+ #[test]
+ fn parse_public_key() {
+ let jwk = JwkEcKey::from_str(JWK_PUBLIC_KEY).unwrap();
+ assert_eq!(jwk.crv, "P-256");
+ assert_eq!(jwk.x, "gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0");
+ assert_eq!(jwk.y, "SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps");
+ assert_eq!(jwk.d, None);
+ }
+
+ #[test]
+ fn parse_unsupported() {
+ assert_eq!(JwkEcKey::from_str(UNSUPPORTED_JWK), Err(Error));
+ }
+
+ #[test]
+ fn serialize_private_key() {
+ let actual = JwkEcKey::from_str(JWK_PRIVATE_KEY).unwrap().to_string();
+ let expected: String = JWK_PRIVATE_KEY.split_whitespace().collect();
+ assert_eq!(actual, expected);
+ }
+
+ #[test]
+ fn serialize_public_key() {
+ let actual = JwkEcKey::from_str(JWK_PUBLIC_KEY).unwrap().to_string();
+ let expected: String = JWK_PUBLIC_KEY.split_whitespace().collect();
+ assert_eq!(actual, expected);
+ }
+
+ #[cfg(feature = "dev")]
+ #[test]
+ fn jwk_into_encoded_point() {
+ let jwk = JwkEcKey::from_str(JWK_PUBLIC_KEY).unwrap();
+ let point = jwk.to_encoded_point::<MockCurve>().unwrap();
+ let (x, y) = match point.coordinates() {
+ Coordinates::Uncompressed { x, y } => (x, y),
+ other => panic!("unexpected coordinates: {:?}", other),
+ };
+
+ assert_eq!(&decode_base64url_fe::<MockCurve>(&jwk.x).unwrap(), x);
+ assert_eq!(&decode_base64url_fe::<MockCurve>(&jwk.y).unwrap(), y);
+ }
+
+ #[cfg(feature = "dev")]
+ #[test]
+ fn encoded_point_into_jwk() {
+ let jwk = JwkEcKey::from_str(JWK_PUBLIC_KEY).unwrap();
+ let point = jwk.to_encoded_point::<MockCurve>().unwrap();
+ let jwk2 = JwkEcKey::from_encoded_point::<MockCurve>(&point).unwrap();
+ assert_eq!(jwk, jwk2);
+ }
+}
diff --git a/vendor/elliptic-curve/src/lib.rs b/vendor/elliptic-curve/src/lib.rs
new file mode 100644
index 0000000..5f2a6c6
--- /dev/null
+++ b/vendor/elliptic-curve/src/lib.rs
@@ -0,0 +1,197 @@
+#![no_std]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+#![doc = include_str!("../README.md")]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
+)]
+#![forbid(unsafe_code)]
+#![warn(
+ clippy::cast_lossless,
+ clippy::cast_possible_truncation,
+ clippy::cast_possible_wrap,
+ clippy::cast_precision_loss,
+ clippy::cast_sign_loss,
+ clippy::checked_conversions,
+ clippy::implicit_saturating_sub,
+ clippy::integer_arithmetic,
+ clippy::mod_module_files,
+ clippy::panic,
+ clippy::panic_in_result_fn,
+ clippy::unwrap_used,
+ missing_docs,
+ rust_2018_idioms,
+ unused_lifetimes,
+ unused_qualifications
+)]
+
+//! ## Usage
+//!
+//! This crate provides traits for describing elliptic curves, along with
+//! types which are generic over elliptic curves which can be used as the
+//! basis of curve-agnostic code.
+//!
+//! It's intended to be used with the following concrete elliptic curve
+//! implementations from the [`RustCrypto/elliptic-curves`] project:
+//!
+//! - [`bp256`]: brainpoolP256r1 and brainpoolP256t1
+//! - [`bp384`]: brainpoolP384r1 and brainpoolP384t1
+//! - [`k256`]: secp256k1 a.k.a. K-256
+//! - [`p224`]: NIST P-224 a.k.a. secp224r1
+//! - [`p256`]: NIST P-256 a.k.a secp256r1, prime256v1
+//! - [`p384`]: NIST P-384 a.k.a. secp384r1
+//! - [`p521`]: NIST P-521 a.k.a. secp521r1
+//!
+//! The [`ecdsa`] crate provides a generic implementation of the
+//! Elliptic Curve Digital Signature Algorithm which can be used with any of
+//! the above crates, either via an external ECDSA implementation, or
+//! using native curve arithmetic where applicable.
+//!
+//! ## Type conversions
+//!
+//! The following chart illustrates the various conversions possible between
+//! the various types defined by this crate.
+//!
+//! ![Type Conversion Map](https://raw.githubusercontent.com/RustCrypto/media/master/img/elliptic-curve/type-transforms.svg)
+//!
+//! ## `serde` support
+//!
+//! When the `serde` feature of this crate is enabled, `Serialize` and
+//! `Deserialize` impls are provided for the following types:
+//!
+//! - [`JwkEcKey`]
+//! - [`PublicKey`]
+//! - [`ScalarPrimitive`]
+//!
+//! Please see type-specific documentation for more information.
+//!
+//! [`RustCrypto/elliptic-curves`]: https://github.com/RustCrypto/elliptic-curves
+//! [`bp256`]: https://github.com/RustCrypto/elliptic-curves/tree/master/bp256
+//! [`bp384`]: https://github.com/RustCrypto/elliptic-curves/tree/master/bp384
+//! [`k256`]: https://github.com/RustCrypto/elliptic-curves/tree/master/k256
+//! [`p224`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p224
+//! [`p256`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p256
+//! [`p384`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p384
+//! [`p521`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p521
+//! [`ecdsa`]: https://github.com/RustCrypto/signatures/tree/master/ecdsa
+
+#[cfg(feature = "alloc")]
+#[allow(unused_imports)]
+#[macro_use]
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
+
+pub mod point;
+pub mod scalar;
+
+#[cfg(feature = "dev")]
+pub mod dev;
+#[cfg(feature = "ecdh")]
+pub mod ecdh;
+#[cfg(feature = "hash2curve")]
+pub mod hash2curve;
+#[cfg(feature = "arithmetic")]
+pub mod ops;
+#[cfg(feature = "sec1")]
+pub mod sec1;
+#[cfg(feature = "arithmetic")]
+pub mod weierstrass;
+
+mod error;
+mod field;
+mod secret_key;
+
+#[cfg(feature = "arithmetic")]
+mod arithmetic;
+#[cfg(feature = "arithmetic")]
+mod public_key;
+
+#[cfg(feature = "jwk")]
+mod jwk;
+
+#[cfg(feature = "voprf")]
+mod voprf;
+
+pub use crate::{
+ error::{Error, Result},
+ field::{FieldBytes, FieldBytesEncoding, FieldBytesSize},
+ scalar::ScalarPrimitive,
+ secret_key::SecretKey,
+};
+pub use crypto_bigint as bigint;
+pub use generic_array::{self, typenum::consts};
+pub use rand_core;
+pub use subtle;
+pub use zeroize;
+
+#[cfg(feature = "arithmetic")]
+pub use {
+ crate::{
+ arithmetic::{CurveArithmetic, PrimeCurveArithmetic},
+ point::{AffinePoint, ProjectivePoint},
+ public_key::PublicKey,
+ scalar::{NonZeroScalar, Scalar},
+ },
+ ff::{self, Field, PrimeField},
+ group::{self, Group},
+};
+
+#[cfg(feature = "jwk")]
+pub use crate::jwk::{JwkEcKey, JwkParameters};
+
+#[cfg(feature = "pkcs8")]
+pub use pkcs8;
+
+#[cfg(feature = "voprf")]
+pub use crate::voprf::VoprfParameters;
+
+use core::{
+ fmt::Debug,
+ ops::{Add, ShrAssign},
+};
+use generic_array::ArrayLength;
+
+/// Algorithm [`ObjectIdentifier`][`pkcs8::ObjectIdentifier`] for elliptic
+/// curve public key cryptography (`id-ecPublicKey`).
+///
+/// <http://oid-info.com/get/1.2.840.10045.2.1>
+#[cfg(feature = "pkcs8")]
+pub const ALGORITHM_OID: pkcs8::ObjectIdentifier =
+ pkcs8::ObjectIdentifier::new_unwrap("1.2.840.10045.2.1");
+
+/// Elliptic curve.
+///
+/// This trait is intended to be impl'd by a ZST which represents a concrete
+/// elliptic curve.
+///
+/// Other traits in this crate which are bounded by [`Curve`] are intended to
+/// be impl'd by these ZSTs, facilitating types which are generic over elliptic
+/// curves (e.g. [`SecretKey`]).
+pub trait Curve: 'static + Copy + Clone + Debug + Default + Eq + Ord + Send + Sync {
+ /// Size of a serialized field element in bytes.
+ ///
+ /// This is typically the same as `Self::Uint::ByteSize` but for curves
+ /// with an unusual field modulus (e.g. P-224, P-521) it may be different.
+ type FieldBytesSize: ArrayLength<u8> + Add + Eq;
+
+ /// Integer type used to represent field elements of this elliptic curve.
+ type Uint: bigint::ArrayEncoding
+ + bigint::AddMod<Output = Self::Uint>
+ + bigint::Encoding
+ + bigint::Integer
+ + bigint::NegMod<Output = Self::Uint>
+ + bigint::Random
+ + bigint::RandomMod
+ + bigint::SubMod<Output = Self::Uint>
+ + zeroize::Zeroize
+ + FieldBytesEncoding<Self>
+ + ShrAssign<usize>;
+
+ /// Order of this elliptic curve, i.e. number of elements in the scalar
+ /// field.
+ const ORDER: Self::Uint;
+}
+
+/// Marker trait for elliptic curves with prime order.
+pub trait PrimeCurve: Curve {}
diff --git a/vendor/elliptic-curve/src/ops.rs b/vendor/elliptic-curve/src/ops.rs
new file mode 100644
index 0000000..b7e9e3d
--- /dev/null
+++ b/vendor/elliptic-curve/src/ops.rs
@@ -0,0 +1,79 @@
+//! Traits for arithmetic operations on elliptic curve field elements.
+
+pub use core::ops::{Add, AddAssign, Mul, Neg, Shr, ShrAssign, Sub, SubAssign};
+
+use crypto_bigint::Integer;
+use group::Group;
+
+/// Perform an inversion on a field element (i.e. base field element or scalar)
+pub trait Invert {
+ /// Field element type
+ type Output;
+
+ /// Invert a field element.
+ fn invert(&self) -> Self::Output;
+
+ /// Invert a field element in variable time.
+ ///
+ /// ⚠️ WARNING!
+ ///
+ /// This method should not be used with secret values, as its variable-time
+ /// operation can potentially leak secrets through sidechannels.
+ fn invert_vartime(&self) -> Self::Output {
+ // Fall back on constant-time implementation by default.
+ self.invert()
+ }
+}
+
+/// Linear combination.
+///
+/// This trait enables crates to provide an optimized implementation of
+/// linear combinations (e.g. Shamir's Trick), or otherwise provides a default
+/// non-optimized implementation.
+// TODO(tarcieri): replace this with a trait from the `group` crate? (see zkcrypto/group#25)
+pub trait LinearCombination: Group {
+ /// Calculates `x * k + y * l`.
+ fn lincomb(x: &Self, k: &Self::Scalar, y: &Self, l: &Self::Scalar) -> Self {
+ (*x * k) + (*y * l)
+ }
+}
+
+/// Multiplication by the generator.
+///
+/// May use optimizations (e.g. precomputed tables) when available.
+// TODO(tarcieri): replace this with `Group::mul_by_generator``? (see zkcrypto/group#44)
+pub trait MulByGenerator: Group {
+ /// Multiply by the generator of the prime-order subgroup.
+ #[must_use]
+ fn mul_by_generator(scalar: &Self::Scalar) -> Self {
+ Self::generator() * scalar
+ }
+}
+
+/// Modular reduction.
+pub trait Reduce<Uint: Integer>: Sized {
+ /// Bytes used as input to [`Reduce::reduce_bytes`].
+ type Bytes: AsRef<[u8]>;
+
+ /// Perform a modular reduction, returning a field element.
+ fn reduce(n: Uint) -> Self;
+
+ /// Interpret the given bytes as an integer and perform a modular reduction.
+ fn reduce_bytes(bytes: &Self::Bytes) -> Self;
+}
+
+/// Modular reduction to a non-zero output.
+///
+/// This trait is primarily intended for use by curve implementations such
+/// as the `k256` and `p256` crates.
+///
+/// End users should use the [`Reduce`] impl on
+/// [`NonZeroScalar`][`crate::NonZeroScalar`] instead.
+pub trait ReduceNonZero<Uint: Integer>: Reduce<Uint> + Sized {
+ /// Perform a modular reduction, returning a field element.
+ fn reduce_nonzero(n: Uint) -> Self;
+
+ /// Interpret the given bytes as an integer and perform a modular reduction
+ /// to a non-zero output.
+ fn reduce_nonzero_bytes(bytes: &Self::Bytes) -> Self;
+}
diff --git a/vendor/elliptic-curve/src/point.rs b/vendor/elliptic-curve/src/point.rs
new file mode 100644
index 0000000..25b872a
--- /dev/null
+++ b/vendor/elliptic-curve/src/point.rs
@@ -0,0 +1,69 @@
+//! Traits for elliptic curve points.
+
+#[cfg(feature = "arithmetic")]
+mod non_identity;
+
+#[cfg(feature = "arithmetic")]
+pub use {self::non_identity::NonIdentity, crate::CurveArithmetic};
+
+use crate::{Curve, FieldBytes};
+use subtle::{Choice, CtOption};
+
+/// Affine point type for a given curve with a [`CurveArithmetic`]
+/// implementation.
+#[cfg(feature = "arithmetic")]
+pub type AffinePoint<C> = <C as CurveArithmetic>::AffinePoint;
+
+/// Projective point type for a given curve with a [`CurveArithmetic`]
+/// implementation.
+#[cfg(feature = "arithmetic")]
+pub type ProjectivePoint<C> = <C as CurveArithmetic>::ProjectivePoint;
+
+/// Access to the affine coordinates of an elliptic curve point.
+// TODO: use zkcrypto/group#30 coordinate API when available
+pub trait AffineCoordinates {
+ /// Field element representation.
+ type FieldRepr: AsRef<[u8]>;
+
+ /// Get the affine x-coordinate as a serialized field element.
+ fn x(&self) -> Self::FieldRepr;
+
+ /// Is the affine y-coordinate odd?
+ fn y_is_odd(&self) -> Choice;
+}
+
+/// Double a point (i.e. add it to itself)
+pub trait Double {
+ /// Double this point.
+ fn double(&self) -> Self;
+}
+
+/// Decompress an elliptic curve point.
+///
+/// Point decompression recovers an original curve point from its x-coordinate
+/// and a boolean flag indicating whether or not the y-coordinate is odd.
+pub trait DecompressPoint<C: Curve>: Sized {
+ /// Attempt to decompress an elliptic curve point.
+ fn decompress(x: &FieldBytes<C>, y_is_odd: Choice) -> CtOption<Self>;
+}
+
+/// Decompact an elliptic curve point from an x-coordinate.
+///
+/// Decompaction relies on properties of specially-generated keys but provides
+/// a more compact representation than standard point compression.
+pub trait DecompactPoint<C: Curve>: Sized {
+ /// Attempt to decompact an elliptic curve point
+ fn decompact(x: &FieldBytes<C>) -> CtOption<Self>;
+}
+
+/// Point compression settings.
+pub trait PointCompression {
+ /// Should point compression be applied by default?
+ const COMPRESS_POINTS: bool;
+}
+
+/// Point compaction settings.
+pub trait PointCompaction {
+ /// Should point compaction be applied by default?
+ const COMPACT_POINTS: bool;
+}
diff --git a/vendor/elliptic-curve/src/point/non_identity.rs b/vendor/elliptic-curve/src/point/non_identity.rs
new file mode 100644
index 0000000..81c31cd
--- /dev/null
+++ b/vendor/elliptic-curve/src/point/non_identity.rs
@@ -0,0 +1,237 @@
+//! Non-identity point type.
+
+use core::ops::{Deref, Mul};
+
+use group::{prime::PrimeCurveAffine, Curve, GroupEncoding};
+use rand_core::{CryptoRng, RngCore};
+use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
+
+#[cfg(feature = "serde")]
+use serdect::serde::{de, ser, Deserialize, Serialize};
+
+use crate::{CurveArithmetic, NonZeroScalar, Scalar};
+
+/// Non-identity point type.
+///
+/// This type ensures that its value is not the identity point, ala `core::num::NonZero*`.
+///
+/// In the context of ECC, it's useful for ensuring that certain arithmetic
+/// cannot result in the identity point.
+#[derive(Clone, Copy)]
+pub struct NonIdentity<P> {
+ point: P,
+}
+
+impl<P> NonIdentity<P>
+where
+ P: ConditionallySelectable + ConstantTimeEq + Default,
+{
+ /// Create a [`NonIdentity`] from a point.
+ pub fn new(point: P) -> CtOption<Self> {
+ CtOption::new(Self { point }, !point.ct_eq(&P::default()))
+ }
+
+ pub(crate) fn new_unchecked(point: P) -> Self {
+ Self { point }
+ }
+}
+
+impl<P> NonIdentity<P>
+where
+ P: ConditionallySelectable + ConstantTimeEq + Default + GroupEncoding,
+{
+ /// Decode a [`NonIdentity`] from its encoding.
+ pub fn from_repr(repr: &P::Repr) -> CtOption<Self> {
+ Self::from_bytes(repr)
+ }
+}
+
+impl<P: Copy> NonIdentity<P> {
+ /// Return wrapped point.
+ pub fn to_point(self) -> P {
+ self.point
+ }
+}
+
+impl<P> NonIdentity<P>
+where
+ P: ConditionallySelectable + ConstantTimeEq + Curve + Default,
+{
+ /// Generate a random `NonIdentity<ProjectivePoint>`.
+ pub fn random(mut rng: impl CryptoRng + RngCore) -> Self {
+ loop {
+ if let Some(point) = Self::new(P::random(&mut rng)).into() {
+ break point;
+ }
+ }
+ }
+
+ /// Converts this element into its affine representation.
+ pub fn to_affine(self) -> NonIdentity<P::AffineRepr> {
+ NonIdentity {
+ point: self.point.to_affine(),
+ }
+ }
+}
+
+impl<P> NonIdentity<P>
+where
+ P: PrimeCurveAffine,
+{
+ /// Converts this element to its curve representation.
+ pub fn to_curve(self) -> NonIdentity<P::Curve> {
+ NonIdentity {
+ point: self.point.to_curve(),
+ }
+ }
+}
+
+impl<P> AsRef<P> for NonIdentity<P> {
+ fn as_ref(&self) -> &P {
+ &self.point
+ }
+}
+
+impl<P> ConditionallySelectable for NonIdentity<P>
+where
+ P: ConditionallySelectable,
+{
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ Self {
+ point: P::conditional_select(&a.point, &b.point, choice),
+ }
+ }
+}
+
+impl<P> ConstantTimeEq for NonIdentity<P>
+where
+ P: ConstantTimeEq,
+{
+ fn ct_eq(&self, other: &Self) -> Choice {
+ self.point.ct_eq(&other.point)
+ }
+}
+
+impl<P> Deref for NonIdentity<P> {
+ type Target = P;
+
+ fn deref(&self) -> &Self::Target {
+ &self.point
+ }
+}
+
+impl<P> GroupEncoding for NonIdentity<P>
+where
+ P: ConditionallySelectable + ConstantTimeEq + Default + GroupEncoding,
+{
+ type Repr = P::Repr;
+
+ fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
+ let point = P::from_bytes(bytes);
+ point.and_then(|point| CtOption::new(Self { point }, !point.ct_eq(&P::default())))
+ }
+
+ fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
+ P::from_bytes_unchecked(bytes).map(|point| Self { point })
+ }
+
+ fn to_bytes(&self) -> Self::Repr {
+ self.point.to_bytes()
+ }
+}
+
+impl<C, P> Mul<NonZeroScalar<C>> for NonIdentity<P>
+where
+ C: CurveArithmetic,
+ P: Copy + Mul<Scalar<C>, Output = P>,
+{
+ type Output = NonIdentity<P>;
+
+ fn mul(self, rhs: NonZeroScalar<C>) -> Self::Output {
+ &self * &rhs
+ }
+}
+
+impl<C, P> Mul<&NonZeroScalar<C>> for &NonIdentity<P>
+where
+ C: CurveArithmetic,
+ P: Copy + Mul<Scalar<C>, Output = P>,
+{
+ type Output = NonIdentity<P>;
+
+ fn mul(self, rhs: &NonZeroScalar<C>) -> Self::Output {
+ NonIdentity {
+ point: self.point * *rhs.as_ref(),
+ }
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<P> Serialize for NonIdentity<P>
+where
+ P: Serialize,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: ser::Serializer,
+ {
+ self.point.serialize(serializer)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, P> Deserialize<'de> for NonIdentity<P>
+where
+ P: ConditionallySelectable + ConstantTimeEq + Default + Deserialize<'de> + GroupEncoding,
+{
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ Option::from(Self::new(P::deserialize(deserializer)?))
+ .ok_or_else(|| de::Error::custom("expected non-identity point"))
+ }
+}
+
+#[cfg(all(test, feature = "dev"))]
+mod tests {
+ use super::NonIdentity;
+ use crate::dev::{AffinePoint, ProjectivePoint};
+ use group::GroupEncoding;
+ use hex_literal::hex;
+
+ #[test]
+ fn new_success() {
+ let point = ProjectivePoint::from_bytes(
+ &hex!("02c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721").into(),
+ )
+ .unwrap();
+
+ assert!(bool::from(NonIdentity::new(point).is_some()));
+
+ assert!(bool::from(
+ NonIdentity::new(AffinePoint::from(point)).is_some()
+ ));
+ }
+
+ #[test]
+ fn new_fail() {
+ assert!(bool::from(
+ NonIdentity::new(ProjectivePoint::default()).is_none()
+ ));
+ assert!(bool::from(
+ NonIdentity::new(AffinePoint::default()).is_none()
+ ));
+ }
+
+ #[test]
+ fn round_trip() {
+ let bytes = hex!("02c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
+ let point = NonIdentity::<ProjectivePoint>::from_repr(&bytes.into()).unwrap();
+ assert_eq!(&bytes, point.to_bytes().as_slice());
+
+ let bytes = hex!("02c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
+ let point = NonIdentity::<AffinePoint>::from_repr(&bytes.into()).unwrap();
+ assert_eq!(&bytes, point.to_bytes().as_slice());
+ }
+}
diff --git a/vendor/elliptic-curve/src/public_key.rs b/vendor/elliptic-curve/src/public_key.rs
new file mode 100644
index 0000000..485b0ec
--- /dev/null
+++ b/vendor/elliptic-curve/src/public_key.rs
@@ -0,0 +1,566 @@
+//! Elliptic curve public keys.
+
+use crate::{
+ point::NonIdentity, AffinePoint, CurveArithmetic, Error, NonZeroScalar, ProjectivePoint, Result,
+};
+use core::fmt::Debug;
+use group::{Curve, Group};
+
+#[cfg(feature = "jwk")]
+use crate::{JwkEcKey, JwkParameters};
+
+#[cfg(feature = "pkcs8")]
+use pkcs8::spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, ObjectIdentifier};
+
+#[cfg(feature = "pem")]
+use core::str::FromStr;
+
+#[cfg(feature = "sec1")]
+use {
+ crate::{
+ point::PointCompression,
+ sec1::{CompressedPoint, EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
+ FieldBytesSize,
+ },
+ core::cmp::Ordering,
+ subtle::{Choice, CtOption},
+};
+
+#[cfg(all(feature = "alloc", feature = "pkcs8"))]
+use pkcs8::EncodePublicKey;
+
+#[cfg(all(feature = "alloc", feature = "sec1"))]
+use alloc::boxed::Box;
+
+#[cfg(any(feature = "jwk", feature = "pem"))]
+use alloc::string::{String, ToString};
+
+#[cfg(feature = "serde")]
+use serdect::serde::{de, ser, Deserialize, Serialize};
+
+#[cfg(any(feature = "pem", feature = "serde"))]
+use pkcs8::DecodePublicKey;
+
+#[cfg(all(feature = "sec1", feature = "pkcs8"))]
+use {
+ crate::{
+ pkcs8::{self, AssociatedOid},
+ ALGORITHM_OID,
+ },
+ pkcs8::der,
+};
+
+/// Elliptic curve public keys.
+///
+/// This is a wrapper type for [`AffinePoint`] which ensures an inner
+/// non-identity point and provides a common place to handle encoding/decoding.
+///
+/// # Parsing "SPKI" Keys
+///
+/// X.509 `SubjectPublicKeyInfo` (SPKI) is a commonly used format for encoding
+/// public keys, notably public keys corresponding to PKCS#8 private keys.
+/// (especially ones generated by OpenSSL).
+///
+/// Keys in SPKI format are either binary (ASN.1 BER/DER), or PEM encoded
+/// (ASCII) and begin with the following:
+///
+/// ```text
+/// -----BEGIN PUBLIC KEY-----
+/// ```
+///
+/// To decode an elliptic curve public key from SPKI, enable the `pkcs8`
+/// feature of this crate (or the `pkcs8` feature of a specific RustCrypto
+/// elliptic curve crate) and use the
+/// [`elliptic_curve::pkcs8::DecodePublicKey`][`pkcs8::DecodePublicKey`]
+/// trait to parse it.
+///
+/// When the `pem` feature of this crate (or a specific RustCrypto elliptic
+/// curve crate) is enabled, a [`FromStr`] impl is also available.
+///
+/// # `serde` support
+///
+/// When the optional `serde` feature of this create is enabled, [`Serialize`]
+/// and [`Deserialize`] impls are provided for this type.
+///
+/// The serialization is binary-oriented and supports ASN.1 DER
+/// Subject Public Key Info (SPKI) as the encoding format.
+///
+/// For a more text-friendly encoding of public keys, use [`JwkEcKey`] instead.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct PublicKey<C>
+where
+ C: CurveArithmetic,
+{
+ point: AffinePoint<C>,
+}
+
+impl<C> PublicKey<C>
+where
+ C: CurveArithmetic,
+{
+ /// Convert an [`AffinePoint`] into a [`PublicKey`]
+ pub fn from_affine(point: AffinePoint<C>) -> Result<Self> {
+ if ProjectivePoint::<C>::from(point).is_identity().into() {
+ Err(Error)
+ } else {
+ Ok(Self { point })
+ }
+ }
+
+ /// Compute a [`PublicKey`] from a secret [`NonZeroScalar`] value
+ /// (i.e. a secret key represented as a raw scalar value)
+ pub fn from_secret_scalar(scalar: &NonZeroScalar<C>) -> Self {
+ // `NonZeroScalar` ensures the resulting point is not the identity
+ Self {
+ point: (C::ProjectivePoint::generator() * scalar.as_ref()).to_affine(),
+ }
+ }
+
+ /// Decode [`PublicKey`] (compressed or uncompressed) from the
+ /// `Elliptic-Curve-Point-to-Octet-String` encoding described in
+ /// SEC 1: Elliptic Curve Cryptography (Version 2.0) section
+ /// 2.3.3 (page 10).
+ ///
+ /// <http://www.secg.org/sec1-v2.pdf>
+ #[cfg(feature = "sec1")]
+ pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self>
+ where
+ FieldBytesSize<C>: ModulusSize,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ {
+ let point = EncodedPoint::<C>::from_bytes(bytes).map_err(|_| Error)?;
+ Option::from(Self::from_encoded_point(&point)).ok_or(Error)
+ }
+
+ /// Convert this [`PublicKey`] into the
+ /// `Elliptic-Curve-Point-to-Octet-String` encoding described in
+ /// SEC 1: Elliptic Curve Cryptography (Version 2.0) section 2.3.3
+ /// (page 10).
+ ///
+ /// <http://www.secg.org/sec1-v2.pdf>
+ #[cfg(all(feature = "alloc", feature = "sec1"))]
+ pub fn to_sec1_bytes(&self) -> Box<[u8]>
+ where
+ C: PointCompression,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ EncodedPoint::<C>::from(self).to_bytes()
+ }
+
+ /// Borrow the inner [`AffinePoint`] from this [`PublicKey`].
+ ///
+ /// In ECC, public keys are elliptic curve points.
+ pub fn as_affine(&self) -> &AffinePoint<C> {
+ &self.point
+ }
+
+ /// Convert this [`PublicKey`] to a [`ProjectivePoint`] for the given curve
+ pub fn to_projective(&self) -> ProjectivePoint<C> {
+ self.point.into()
+ }
+
+ /// Convert this [`PublicKey`] to a [`NonIdentity`] of the inner [`AffinePoint`]
+ pub fn to_nonidentity(&self) -> NonIdentity<AffinePoint<C>> {
+ NonIdentity::new_unchecked(self.point)
+ }
+
+ /// Parse a [`JwkEcKey`] JSON Web Key (JWK) into a [`PublicKey`].
+ #[cfg(feature = "jwk")]
+ pub fn from_jwk(jwk: &JwkEcKey) -> Result<Self>
+ where
+ C: JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ jwk.to_public_key::<C>()
+ }
+
+ /// Parse a string containing a JSON Web Key (JWK) into a [`PublicKey`].
+ #[cfg(feature = "jwk")]
+ pub fn from_jwk_str(jwk: &str) -> Result<Self>
+ where
+ C: JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ jwk.parse::<JwkEcKey>().and_then(|jwk| Self::from_jwk(&jwk))
+ }
+
+ /// Serialize this public key as [`JwkEcKey`] JSON Web Key (JWK).
+ #[cfg(feature = "jwk")]
+ pub fn to_jwk(&self) -> JwkEcKey
+ where
+ C: JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ self.into()
+ }
+
+ /// Serialize this public key as JSON Web Key (JWK) string.
+ #[cfg(feature = "jwk")]
+ pub fn to_jwk_string(&self) -> String
+ where
+ C: JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ self.to_jwk().to_string()
+ }
+}
+
+impl<C> AsRef<AffinePoint<C>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+{
+ fn as_ref(&self) -> &AffinePoint<C> {
+ self.as_affine()
+ }
+}
+
+impl<C> Copy for PublicKey<C> where C: CurveArithmetic {}
+
+#[cfg(feature = "sec1")]
+impl<C> FromEncodedPoint<C> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ /// Initialize [`PublicKey`] from an [`EncodedPoint`]
+ fn from_encoded_point(encoded_point: &EncodedPoint<C>) -> CtOption<Self> {
+ AffinePoint::<C>::from_encoded_point(encoded_point).and_then(|point| {
+ let is_identity = Choice::from(encoded_point.is_identity() as u8);
+ CtOption::new(PublicKey { point }, !is_identity)
+ })
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> ToEncodedPoint<C> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ /// Serialize this [`PublicKey`] as a SEC1 [`EncodedPoint`], optionally applying
+ /// point compression
+ fn to_encoded_point(&self, compress: bool) -> EncodedPoint<C> {
+ self.point.to_encoded_point(compress)
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> From<PublicKey<C>> for CompressedPoint<C>
+where
+ C: CurveArithmetic + PointCompression,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(public_key: PublicKey<C>) -> CompressedPoint<C> {
+ CompressedPoint::<C>::from(&public_key)
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> From<&PublicKey<C>> for CompressedPoint<C>
+where
+ C: CurveArithmetic + PointCompression,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(public_key: &PublicKey<C>) -> CompressedPoint<C> {
+ CompressedPoint::<C>::clone_from_slice(public_key.to_encoded_point(true).as_bytes())
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> From<PublicKey<C>> for EncodedPoint<C>
+where
+ C: CurveArithmetic + PointCompression,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(public_key: PublicKey<C>) -> EncodedPoint<C> {
+ EncodedPoint::<C>::from(&public_key)
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> From<&PublicKey<C>> for EncodedPoint<C>
+where
+ C: CurveArithmetic + PointCompression,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn from(public_key: &PublicKey<C>) -> EncodedPoint<C> {
+ public_key.to_encoded_point(C::COMPRESS_POINTS)
+ }
+}
+
+impl<C, P> From<NonIdentity<P>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ P: Copy + Into<AffinePoint<C>>,
+{
+ fn from(value: NonIdentity<P>) -> Self {
+ Self::from(&value)
+ }
+}
+
+impl<C, P> From<&NonIdentity<P>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ P: Copy + Into<AffinePoint<C>>,
+{
+ fn from(value: &NonIdentity<P>) -> Self {
+ Self {
+ point: value.to_point().into(),
+ }
+ }
+}
+
+impl<C> From<PublicKey<C>> for NonIdentity<AffinePoint<C>>
+where
+ C: CurveArithmetic,
+{
+ fn from(value: PublicKey<C>) -> Self {
+ Self::from(&value)
+ }
+}
+
+impl<C> From<&PublicKey<C>> for NonIdentity<AffinePoint<C>>
+where
+ C: CurveArithmetic,
+{
+ fn from(value: &PublicKey<C>) -> Self {
+ PublicKey::to_nonidentity(value)
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> PartialOrd for PublicKey<C>
+where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> Ord for PublicKey<C>
+where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn cmp(&self, other: &Self) -> Ordering {
+ // TODO(tarcieri): more efficient implementation?
+ // This is implemented this way to reduce bounds for `AffinePoint<C>`
+ self.to_encoded_point(false)
+ .cmp(&other.to_encoded_point(false))
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> TryFrom<CompressedPoint<C>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ FieldBytesSize<C>: ModulusSize,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+{
+ type Error = Error;
+
+ fn try_from(point: CompressedPoint<C>) -> Result<Self> {
+ Self::from_sec1_bytes(&point)
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> TryFrom<&CompressedPoint<C>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ FieldBytesSize<C>: ModulusSize,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+{
+ type Error = Error;
+
+ fn try_from(point: &CompressedPoint<C>) -> Result<Self> {
+ Self::from_sec1_bytes(point)
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> TryFrom<EncodedPoint<C>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ FieldBytesSize<C>: ModulusSize,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+{
+ type Error = Error;
+
+ fn try_from(point: EncodedPoint<C>) -> Result<Self> {
+ Self::from_sec1_bytes(point.as_bytes())
+ }
+}
+
+#[cfg(feature = "sec1")]
+impl<C> TryFrom<&EncodedPoint<C>> for PublicKey<C>
+where
+ C: CurveArithmetic,
+ FieldBytesSize<C>: ModulusSize,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+{
+ type Error = Error;
+
+ fn try_from(point: &EncodedPoint<C>) -> Result<Self> {
+ Self::from_sec1_bytes(point.as_bytes())
+ }
+}
+
+#[cfg(feature = "pkcs8")]
+impl<C> AssociatedAlgorithmIdentifier for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+{
+ type Params = ObjectIdentifier;
+
+ const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<ObjectIdentifier> = AlgorithmIdentifier {
+ oid: ALGORITHM_OID,
+ parameters: Some(C::OID),
+ };
+}
+
+#[cfg(feature = "pkcs8")]
+impl<C> TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = pkcs8::spki::Error;
+
+ fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result<Self> {
+ Self::try_from(&spki)
+ }
+}
+
+#[cfg(feature = "pkcs8")]
+impl<C> TryFrom<&pkcs8::SubjectPublicKeyInfoRef<'_>> for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = pkcs8::spki::Error;
+
+ fn try_from(spki: &pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result<Self> {
+ spki.algorithm.assert_oids(ALGORITHM_OID, C::OID)?;
+
+ let public_key_bytes = spki
+ .subject_public_key
+ .as_bytes()
+ .ok_or_else(|| der::Tag::BitString.value_error())?;
+
+ Self::from_sec1_bytes(public_key_bytes)
+ .map_err(|_| der::Tag::BitString.value_error().into())
+ }
+}
+
+#[cfg(all(feature = "alloc", feature = "pkcs8"))]
+impl<C> EncodePublicKey for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn to_public_key_der(&self) -> pkcs8::spki::Result<der::Document> {
+ let public_key_bytes = self.to_encoded_point(false);
+ let subject_public_key = der::asn1::BitStringRef::new(0, public_key_bytes.as_bytes())?;
+
+ pkcs8::SubjectPublicKeyInfo {
+ algorithm: Self::ALGORITHM_IDENTIFIER,
+ subject_public_key,
+ }
+ .try_into()
+ }
+}
+
+#[cfg(feature = "pem")]
+impl<C> FromStr for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Err = Error;
+
+ fn from_str(s: &str) -> Result<Self> {
+ Self::from_public_key_pem(s).map_err(|_| Error)
+ }
+}
+
+#[cfg(feature = "pem")]
+impl<C> ToString for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn to_string(&self) -> String {
+ self.to_public_key_pem(Default::default())
+ .expect("PEM encoding error")
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<C> Serialize for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
+ where
+ S: ser::Serializer,
+ {
+ let der = self.to_public_key_der().map_err(ser::Error::custom)?;
+ serdect::slice::serialize_hex_upper_or_bin(&der, serializer)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, C> Deserialize<'de> for PublicKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
+ Self::from_public_key_der(&der_bytes).map_err(de::Error::custom)
+ }
+}
+
+#[cfg(all(feature = "dev", test))]
+mod tests {
+ use crate::{dev::MockCurve, sec1::FromEncodedPoint};
+
+ type EncodedPoint = crate::sec1::EncodedPoint<MockCurve>;
+ type PublicKey = super::PublicKey<MockCurve>;
+
+ #[test]
+ fn from_encoded_point_rejects_identity() {
+ let identity = EncodedPoint::identity();
+ assert!(bool::from(
+ PublicKey::from_encoded_point(&identity).is_none()
+ ));
+ }
+}
diff --git a/vendor/elliptic-curve/src/scalar.rs b/vendor/elliptic-curve/src/scalar.rs
new file mode 100644
index 0000000..eb99249
--- /dev/null
+++ b/vendor/elliptic-curve/src/scalar.rs
@@ -0,0 +1,53 @@
+//! Scalar types.
+
+#[cfg(feature = "arithmetic")]
+mod blinded;
+#[cfg(feature = "arithmetic")]
+mod nonzero;
+mod primitive;
+
+pub use self::primitive::ScalarPrimitive;
+#[cfg(feature = "arithmetic")]
+pub use self::{blinded::BlindedScalar, nonzero::NonZeroScalar};
+
+use crypto_bigint::Integer;
+use subtle::Choice;
+
+#[cfg(feature = "arithmetic")]
+use crate::CurveArithmetic;
+
+/// Scalar field element for a particular elliptic curve.
+#[cfg(feature = "arithmetic")]
+pub type Scalar<C> = <C as CurveArithmetic>::Scalar;
+
+/// Bit representation of a scalar field element of a given curve.
+#[cfg(feature = "bits")]
+pub type ScalarBits<C> = ff::FieldBits<<Scalar<C> as ff::PrimeFieldBits>::ReprBits>;
+
+/// Instantiate a scalar from an unsigned integer without checking for overflow.
+pub trait FromUintUnchecked {
+ /// Unsigned integer type (i.e. `Curve::Uint`)
+ type Uint: Integer;
+
+ /// Instantiate scalar from an unsigned integer without checking
+ /// whether the value overflows the field modulus.
+ ///
+ /// ⚠️ WARNING!
+ ///
+ /// Incorrectly used this can lead to mathematically invalid results,
+ /// which can lead to potential security vulnerabilities.
+ ///
+ /// Use with care!
+ fn from_uint_unchecked(uint: Self::Uint) -> Self;
+}
+
+/// Is this scalar greater than n / 2?
+///
+/// # Returns
+///
+/// - For scalars 0 through n / 2: `Choice::from(0)`
+/// - For scalars (n / 2) + 1 through n - 1: `Choice::from(1)`
+pub trait IsHigh {
+ /// Is this scalar greater than or equal to n / 2?
+ fn is_high(&self) -> Choice;
+}
diff --git a/vendor/elliptic-curve/src/scalar/blinded.rs b/vendor/elliptic-curve/src/scalar/blinded.rs
new file mode 100644
index 0000000..29cfea9
--- /dev/null
+++ b/vendor/elliptic-curve/src/scalar/blinded.rs
@@ -0,0 +1,74 @@
+//! Random blinding support for [`Scalar`]
+
+use super::Scalar;
+use crate::{ops::Invert, CurveArithmetic};
+use group::ff::Field;
+use rand_core::CryptoRngCore;
+use subtle::CtOption;
+use zeroize::Zeroize;
+
+/// Scalar blinded with a randomly generated masking value.
+///
+/// This provides a randomly blinded impl of [`Invert`] which is useful for
+/// e.g. ECDSA ephemeral (`k`) scalars.
+///
+/// It implements masked variable-time inversions using Stein's algorithm, which
+/// may be helpful for performance on embedded platforms.
+#[derive(Clone)]
+pub struct BlindedScalar<C>
+where
+ C: CurveArithmetic,
+{
+ /// Actual scalar value.
+ scalar: Scalar<C>,
+
+ /// Mask value.
+ mask: Scalar<C>,
+}
+
+impl<C> BlindedScalar<C>
+where
+ C: CurveArithmetic,
+{
+ /// Create a new [`BlindedScalar`] from a scalar and a [`CryptoRngCore`].
+ pub fn new(scalar: Scalar<C>, rng: &mut impl CryptoRngCore) -> Self {
+ Self {
+ scalar,
+ mask: Scalar::<C>::random(rng),
+ }
+ }
+}
+
+impl<C> AsRef<Scalar<C>> for BlindedScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn as_ref(&self) -> &Scalar<C> {
+ &self.scalar
+ }
+}
+
+impl<C> Invert for BlindedScalar<C>
+where
+ C: CurveArithmetic,
+{
+ type Output = CtOption<Scalar<C>>;
+
+ fn invert(&self) -> CtOption<Scalar<C>> {
+ // prevent side channel analysis of scalar inversion by pre-and-post-multiplying
+ // with the random masking scalar
+ (self.scalar * self.mask)
+ .invert_vartime()
+ .map(|s| s * self.mask)
+ }
+}
+
+impl<C> Drop for BlindedScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn drop(&mut self) {
+ self.scalar.zeroize();
+ self.mask.zeroize();
+ }
+}
diff --git a/vendor/elliptic-curve/src/scalar/nonzero.rs b/vendor/elliptic-curve/src/scalar/nonzero.rs
new file mode 100644
index 0000000..c0e4574
--- /dev/null
+++ b/vendor/elliptic-curve/src/scalar/nonzero.rs
@@ -0,0 +1,405 @@
+//! Non-zero scalar type.
+
+use crate::{
+ ops::{Invert, Reduce, ReduceNonZero},
+ scalar::IsHigh,
+ CurveArithmetic, Error, FieldBytes, PrimeCurve, Scalar, ScalarPrimitive, SecretKey,
+};
+use base16ct::HexDisplay;
+use core::{
+ fmt,
+ ops::{Deref, Mul, Neg},
+ str,
+};
+use crypto_bigint::{ArrayEncoding, Integer};
+use ff::{Field, PrimeField};
+use generic_array::{typenum::Unsigned, GenericArray};
+use rand_core::CryptoRngCore;
+use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
+use zeroize::Zeroize;
+
+#[cfg(feature = "serde")]
+use serdect::serde::{de, ser, Deserialize, Serialize};
+
+/// Non-zero scalar type.
+///
+/// This type ensures that its value is not zero, ala `core::num::NonZero*`.
+/// To do this, the generic `S` type must impl both `Default` and
+/// `ConstantTimeEq`, with the requirement that `S::default()` returns 0.
+///
+/// In the context of ECC, it's useful for ensuring that scalar multiplication
+/// cannot result in the point at infinity.
+#[derive(Clone)]
+pub struct NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ scalar: Scalar<C>,
+}
+
+impl<C> NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ /// Generate a random `NonZeroScalar`.
+ pub fn random(mut rng: &mut impl CryptoRngCore) -> Self {
+ // Use rejection sampling to eliminate zero values.
+ // While this method isn't constant-time, the attacker shouldn't learn
+ // anything about unrelated outputs so long as `rng` is a secure `CryptoRng`.
+ loop {
+ if let Some(result) = Self::new(Field::random(&mut rng)).into() {
+ break result;
+ }
+ }
+ }
+
+ /// Create a [`NonZeroScalar`] from a scalar.
+ pub fn new(scalar: Scalar<C>) -> CtOption<Self> {
+ CtOption::new(Self { scalar }, !scalar.is_zero())
+ }
+
+ /// Decode a [`NonZeroScalar`] from a big endian-serialized field element.
+ pub fn from_repr(repr: FieldBytes<C>) -> CtOption<Self> {
+ Scalar::<C>::from_repr(repr).and_then(Self::new)
+ }
+
+ /// Create a [`NonZeroScalar`] from a `C::Uint`.
+ pub fn from_uint(uint: C::Uint) -> CtOption<Self> {
+ ScalarPrimitive::new(uint).and_then(|scalar| Self::new(scalar.into()))
+ }
+}
+
+impl<C> AsRef<Scalar<C>> for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn as_ref(&self) -> &Scalar<C> {
+ &self.scalar
+ }
+}
+
+impl<C> ConditionallySelectable for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ Self {
+ scalar: Scalar::<C>::conditional_select(&a.scalar, &b.scalar, choice),
+ }
+ }
+}
+
+impl<C> ConstantTimeEq for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn ct_eq(&self, other: &Self) -> Choice {
+ self.scalar.ct_eq(&other.scalar)
+ }
+}
+
+impl<C> Copy for NonZeroScalar<C> where C: CurveArithmetic {}
+
+impl<C> Deref for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ type Target = Scalar<C>;
+
+ fn deref(&self) -> &Scalar<C> {
+ &self.scalar
+ }
+}
+
+impl<C> From<NonZeroScalar<C>> for FieldBytes<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(scalar: NonZeroScalar<C>) -> FieldBytes<C> {
+ Self::from(&scalar)
+ }
+}
+
+impl<C> From<&NonZeroScalar<C>> for FieldBytes<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(scalar: &NonZeroScalar<C>) -> FieldBytes<C> {
+ scalar.to_repr()
+ }
+}
+
+impl<C> From<NonZeroScalar<C>> for ScalarPrimitive<C>
+where
+ C: CurveArithmetic,
+{
+ #[inline]
+ fn from(scalar: NonZeroScalar<C>) -> ScalarPrimitive<C> {
+ Self::from(&scalar)
+ }
+}
+
+impl<C> From<&NonZeroScalar<C>> for ScalarPrimitive<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(scalar: &NonZeroScalar<C>) -> ScalarPrimitive<C> {
+ ScalarPrimitive::from_bytes(&scalar.to_repr()).unwrap()
+ }
+}
+
+impl<C> From<SecretKey<C>> for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(sk: SecretKey<C>) -> NonZeroScalar<C> {
+ Self::from(&sk)
+ }
+}
+
+impl<C> From<&SecretKey<C>> for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(sk: &SecretKey<C>) -> NonZeroScalar<C> {
+ let scalar = sk.as_scalar_primitive().to_scalar();
+ debug_assert!(!bool::from(scalar.is_zero()));
+ Self { scalar }
+ }
+}
+
+impl<C> Invert for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+ Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
+{
+ type Output = Self;
+
+ fn invert(&self) -> Self {
+ Self {
+ // This will always succeed since `scalar` will never be 0
+ scalar: Invert::invert(&self.scalar).unwrap(),
+ }
+ }
+
+ fn invert_vartime(&self) -> Self::Output {
+ Self {
+ // This will always succeed since `scalar` will never be 0
+ scalar: Invert::invert_vartime(&self.scalar).unwrap(),
+ }
+ }
+}
+
+impl<C> IsHigh for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn is_high(&self) -> Choice {
+ self.scalar.is_high()
+ }
+}
+
+impl<C> Neg for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ type Output = NonZeroScalar<C>;
+
+ fn neg(self) -> NonZeroScalar<C> {
+ let scalar = -self.scalar;
+ debug_assert!(!bool::from(scalar.is_zero()));
+ NonZeroScalar { scalar }
+ }
+}
+
+impl<C> Mul<NonZeroScalar<C>> for NonZeroScalar<C>
+where
+ C: PrimeCurve + CurveArithmetic,
+{
+ type Output = Self;
+
+ #[inline]
+ fn mul(self, other: Self) -> Self {
+ Self::mul(self, &other)
+ }
+}
+
+impl<C> Mul<&NonZeroScalar<C>> for NonZeroScalar<C>
+where
+ C: PrimeCurve + CurveArithmetic,
+{
+ type Output = Self;
+
+ fn mul(self, other: &Self) -> Self {
+ // Multiplication is modulo a prime, so the product of two non-zero
+ // scalars is also non-zero.
+ let scalar = self.scalar * other.scalar;
+ debug_assert!(!bool::from(scalar.is_zero()));
+ NonZeroScalar { scalar }
+ }
+}
+
+/// Note: this is a non-zero reduction, as it's impl'd for [`NonZeroScalar`].
+impl<C, I> Reduce<I> for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+ I: Integer + ArrayEncoding,
+ Scalar<C>: Reduce<I> + ReduceNonZero<I>,
+{
+ type Bytes = <Scalar<C> as Reduce<I>>::Bytes;
+
+ fn reduce(n: I) -> Self {
+ let scalar = Scalar::<C>::reduce_nonzero(n);
+ debug_assert!(!bool::from(scalar.is_zero()));
+ Self { scalar }
+ }
+
+ fn reduce_bytes(bytes: &Self::Bytes) -> Self {
+ let scalar = Scalar::<C>::reduce_nonzero_bytes(bytes);
+ debug_assert!(!bool::from(scalar.is_zero()));
+ Self { scalar }
+ }
+}
+
+/// Note: forwards to the [`Reduce`] impl.
+impl<C, I> ReduceNonZero<I> for NonZeroScalar<C>
+where
+ Self: Reduce<I>,
+ C: CurveArithmetic,
+ I: Integer + ArrayEncoding,
+ Scalar<C>: Reduce<I, Bytes = Self::Bytes> + ReduceNonZero<I>,
+{
+ fn reduce_nonzero(n: I) -> Self {
+ Self::reduce(n)
+ }
+
+ fn reduce_nonzero_bytes(bytes: &Self::Bytes) -> Self {
+ Self::reduce_bytes(bytes)
+ }
+}
+
+impl<C> TryFrom<&[u8]> for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ type Error = Error;
+
+ fn try_from(bytes: &[u8]) -> Result<Self, Error> {
+ if bytes.len() == C::FieldBytesSize::USIZE {
+ Option::from(NonZeroScalar::from_repr(GenericArray::clone_from_slice(
+ bytes,
+ )))
+ .ok_or(Error)
+ } else {
+ Err(Error)
+ }
+ }
+}
+
+impl<C> Zeroize for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn zeroize(&mut self) {
+ // Use zeroize's volatile writes to ensure value is cleared.
+ self.scalar.zeroize();
+
+ // Write a 1 instead of a 0 to ensure this type's non-zero invariant
+ // is upheld.
+ self.scalar = Scalar::<C>::ONE;
+ }
+}
+
+impl<C> fmt::Display for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{self:X}")
+ }
+}
+
+impl<C> fmt::LowerHex for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:x}", HexDisplay(&self.to_repr()))
+ }
+}
+
+impl<C> fmt::UpperHex for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:}", HexDisplay(&self.to_repr()))
+ }
+}
+
+impl<C> str::FromStr for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ type Err = Error;
+
+ fn from_str(hex: &str) -> Result<Self, Error> {
+ let mut bytes = FieldBytes::<C>::default();
+
+ if base16ct::mixed::decode(hex, &mut bytes)?.len() == bytes.len() {
+ Option::from(Self::from_repr(bytes)).ok_or(Error)
+ } else {
+ Err(Error)
+ }
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<C> Serialize for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: ser::Serializer,
+ {
+ ScalarPrimitive::from(self).serialize(serializer)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, C> Deserialize<'de> for NonZeroScalar<C>
+where
+ C: CurveArithmetic,
+{
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ let scalar = ScalarPrimitive::deserialize(deserializer)?;
+ Option::from(Self::new(scalar.into()))
+ .ok_or_else(|| de::Error::custom("expected non-zero scalar"))
+ }
+}
+
+#[cfg(all(test, feature = "dev"))]
+mod tests {
+ use crate::dev::{NonZeroScalar, Scalar};
+ use ff::{Field, PrimeField};
+ use hex_literal::hex;
+ use zeroize::Zeroize;
+
+ #[test]
+ fn round_trip() {
+ let bytes = hex!("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
+ let scalar = NonZeroScalar::from_repr(bytes.into()).unwrap();
+ assert_eq!(&bytes, scalar.to_repr().as_slice());
+ }
+
+ #[test]
+ fn zeroize() {
+ let mut scalar = NonZeroScalar::new(Scalar::from(42u64)).unwrap();
+ scalar.zeroize();
+ assert_eq!(*scalar, Scalar::ONE);
+ }
+}
diff --git a/vendor/elliptic-curve/src/scalar/primitive.rs b/vendor/elliptic-curve/src/scalar/primitive.rs
new file mode 100644
index 0000000..a4f64cb
--- /dev/null
+++ b/vendor/elliptic-curve/src/scalar/primitive.rs
@@ -0,0 +1,434 @@
+//! Generic scalar type with primitive functionality.
+
+use crate::{
+ bigint::{prelude::*, Limb, NonZero},
+ scalar::FromUintUnchecked,
+ scalar::IsHigh,
+ Curve, Error, FieldBytes, FieldBytesEncoding, Result,
+};
+use base16ct::HexDisplay;
+use core::{
+ cmp::Ordering,
+ fmt,
+ ops::{Add, AddAssign, Neg, ShrAssign, Sub, SubAssign},
+ str,
+};
+use generic_array::{typenum::Unsigned, GenericArray};
+use rand_core::CryptoRngCore;
+use subtle::{
+ Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
+ CtOption,
+};
+use zeroize::DefaultIsZeroes;
+
+#[cfg(feature = "arithmetic")]
+use super::{CurveArithmetic, Scalar};
+
+#[cfg(feature = "serde")]
+use serdect::serde::{de, ser, Deserialize, Serialize};
+
+/// Generic scalar type with primitive functionality.
+///
+/// This type provides a baseline level of scalar arithmetic functionality
+/// which is always available for all curves, regardless of if they implement
+/// any arithmetic traits.
+///
+/// # `serde` support
+///
+/// When the optional `serde` feature of this create is enabled, [`Serialize`]
+/// and [`Deserialize`] impls are provided for this type.
+///
+/// The serialization is a fixed-width big endian encoding. When used with
+/// textual formats, the binary data is encoded as hexadecimal.
+// TODO(tarcieri): use `crypto-bigint`'s `Residue` type, expose more functionality?
+#[derive(Copy, Clone, Debug, Default)]
+pub struct ScalarPrimitive<C: Curve> {
+ /// Inner unsigned integer type.
+ inner: C::Uint,
+}
+
+impl<C> ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ /// Zero scalar.
+ pub const ZERO: Self = Self {
+ inner: C::Uint::ZERO,
+ };
+
+ /// Multiplicative identity.
+ pub const ONE: Self = Self {
+ inner: C::Uint::ONE,
+ };
+
+ /// Scalar modulus.
+ pub const MODULUS: C::Uint = C::ORDER;
+
+ /// Generate a random [`ScalarPrimitive`].
+ pub fn random(rng: &mut impl CryptoRngCore) -> Self {
+ Self {
+ inner: C::Uint::random_mod(rng, &NonZero::new(Self::MODULUS).unwrap()),
+ }
+ }
+
+ /// Create a new scalar from [`Curve::Uint`].
+ pub fn new(uint: C::Uint) -> CtOption<Self> {
+ CtOption::new(Self { inner: uint }, uint.ct_lt(&Self::MODULUS))
+ }
+
+ /// Decode [`ScalarPrimitive`] from a serialized field element
+ pub fn from_bytes(bytes: &FieldBytes<C>) -> CtOption<Self> {
+ Self::new(C::Uint::decode_field_bytes(bytes))
+ }
+
+ /// Decode [`ScalarPrimitive`] from a big endian byte slice.
+ pub fn from_slice(slice: &[u8]) -> Result<Self> {
+ if slice.len() == C::FieldBytesSize::USIZE {
+ Option::from(Self::from_bytes(GenericArray::from_slice(slice))).ok_or(Error)
+ } else {
+ Err(Error)
+ }
+ }
+
+ /// Borrow the inner `C::Uint`.
+ pub fn as_uint(&self) -> &C::Uint {
+ &self.inner
+ }
+
+ /// Borrow the inner limbs as a slice.
+ pub fn as_limbs(&self) -> &[Limb] {
+ self.inner.as_ref()
+ }
+
+ /// Is this [`ScalarPrimitive`] value equal to zero?
+ pub fn is_zero(&self) -> Choice {
+ self.inner.is_zero()
+ }
+
+ /// Is this [`ScalarPrimitive`] value even?
+ pub fn is_even(&self) -> Choice {
+ self.inner.is_even()
+ }
+
+ /// Is this [`ScalarPrimitive`] value odd?
+ pub fn is_odd(&self) -> Choice {
+ self.inner.is_odd()
+ }
+
+ /// Encode [`ScalarPrimitive`] as a serialized field element.
+ pub fn to_bytes(&self) -> FieldBytes<C> {
+ self.inner.encode_field_bytes()
+ }
+
+ /// Convert to a `C::Uint`.
+ pub fn to_uint(&self) -> C::Uint {
+ self.inner
+ }
+}
+
+impl<C> FromUintUnchecked for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Uint = C::Uint;
+
+ fn from_uint_unchecked(uint: C::Uint) -> Self {
+ Self { inner: uint }
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> ScalarPrimitive<C>
+where
+ C: CurveArithmetic,
+{
+ /// Convert [`ScalarPrimitive`] into a given curve's scalar type.
+ pub(super) fn to_scalar(self) -> Scalar<C> {
+ Scalar::<C>::from_uint_unchecked(self.inner)
+ }
+}
+
+// TODO(tarcieri): better encapsulate this?
+impl<C> AsRef<[Limb]> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn as_ref(&self) -> &[Limb] {
+ self.as_limbs()
+ }
+}
+
+impl<C> ConditionallySelectable for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ Self {
+ inner: C::Uint::conditional_select(&a.inner, &b.inner, choice),
+ }
+ }
+}
+
+impl<C> ConstantTimeEq for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn ct_eq(&self, other: &Self) -> Choice {
+ self.inner.ct_eq(&other.inner)
+ }
+}
+
+impl<C> ConstantTimeLess for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn ct_lt(&self, other: &Self) -> Choice {
+ self.inner.ct_lt(&other.inner)
+ }
+}
+
+impl<C> ConstantTimeGreater for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn ct_gt(&self, other: &Self) -> Choice {
+ self.inner.ct_gt(&other.inner)
+ }
+}
+
+impl<C: Curve> DefaultIsZeroes for ScalarPrimitive<C> {}
+
+impl<C: Curve> Eq for ScalarPrimitive<C> {}
+
+impl<C> PartialEq for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn eq(&self, other: &Self) -> bool {
+ self.ct_eq(other).into()
+ }
+}
+
+impl<C> PartialOrd for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl<C> Ord for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.inner.cmp(&other.inner)
+ }
+}
+
+impl<C> From<u64> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn from(n: u64) -> Self {
+ Self {
+ inner: C::Uint::from(n),
+ }
+ }
+}
+
+impl<C> Add<ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Output = Self;
+
+ fn add(self, other: Self) -> Self {
+ self.add(&other)
+ }
+}
+
+impl<C> Add<&ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Output = Self;
+
+ fn add(self, other: &Self) -> Self {
+ Self {
+ inner: self.inner.add_mod(&other.inner, &Self::MODULUS),
+ }
+ }
+}
+
+impl<C> AddAssign<ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn add_assign(&mut self, other: Self) {
+ *self = *self + other;
+ }
+}
+
+impl<C> AddAssign<&ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn add_assign(&mut self, other: &Self) {
+ *self = *self + other;
+ }
+}
+
+impl<C> Sub<ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Output = Self;
+
+ fn sub(self, other: Self) -> Self {
+ self.sub(&other)
+ }
+}
+
+impl<C> Sub<&ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Output = Self;
+
+ fn sub(self, other: &Self) -> Self {
+ Self {
+ inner: self.inner.sub_mod(&other.inner, &Self::MODULUS),
+ }
+ }
+}
+
+impl<C> SubAssign<ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn sub_assign(&mut self, other: Self) {
+ *self = *self - other;
+ }
+}
+
+impl<C> SubAssign<&ScalarPrimitive<C>> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn sub_assign(&mut self, other: &Self) {
+ *self = *self - other;
+ }
+}
+
+impl<C> Neg for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Output = Self;
+
+ fn neg(self) -> Self {
+ Self {
+ inner: self.inner.neg_mod(&Self::MODULUS),
+ }
+ }
+}
+
+impl<C> Neg for &ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Output = ScalarPrimitive<C>;
+
+ fn neg(self) -> ScalarPrimitive<C> {
+ -*self
+ }
+}
+
+impl<C> ShrAssign<usize> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn shr_assign(&mut self, rhs: usize) {
+ self.inner >>= rhs;
+ }
+}
+
+impl<C> IsHigh for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn is_high(&self) -> Choice {
+ let n_2 = C::ORDER >> 1;
+ self.inner.ct_gt(&n_2)
+ }
+}
+
+impl<C> fmt::Display for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{self:X}")
+ }
+}
+
+impl<C> fmt::LowerHex for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:x}", HexDisplay(&self.to_bytes()))
+ }
+}
+
+impl<C> fmt::UpperHex for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:X}", HexDisplay(&self.to_bytes()))
+ }
+}
+
+impl<C> str::FromStr for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ type Err = Error;
+
+ fn from_str(hex: &str) -> Result<Self> {
+ let mut bytes = FieldBytes::<C>::default();
+ base16ct::lower::decode(hex, &mut bytes)?;
+ Self::from_slice(&bytes)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<C> Serialize for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
+ where
+ S: ser::Serializer,
+ {
+ serdect::array::serialize_hex_upper_or_bin(&self.to_bytes(), serializer)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, C> Deserialize<'de> for ScalarPrimitive<C>
+where
+ C: Curve,
+{
+ fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ let mut bytes = FieldBytes::<C>::default();
+ serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
+ Self::from_slice(&bytes).map_err(|_| de::Error::custom("scalar out of range"))
+ }
+}
diff --git a/vendor/elliptic-curve/src/sec1.rs b/vendor/elliptic-curve/src/sec1.rs
new file mode 100644
index 0000000..7673386
--- /dev/null
+++ b/vendor/elliptic-curve/src/sec1.rs
@@ -0,0 +1,114 @@
+//! Support for SEC1 elliptic curve encoding formats.
+//!
+//! <https://www.secg.org/sec1-v2.pdf>
+
+pub use sec1::point::{Coordinates, ModulusSize, Tag};
+
+use crate::{Curve, FieldBytesSize, Result, SecretKey};
+use generic_array::GenericArray;
+use subtle::CtOption;
+
+#[cfg(feature = "arithmetic")]
+use crate::{AffinePoint, CurveArithmetic, Error};
+
+/// Encoded elliptic curve point with point compression.
+pub type CompressedPoint<C> = GenericArray<u8, CompressedPointSize<C>>;
+
+/// Size of a compressed elliptic curve point.
+pub type CompressedPointSize<C> = <FieldBytesSize<C> as ModulusSize>::CompressedPointSize;
+
+/// Encoded elliptic curve point sized appropriately for a given curve.
+pub type EncodedPoint<C> = sec1::point::EncodedPoint<FieldBytesSize<C>>;
+
+/// Encoded elliptic curve point *without* point compression.
+pub type UncompressedPoint<C> = GenericArray<u8, UncompressedPointSize<C>>;
+
+/// Size of an uncompressed elliptic curve point.
+pub type UncompressedPointSize<C> = <FieldBytesSize<C> as ModulusSize>::UncompressedPointSize;
+
+/// Trait for deserializing a value from a SEC1 encoded curve point.
+///
+/// This is intended for use with the `AffinePoint` type for a given elliptic curve.
+pub trait FromEncodedPoint<C>
+where
+ Self: Sized,
+ C: Curve,
+ FieldBytesSize<C>: ModulusSize,
+{
+ /// Deserialize the type this trait is impl'd on from an [`EncodedPoint`].
+ fn from_encoded_point(point: &EncodedPoint<C>) -> CtOption<Self>;
+}
+
+/// Trait for serializing a value to a SEC1 encoded curve point.
+///
+/// This is intended for use with the `AffinePoint` type for a given elliptic curve.
+pub trait ToEncodedPoint<C>
+where
+ C: Curve,
+ FieldBytesSize<C>: ModulusSize,
+{
+ /// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying
+ /// point compression.
+ fn to_encoded_point(&self, compress: bool) -> EncodedPoint<C>;
+}
+
+/// Trait for serializing a value to a SEC1 encoded curve point with compaction.
+///
+/// This is intended for use with the `AffinePoint` type for a given elliptic curve.
+pub trait ToCompactEncodedPoint<C>
+where
+ C: Curve,
+ FieldBytesSize<C>: ModulusSize,
+{
+ /// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying
+ /// point compression.
+ fn to_compact_encoded_point(&self) -> CtOption<EncodedPoint<C>>;
+}
+
+/// Validate that the given [`EncodedPoint`] represents the encoded public key
+/// value of the given secret.
+///
+/// Curve implementations which also impl [`CurveArithmetic`] will receive
+/// a blanket default impl of this trait.
+pub trait ValidatePublicKey
+where
+ Self: Curve,
+ FieldBytesSize<Self>: ModulusSize,
+{
+ /// Validate that the given [`EncodedPoint`] is a valid public key for the
+ /// provided secret value.
+ #[allow(unused_variables)]
+ fn validate_public_key(
+ secret_key: &SecretKey<Self>,
+ public_key: &EncodedPoint<Self>,
+ ) -> Result<()> {
+ // Provide a default "always succeeds" implementation.
+ // This is the intended default for curve implementations which
+ // do not provide an arithmetic implementation, since they have no
+ // way to verify this.
+ //
+ // Implementations with an arithmetic impl will receive a blanket impl
+ // of this trait.
+ Ok(())
+ }
+}
+
+#[cfg(all(feature = "arithmetic"))]
+impl<C> ValidatePublicKey for C
+where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn validate_public_key(secret_key: &SecretKey<C>, public_key: &EncodedPoint<C>) -> Result<()> {
+ let pk = secret_key
+ .public_key()
+ .to_encoded_point(public_key.is_compressed());
+
+ if public_key == &pk {
+ Ok(())
+ } else {
+ Err(Error)
+ }
+ }
+}
diff --git a/vendor/elliptic-curve/src/secret_key.rs b/vendor/elliptic-curve/src/secret_key.rs
new file mode 100644
index 0000000..607589a
--- /dev/null
+++ b/vendor/elliptic-curve/src/secret_key.rs
@@ -0,0 +1,393 @@
+//! Secret keys for elliptic curves (i.e. private scalars).
+//!
+//! The [`SecretKey`] type is a wrapper around a secret scalar value which is
+//! designed to prevent unintentional exposure (e.g. via `Debug` or other
+//! logging). It also handles zeroing the secret value out of memory securely
+//! on drop.
+
+#[cfg(all(feature = "pkcs8", feature = "sec1"))]
+mod pkcs8;
+
+use crate::{Curve, Error, FieldBytes, Result, ScalarPrimitive};
+use core::fmt::{self, Debug};
+use generic_array::typenum::Unsigned;
+use subtle::{Choice, ConstantTimeEq};
+use zeroize::{Zeroize, ZeroizeOnDrop};
+
+#[cfg(feature = "arithmetic")]
+use crate::{rand_core::CryptoRngCore, CurveArithmetic, NonZeroScalar, PublicKey};
+
+#[cfg(feature = "jwk")]
+use crate::jwk::{JwkEcKey, JwkParameters};
+
+#[cfg(feature = "pem")]
+use pem_rfc7468::{self as pem, PemLabel};
+
+#[cfg(feature = "sec1")]
+use {
+ crate::{
+ sec1::{EncodedPoint, ModulusSize, ValidatePublicKey},
+ FieldBytesSize,
+ },
+ sec1::der,
+};
+
+#[cfg(all(feature = "alloc", feature = "arithmetic", feature = "sec1"))]
+use {
+ crate::{
+ sec1::{FromEncodedPoint, ToEncodedPoint},
+ AffinePoint,
+ },
+ alloc::vec::Vec,
+ sec1::der::Encode,
+ zeroize::Zeroizing,
+};
+
+#[cfg(all(feature = "arithmetic", any(feature = "jwk", feature = "pem")))]
+use alloc::string::String;
+
+#[cfg(all(feature = "arithmetic", feature = "jwk"))]
+use alloc::string::ToString;
+
+#[cfg(all(doc, feature = "pkcs8"))]
+use {crate::pkcs8::DecodePrivateKey, core::str::FromStr};
+
+/// Elliptic curve secret keys.
+///
+/// This type wraps a secret scalar value, helping to prevent accidental
+/// exposure and securely erasing the value from memory when dropped.
+///
+/// # Parsing PKCS#8 Keys
+///
+/// PKCS#8 is a commonly used format for encoding secret keys (especially ones
+/// generated by OpenSSL).
+///
+/// Keys in PKCS#8 format are either binary (ASN.1 BER/DER), or PEM encoded
+/// (ASCII) and begin with the following:
+///
+/// ```text
+/// -----BEGIN PRIVATE KEY-----
+/// ```
+///
+/// To decode an elliptic curve private key from PKCS#8, enable the `pkcs8`
+/// feature of this crate (or the `pkcs8` feature of a specific RustCrypto
+/// elliptic curve crate) and use the [`DecodePrivateKey`] trait to parse it.
+///
+/// When the `pem` feature of this crate (or a specific RustCrypto elliptic
+/// curve crate) is enabled, a [`FromStr`] impl is also available.
+#[derive(Clone)]
+pub struct SecretKey<C: Curve> {
+ /// Scalar value
+ inner: ScalarPrimitive<C>,
+}
+
+impl<C> SecretKey<C>
+where
+ C: Curve,
+{
+ /// Generate a random [`SecretKey`].
+ #[cfg(feature = "arithmetic")]
+ pub fn random(rng: &mut impl CryptoRngCore) -> Self
+ where
+ C: CurveArithmetic,
+ {
+ Self {
+ inner: NonZeroScalar::<C>::random(rng).into(),
+ }
+ }
+
+ /// Create a new secret key from a scalar value.
+ pub fn new(scalar: ScalarPrimitive<C>) -> Self {
+ Self { inner: scalar }
+ }
+
+ /// Borrow the inner secret [`ScalarPrimitive`] value.
+ ///
+ /// # ⚠️ Warning
+ ///
+ /// This value is key material.
+ ///
+ /// Please treat it with the care it deserves!
+ pub fn as_scalar_primitive(&self) -> &ScalarPrimitive<C> {
+ &self.inner
+ }
+
+ /// Get the secret [`NonZeroScalar`] value for this key.
+ ///
+ /// # ⚠️ Warning
+ ///
+ /// This value is key material.
+ ///
+ /// Please treat it with the care it deserves!
+ #[cfg(feature = "arithmetic")]
+ pub fn to_nonzero_scalar(&self) -> NonZeroScalar<C>
+ where
+ C: CurveArithmetic,
+ {
+ self.into()
+ }
+
+ /// Get the [`PublicKey`] which corresponds to this secret key
+ #[cfg(feature = "arithmetic")]
+ pub fn public_key(&self) -> PublicKey<C>
+ where
+ C: CurveArithmetic,
+ {
+ PublicKey::from_secret_scalar(&self.to_nonzero_scalar())
+ }
+
+ /// Deserialize secret key from an encoded secret scalar.
+ pub fn from_bytes(bytes: &FieldBytes<C>) -> Result<Self> {
+ let inner: ScalarPrimitive<C> =
+ Option::from(ScalarPrimitive::from_bytes(bytes)).ok_or(Error)?;
+
+ if inner.is_zero().into() {
+ return Err(Error);
+ }
+
+ Ok(Self { inner })
+ }
+
+ /// Deserialize secret key from an encoded secret scalar passed as a
+ /// byte slice.
+ ///
+ /// The slice is expected to be at most `C::FieldBytesSize` bytes in
+ /// length but may be up to 4-bytes shorter than that, which is handled by
+ /// zero-padding the value.
+ pub fn from_slice(slice: &[u8]) -> Result<Self> {
+ if slice.len() > C::FieldBytesSize::USIZE {
+ return Err(Error);
+ }
+
+ /// Maximum number of "missing" bytes to interpret as zeroes.
+ const MAX_LEADING_ZEROES: usize = 4;
+
+ let offset = C::FieldBytesSize::USIZE.saturating_sub(slice.len());
+
+ if offset == 0 {
+ Self::from_bytes(FieldBytes::<C>::from_slice(slice))
+ } else if offset <= MAX_LEADING_ZEROES {
+ let mut bytes = FieldBytes::<C>::default();
+ bytes[offset..].copy_from_slice(slice);
+
+ let ret = Self::from_bytes(&bytes);
+ bytes.zeroize();
+ ret
+ } else {
+ Err(Error)
+ }
+ }
+
+ /// Serialize raw secret scalar as a big endian integer.
+ pub fn to_bytes(&self) -> FieldBytes<C> {
+ self.inner.to_bytes()
+ }
+
+ /// Deserialize secret key encoded in the SEC1 ASN.1 DER `ECPrivateKey` format.
+ #[cfg(all(feature = "sec1"))]
+ pub fn from_sec1_der(der_bytes: &[u8]) -> Result<Self>
+ where
+ C: Curve + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ sec1::EcPrivateKey::try_from(der_bytes)?
+ .try_into()
+ .map_err(|_| Error)
+ }
+
+ /// Serialize secret key in the SEC1 ASN.1 DER `ECPrivateKey` format.
+ #[cfg(all(feature = "alloc", feature = "arithmetic", feature = "sec1"))]
+ pub fn to_sec1_der(&self) -> der::Result<Zeroizing<Vec<u8>>>
+ where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ let private_key_bytes = Zeroizing::new(self.to_bytes());
+ let public_key_bytes = self.public_key().to_encoded_point(false);
+
+ let ec_private_key = Zeroizing::new(
+ sec1::EcPrivateKey {
+ private_key: &private_key_bytes,
+ parameters: None,
+ public_key: Some(public_key_bytes.as_bytes()),
+ }
+ .to_der()?,
+ );
+
+ Ok(ec_private_key)
+ }
+
+ /// Parse [`SecretKey`] from PEM-encoded SEC1 `ECPrivateKey` format.
+ ///
+ /// PEM-encoded SEC1 keys can be identified by the leading delimiter:
+ ///
+ /// ```text
+ /// -----BEGIN EC PRIVATE KEY-----
+ /// ```
+ #[cfg(feature = "pem")]
+ pub fn from_sec1_pem(s: &str) -> Result<Self>
+ where
+ C: Curve + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ let (label, der_bytes) = pem::decode_vec(s.as_bytes()).map_err(|_| Error)?;
+
+ if label != sec1::EcPrivateKey::PEM_LABEL {
+ return Err(Error);
+ }
+
+ Self::from_sec1_der(&der_bytes).map_err(|_| Error)
+ }
+
+ /// Serialize private key as self-zeroizing PEM-encoded SEC1 `ECPrivateKey`
+ /// with the given [`pem::LineEnding`].
+ ///
+ /// Pass `Default::default()` to use the OS's native line endings.
+ #[cfg(feature = "pem")]
+ pub fn to_sec1_pem(&self, line_ending: pem::LineEnding) -> Result<Zeroizing<String>>
+ where
+ C: CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ self.to_sec1_der()
+ .ok()
+ .and_then(|der| {
+ pem::encode_string(sec1::EcPrivateKey::PEM_LABEL, line_ending, &der).ok()
+ })
+ .map(Zeroizing::new)
+ .ok_or(Error)
+ }
+
+ /// Parse a [`JwkEcKey`] JSON Web Key (JWK) into a [`SecretKey`].
+ #[cfg(feature = "jwk")]
+ pub fn from_jwk(jwk: &JwkEcKey) -> Result<Self>
+ where
+ C: JwkParameters + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ Self::try_from(jwk)
+ }
+
+ /// Parse a string containing a JSON Web Key (JWK) into a [`SecretKey`].
+ #[cfg(feature = "jwk")]
+ pub fn from_jwk_str(jwk: &str) -> Result<Self>
+ where
+ C: JwkParameters + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ jwk.parse::<JwkEcKey>().and_then(|jwk| Self::from_jwk(&jwk))
+ }
+
+ /// Serialize this secret key as [`JwkEcKey`] JSON Web Key (JWK).
+ #[cfg(all(feature = "arithmetic", feature = "jwk"))]
+ pub fn to_jwk(&self) -> JwkEcKey
+ where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ self.into()
+ }
+
+ /// Serialize this secret key as JSON Web Key (JWK) string.
+ #[cfg(all(feature = "arithmetic", feature = "jwk"))]
+ pub fn to_jwk_string(&self) -> Zeroizing<String>
+ where
+ C: CurveArithmetic + JwkParameters,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+ {
+ Zeroizing::new(self.to_jwk().to_string())
+ }
+}
+
+impl<C> ConstantTimeEq for SecretKey<C>
+where
+ C: Curve,
+{
+ fn ct_eq(&self, other: &Self) -> Choice {
+ self.inner.ct_eq(&other.inner)
+ }
+}
+
+impl<C> Debug for SecretKey<C>
+where
+ C: Curve,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct(core::any::type_name::<Self>())
+ .finish_non_exhaustive()
+ }
+}
+
+impl<C> ZeroizeOnDrop for SecretKey<C> where C: Curve {}
+
+impl<C> Drop for SecretKey<C>
+where
+ C: Curve,
+{
+ fn drop(&mut self) {
+ self.inner.zeroize();
+ }
+}
+
+impl<C: Curve> Eq for SecretKey<C> {}
+
+impl<C> PartialEq for SecretKey<C>
+where
+ C: Curve,
+{
+ fn eq(&self, other: &Self) -> bool {
+ self.ct_eq(other).into()
+ }
+}
+
+#[cfg(all(feature = "sec1"))]
+impl<C> TryFrom<sec1::EcPrivateKey<'_>> for SecretKey<C>
+where
+ C: Curve + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = der::Error;
+
+ fn try_from(sec1_private_key: sec1::EcPrivateKey<'_>) -> der::Result<Self> {
+ let secret_key = Self::from_slice(sec1_private_key.private_key)
+ .map_err(|_| der::Tag::Sequence.value_error())?;
+
+ // TODO(tarcieri): validate `sec1_private_key.params`?
+ if let Some(pk_bytes) = sec1_private_key.public_key {
+ let pk = EncodedPoint::<C>::from_bytes(pk_bytes)
+ .map_err(|_| der::Tag::BitString.value_error())?;
+
+ if C::validate_public_key(&secret_key, &pk).is_err() {
+ return Err(der::Tag::BitString.value_error());
+ }
+ }
+
+ Ok(secret_key)
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> From<NonZeroScalar<C>> for SecretKey<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(scalar: NonZeroScalar<C>) -> SecretKey<C> {
+ SecretKey::from(&scalar)
+ }
+}
+
+#[cfg(feature = "arithmetic")]
+impl<C> From<&NonZeroScalar<C>> for SecretKey<C>
+where
+ C: CurveArithmetic,
+{
+ fn from(scalar: &NonZeroScalar<C>) -> SecretKey<C> {
+ SecretKey {
+ inner: scalar.into(),
+ }
+ }
+}
diff --git a/vendor/elliptic-curve/src/secret_key/pkcs8.rs b/vendor/elliptic-curve/src/secret_key/pkcs8.rs
new file mode 100644
index 0000000..92c81f1
--- /dev/null
+++ b/vendor/elliptic-curve/src/secret_key/pkcs8.rs
@@ -0,0 +1,90 @@
+//! PKCS#8 encoding/decoding support.
+
+use super::SecretKey;
+use crate::{
+ pkcs8::{self, der::Decode, AssociatedOid},
+ sec1::{ModulusSize, ValidatePublicKey},
+ Curve, FieldBytesSize, ALGORITHM_OID,
+};
+use pkcs8::spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, ObjectIdentifier};
+use sec1::EcPrivateKey;
+
+// Imports for the `EncodePrivateKey` impl
+#[cfg(all(feature = "alloc", feature = "arithmetic"))]
+use {
+ crate::{
+ sec1::{FromEncodedPoint, ToEncodedPoint},
+ AffinePoint, CurveArithmetic,
+ },
+ pkcs8::{der, EncodePrivateKey},
+};
+
+// Imports for actual PEM support
+#[cfg(feature = "pem")]
+use {
+ crate::{error::Error, Result},
+ core::str::FromStr,
+ pkcs8::DecodePrivateKey,
+};
+
+impl<C> AssociatedAlgorithmIdentifier for SecretKey<C>
+where
+ C: AssociatedOid + Curve,
+{
+ type Params = ObjectIdentifier;
+
+ const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<ObjectIdentifier> = AlgorithmIdentifier {
+ oid: ALGORITHM_OID,
+ parameters: Some(C::OID),
+ };
+}
+
+impl<C> TryFrom<pkcs8::PrivateKeyInfo<'_>> for SecretKey<C>
+where
+ C: AssociatedOid + Curve + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Error = pkcs8::Error;
+
+ fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result<Self> {
+ private_key_info
+ .algorithm
+ .assert_oids(ALGORITHM_OID, C::OID)?;
+
+ let ec_private_key = EcPrivateKey::from_der(private_key_info.private_key)?;
+ Ok(Self::try_from(ec_private_key)?)
+ }
+}
+
+#[cfg(all(feature = "alloc", feature = "arithmetic"))]
+impl<C> EncodePrivateKey for SecretKey<C>
+where
+ C: AssociatedOid + CurveArithmetic,
+ AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
+ FieldBytesSize<C>: ModulusSize,
+{
+ fn to_pkcs8_der(&self) -> pkcs8::Result<der::SecretDocument> {
+ // TODO(tarcieri): make `PrivateKeyInfo` generic around `Params`
+ let algorithm_identifier = pkcs8::AlgorithmIdentifierRef {
+ oid: ALGORITHM_OID,
+ parameters: Some((&C::OID).into()),
+ };
+
+ let ec_private_key = self.to_sec1_der()?;
+ let pkcs8_key = pkcs8::PrivateKeyInfo::new(algorithm_identifier, &ec_private_key);
+ Ok(der::SecretDocument::encode_msg(&pkcs8_key)?)
+ }
+}
+
+#[cfg(feature = "pem")]
+impl<C> FromStr for SecretKey<C>
+where
+ C: Curve + AssociatedOid + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
+{
+ type Err = Error;
+
+ fn from_str(s: &str) -> Result<Self> {
+ Self::from_pkcs8_pem(s).map_err(|_| Error)
+ }
+}
diff --git a/vendor/elliptic-curve/src/voprf.rs b/vendor/elliptic-curve/src/voprf.rs
new file mode 100644
index 0000000..68f2abf
--- /dev/null
+++ b/vendor/elliptic-curve/src/voprf.rs
@@ -0,0 +1,20 @@
+//! Verifiable Oblivious Pseudorandom Function (VOPRF) using prime order groups
+//!
+//! <https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/>
+
+use crate::PrimeCurve;
+
+/// Elliptic curve parameters used by VOPRF.
+pub trait VoprfParameters: PrimeCurve {
+ /// The `ID` parameter which identifies a particular elliptic curve
+ /// as defined in [section 4 of `draft-irtf-cfrg-voprf-19`][voprf].
+ ///
+ /// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-19.html#name-ciphersuites-2
+ const ID: &'static str;
+
+ /// The `Hash` parameter which assigns a particular hash function to this
+ /// ciphersuite as defined in [section 4 of `draft-irtf-cfrg-voprf-19`][voprf].
+ ///
+ /// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-19.html#name-ciphersuites-2
+ type Hash: digest::Digest;
+}
diff --git a/vendor/elliptic-curve/src/weierstrass.rs b/vendor/elliptic-curve/src/weierstrass.rs
new file mode 100644
index 0000000..1782d95
--- /dev/null
+++ b/vendor/elliptic-curve/src/weierstrass.rs
@@ -0,0 +1,128 @@
+//! Complete projective formulas for prime order elliptic curves as described
+//! in [Renes-Costello-Batina 2015].
+//!
+//! [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060
+
+#![allow(clippy::op_ref)]
+
+use ff::Field;
+
+/// Affine point whose coordinates are represented by the given field element.
+pub type AffinePoint<Fe> = (Fe, Fe);
+
+/// Projective point whose coordinates are represented by the given field element.
+pub type ProjectivePoint<Fe> = (Fe, Fe, Fe);
+
+/// Implements the complete addition formula from [Renes-Costello-Batina 2015]
+/// (Algorithm 4).
+///
+/// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060
+#[inline(always)]
+pub fn add<Fe>(
+ (ax, ay, az): ProjectivePoint<Fe>,
+ (bx, by, bz): ProjectivePoint<Fe>,
+ curve_equation_b: Fe,
+) -> ProjectivePoint<Fe>
+where
+ Fe: Field,
+{
+ // The comments after each line indicate which algorithm steps are being
+ // performed.
+ let xx = ax * bx; // 1
+ let yy = ay * by; // 2
+ let zz = az * bz; // 3
+ let xy_pairs = ((ax + ay) * &(bx + by)) - &(xx + &yy); // 4, 5, 6, 7, 8
+ let yz_pairs = ((ay + az) * &(by + bz)) - &(yy + &zz); // 9, 10, 11, 12, 13
+ let xz_pairs = ((ax + az) * &(bx + bz)) - &(xx + &zz); // 14, 15, 16, 17, 18
+
+ let bzz_part = xz_pairs - &(curve_equation_b * &zz); // 19, 20
+ let bzz3_part = bzz_part.double() + &bzz_part; // 21, 22
+ let yy_m_bzz3 = yy - &bzz3_part; // 23
+ let yy_p_bzz3 = yy + &bzz3_part; // 24
+
+ let zz3 = zz.double() + &zz; // 26, 27
+ let bxz_part = (curve_equation_b * &xz_pairs) - &(zz3 + &xx); // 25, 28, 29
+ let bxz3_part = bxz_part.double() + &bxz_part; // 30, 31
+ let xx3_m_zz3 = xx.double() + &xx - &zz3; // 32, 33, 34
+
+ (
+ (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 35, 39, 40
+ (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 36, 37, 38
+ (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 41, 42, 43
+ )
+}
+
+/// Implements the complete mixed addition formula from
+/// [Renes-Costello-Batina 2015] (Algorithm 5).
+///
+/// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060
+#[inline(always)]
+pub fn add_mixed<Fe>(
+ (ax, ay, az): ProjectivePoint<Fe>,
+ (bx, by): AffinePoint<Fe>,
+ curve_equation_b: Fe,
+) -> ProjectivePoint<Fe>
+where
+ Fe: Field,
+{
+ // The comments after each line indicate which algorithm steps are being
+ // performed.
+ let xx = ax * &bx; // 1
+ let yy = ay * &by; // 2
+ let xy_pairs = ((ax + &ay) * &(bx + &by)) - &(xx + &yy); // 3, 4, 5, 6, 7
+ let yz_pairs = (by * &az) + &ay; // 8, 9 (t4)
+ let xz_pairs = (bx * &az) + &ax; // 10, 11 (y3)
+
+ let bz_part = xz_pairs - &(curve_equation_b * &az); // 12, 13
+ let bz3_part = bz_part.double() + &bz_part; // 14, 15
+ let yy_m_bzz3 = yy - &bz3_part; // 16
+ let yy_p_bzz3 = yy + &bz3_part; // 17
+
+ let z3 = az.double() + &az; // 19, 20
+ let bxz_part = (curve_equation_b * &xz_pairs) - &(z3 + &xx); // 18, 21, 22
+ let bxz3_part = bxz_part.double() + &bxz_part; // 23, 24
+ let xx3_m_zz3 = xx.double() + &xx - &z3; // 25, 26, 27
+
+ (
+ (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 28, 32, 33
+ (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 29, 30, 31
+ (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 34, 35, 36
+ )
+}
+
+/// Implements the exception-free point doubling formula from
+/// [Renes-Costello-Batina 2015] (Algorithm 6).
+///
+/// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060
+#[inline(always)]
+pub fn double<Fe>((x, y, z): ProjectivePoint<Fe>, curve_equation_b: Fe) -> ProjectivePoint<Fe>
+where
+ Fe: Field,
+{
+ // The comments after each line indicate which algorithm steps are being
+ // performed.
+ let xx = x.square(); // 1
+ let yy = y.square(); // 2
+ let zz = z.square(); // 3
+ let xy2 = (x * &y).double(); // 4, 5
+ let xz2 = (x * &z).double(); // 6, 7
+
+ let bzz_part = (curve_equation_b * &zz) - &xz2; // 8, 9
+ let bzz3_part = bzz_part.double() + &bzz_part; // 10, 11
+ let yy_m_bzz3 = yy - &bzz3_part; // 12
+ let yy_p_bzz3 = yy + &bzz3_part; // 13
+ let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 14
+ let x_frag = yy_m_bzz3 * &xy2; // 15
+
+ let zz3 = zz.double() + &zz; // 16, 17
+ let bxz2_part = (curve_equation_b * &xz2) - &(zz3 + &xx); // 18, 19, 20
+ let bxz6_part = bxz2_part.double() + &bxz2_part; // 21, 22
+ let xx3_m_zz3 = xx.double() + &xx - &zz3; // 23, 24, 25
+
+ let dy = y_frag + &(xx3_m_zz3 * &bxz6_part); // 26, 27
+ let yz2 = (y * &z).double(); // 28, 29
+ let dx = x_frag - &(bxz6_part * &yz2); // 30, 31
+ let dz = (yz2 * &yy).double().double(); // 32, 33, 34
+
+ (dx, dy, dz)
+}