summaryrefslogtreecommitdiffstats
path: root/vendor/elliptic-curve/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/elliptic-curve/src
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/elliptic-curve/src')
-rw-r--r--vendor/elliptic-curve/src/arithmetic.rs57
-rw-r--r--vendor/elliptic-curve/src/dev.rs334
-rw-r--r--vendor/elliptic-curve/src/ecdh.rs28
-rw-r--r--vendor/elliptic-curve/src/field.rs51
-rw-r--r--vendor/elliptic-curve/src/hash2curve/group_digest.rs19
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field.rs6
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs74
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs78
-rw-r--r--vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs31
-rw-r--r--vendor/elliptic-curve/src/hash2curve/isogeny.rs5
-rw-r--r--vendor/elliptic-curve/src/hash2curve/osswu.rs127
-rw-r--r--vendor/elliptic-curve/src/jwk.rs68
-rw-r--r--vendor/elliptic-curve/src/lib.rs149
-rw-r--r--vendor/elliptic-curve/src/macros.rs440
-rw-r--r--vendor/elliptic-curve/src/ops.rs89
-rw-r--r--vendor/elliptic-curve/src/point.rs35
-rw-r--r--vendor/elliptic-curve/src/point/non_identity.rs237
-rw-r--r--vendor/elliptic-curve/src/public_key.rs325
-rw-r--r--vendor/elliptic-curve/src/scalar.rs37
-rw-r--r--vendor/elliptic-curve/src/scalar/blinded.rs74
-rw-r--r--vendor/elliptic-curve/src/scalar/nonzero.rs170
-rw-r--r--vendor/elliptic-curve/src/scalar/primitive.rs (renamed from vendor/elliptic-curve/src/scalar/core.rs)210
-rw-r--r--vendor/elliptic-curve/src/sec1.rs24
-rw-r--r--vendor/elliptic-curve/src/secret_key.rs150
-rw-r--r--vendor/elliptic-curve/src/secret_key/pkcs8.rs56
-rw-r--r--vendor/elliptic-curve/src/voprf.rs20
26 files changed, 1582 insertions, 1312 deletions
diff --git a/vendor/elliptic-curve/src/arithmetic.rs b/vendor/elliptic-curve/src/arithmetic.rs
index fa445f1bc..7ef7fc53d 100644
--- a/vendor/elliptic-curve/src/arithmetic.rs
+++ b/vendor/elliptic-curve/src/arithmetic.rs
@@ -1,20 +1,21 @@
//! Elliptic curve arithmetic traits.
use crate::{
- ops::LinearCombination, AffineXCoordinate, Curve, FieldBytes, IsHigh, PrimeCurve, ScalarCore,
+ ops::{Invert, LinearCombination, MulByGenerator, Reduce, ShrAssign},
+ point::AffineCoordinates,
+ scalar::{FromUintUnchecked, IsHigh},
+ Curve, FieldBytes, PrimeCurve, ScalarPrimitive,
};
use core::fmt::Debug;
-use subtle::{ConditionallySelectable, ConstantTimeEq};
+use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption};
use zeroize::DefaultIsZeroes;
-/// Elliptic curve with affine arithmetic implementation.
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub trait AffineArithmetic: Curve + ScalarArithmetic {
+/// Elliptic curve with an arithmetic implementation.
+pub trait CurveArithmetic: Curve {
/// Elliptic curve point in affine coordinates.
type AffinePoint: 'static
- + AffineXCoordinate<Self>
+ + AffineCoordinates<FieldRepr = FieldBytes<Self>>
+ Copy
- + Clone
+ ConditionallySelectable
+ ConstantTimeEq
+ Debug
@@ -25,20 +26,7 @@ pub trait AffineArithmetic: Curve + ScalarArithmetic {
+ Sized
+ Send
+ Sync;
-}
-
-/// Prime order elliptic curve with projective arithmetic implementation.
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub trait PrimeCurveArithmetic:
- PrimeCurve + ProjectiveArithmetic<ProjectivePoint = Self::CurveGroup>
-{
- /// Prime order elliptic curve group.
- type CurveGroup: group::prime::PrimeCurve<Affine = <Self as AffineArithmetic>::AffinePoint>;
-}
-/// Elliptic curve with projective arithmetic implementation.
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub trait ProjectiveArithmetic: Curve + AffineArithmetic {
/// Elliptic curve point in projective coordinates.
///
/// Note: the following bounds are provided by [`group::Group`]:
@@ -57,15 +45,11 @@ pub trait ProjectiveArithmetic: Curve + AffineArithmetic {
+ From<Self::AffinePoint>
+ Into<Self::AffinePoint>
+ LinearCombination
+ + MulByGenerator
+ group::Curve<AffineRepr = Self::AffinePoint>
+ group::Group<Scalar = Self::Scalar>;
-}
-/// Scalar arithmetic.
-#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub trait ScalarArithmetic: Curve {
- /// Scalar field type.
+ /// Scalar field modulo this curve's order.
///
/// Note: the following bounds are provided by [`ff::Field`]:
/// - `'static`
@@ -77,11 +61,26 @@ pub trait ScalarArithmetic: Curve {
/// - [`Default`]
/// - [`Send`]
/// - [`Sync`]
- type Scalar: DefaultIsZeroes
- + From<ScalarCore<Self>>
+ type Scalar: AsRef<Self::Scalar>
+ + DefaultIsZeroes
+ + From<ScalarPrimitive<Self>>
+ + FromUintUnchecked<Uint = Self::Uint>
+ Into<FieldBytes<Self>>
- + Into<Self::UInt>
+ + 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
index be0c156e5..36c684ad4 100644
--- a/vendor/elliptic-curve/src/dev.rs
+++ b/vendor/elliptic-curve/src/dev.rs
@@ -6,26 +6,27 @@
use crate::{
bigint::{Limb, U256},
error::{Error, Result},
- ops::{LinearCombination, Reduce},
+ generic_array::typenum::U32,
+ ops::{Invert, LinearCombination, MulByGenerator, Reduce, ShrAssign},
pkcs8,
+ point::AffineCoordinates,
rand_core::RngCore,
- sec1::{FromEncodedPoint, ToEncodedPoint},
+ scalar::{FromUintUnchecked, IsHigh},
+ sec1::{CompressedPoint, FromEncodedPoint, ToEncodedPoint},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
zeroize::DefaultIsZeroes,
- AffineArithmetic, AffineXCoordinate, Curve, IsHigh, PrimeCurve, ProjectiveArithmetic,
- ScalarArithmetic,
+ Curve, CurveArithmetic, FieldBytesEncoding, PrimeCurve,
};
use core::{
- iter::Sum,
+ iter::{Product, Sum},
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use ff::{Field, PrimeField};
-use generic_array::arr;
use hex_literal::hex;
use pkcs8::AssociatedOid;
#[cfg(feature = "bits")]
-use crate::group::ff::PrimeFieldBits;
+use ff::PrimeFieldBits;
#[cfg(feature = "jwk")]
use crate::JwkParameters;
@@ -49,13 +50,13 @@ pub type PublicKey = crate::PublicKey<MockCurve>;
/// Secret key.
pub type SecretKey = crate::SecretKey<MockCurve>;
-/// Scalar core.
-// TODO(tarcieri): make this the scalar type
-pub type ScalarCore = crate::ScalarCore<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::ScalarBits<MockCurve>;
+pub type ScalarBits = crate::scalar::ScalarBits<MockCurve>;
/// Mock elliptic curve type useful for writing tests which require a concrete
/// curve type.
@@ -66,7 +67,8 @@ pub type ScalarBits = crate::ScalarBits<MockCurve>;
pub struct MockCurve;
impl Curve for MockCurve {
- type UInt = U256;
+ type FieldBytesSize = U32;
+ type Uint = U256;
const ORDER: U256 =
U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
@@ -74,15 +76,9 @@ impl Curve for MockCurve {
impl PrimeCurve for MockCurve {}
-impl AffineArithmetic for MockCurve {
+impl CurveArithmetic for MockCurve {
type AffinePoint = AffinePoint;
-}
-
-impl ProjectiveArithmetic for MockCurve {
type ProjectivePoint = ProjectivePoint;
-}
-
-impl ScalarArithmetic for MockCurve {
type Scalar = Scalar;
}
@@ -92,16 +88,18 @@ impl AssociatedOid for MockCurve {
}
#[cfg(feature = "jwk")]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl JwkParameters for MockCurve {
const CRV: &'static str = "P-256";
}
/// Example scalar type
-#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
-pub struct Scalar(ScalarCore);
+#[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();
@@ -113,14 +111,6 @@ impl Field for Scalar {
}
}
- fn zero() -> Self {
- Self(ScalarCore::ZERO)
- }
-
- fn one() -> Self {
- Self(ScalarCore::ONE)
- }
-
fn is_zero(&self) -> Choice {
self.0.is_zero()
}
@@ -142,39 +132,37 @@ impl Field for Scalar {
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> {
- ScalarCore::from_be_bytes(bytes).map(Self)
+ ScalarPrimitive::from_bytes(&bytes).map(Self)
}
fn to_repr(&self) -> FieldBytes {
- self.0.to_be_bytes()
+ self.0.to_bytes()
}
fn is_odd(&self) -> Choice {
self.0.is_odd()
}
-
- fn multiplicative_generator() -> Self {
- 7u64.into()
- }
-
- fn root_of_unity() -> Self {
- Self::from_repr(arr![u8;
- 0xff, 0xc9, 0x7f, 0x06, 0x2a, 0x77, 0x09, 0x92, 0xba, 0x80, 0x7a, 0xce, 0x84, 0x2a,
- 0x3d, 0xfc, 0x15, 0x46, 0xca, 0xd0, 0x04, 0x37, 0x8d, 0xaf, 0x05, 0x92, 0xd7, 0xfb,
- 0xb4, 0x1e, 0x66, 0x02,
- ])
- .unwrap()
- }
}
#[cfg(feature = "bits")]
@@ -194,23 +182,15 @@ impl PrimeFieldBits for Scalar {
}
}
-impl TryFrom<U256> for Scalar {
- type Error = Error;
-
- fn try_from(w: U256) -> Result<Self> {
- Option::from(ScalarCore::new(w)).map(Self).ok_or(Error)
- }
-}
-
-impl From<Scalar> for U256 {
- fn from(scalar: Scalar) -> U256 {
- *scalar.0.as_uint()
+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(ScalarCore::conditional_select(&a.0, &b.0, choice))
+ Self(ScalarPrimitive::conditional_select(&a.0, &b.0, choice))
}
}
@@ -314,27 +294,102 @@ impl Neg for Scalar {
}
}
+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 {
- fn from_uint_reduced(w: U256) -> Self {
+ 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::BIT_SIZE - 1)) as u8);
+ let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
let reduced = U256::conditional_select(&w, &r, !underflow);
- Self(ScalarCore::new(reduced).unwrap())
+ 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<ScalarCore> for Scalar {
- fn from(scalar: ScalarCore) -> Scalar {
+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)
@@ -369,15 +424,28 @@ pub enum AffinePoint {
Other(EncodedPoint),
}
-impl AffineXCoordinate<MockCurve> for AffinePoint {
+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 {
- unimplemented!();
+ 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(),
+ }
}
}
@@ -457,14 +525,25 @@ pub enum ProjectivePoint {
}
impl ConstantTimeEq for ProjectivePoint {
- fn ct_eq(&self, _other: &Self) -> Choice {
- unimplemented!();
+ 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 {
- unimplemented!();
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ if choice.into() {
+ *b
+ } else {
+ *a
+ }
}
}
@@ -521,7 +600,7 @@ impl group::Group for ProjectivePoint {
}
fn is_identity(&self) -> Choice {
- Choice::from((self == &Self::Identity) as u8)
+ Choice::from(u8::from(self == &Self::Identity))
}
#[must_use]
@@ -530,6 +609,47 @@ impl group::Group for ProjectivePoint {
}
}
+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;
@@ -699,6 +819,8 @@ impl MulAssign<&Scalar> for ProjectivePoint {
}
}
+impl MulByGenerator for ProjectivePoint {}
+
impl Neg for ProjectivePoint {
type Output = ProjectivePoint;
@@ -707,78 +829,6 @@ impl Neg for ProjectivePoint {
}
}
-/// Constant representing the base field modulus
-/// p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1
-pub const MODULUS: U256 =
- U256::from_be_hex("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff");
-
-/// Example base field element.
-#[derive(Clone, Copy, Debug)]
-pub struct FieldElement(pub(crate) U256);
-
-/// Internal field element representation.
-#[cfg(target_pointer_width = "32")]
-type FeWords = [u32; 8];
-
-/// Internal field element representation.
-#[cfg(target_pointer_width = "64")]
-type FeWords = [u64; 4];
-
-impl_field_element!(
- FieldElement,
- FieldBytes,
- U256,
- MODULUS,
- FeWords,
- p256_from_montgomery,
- p256_to_montgomery,
- p256_add,
- p256_sub,
- p256_mul,
- p256_opp,
- p256_square
-);
-
-impl FieldElement {
- /// Returns the multiplicative inverse of self, if self is non-zero.
- pub fn invert(&self) -> CtOption<Self> {
- unimplemented!()
- }
-
- /// Returns the square root of self mod p, or `None` if no square root exists.
- pub fn sqrt(&self) -> CtOption<Self> {
- unimplemented!()
- }
-}
-
-const fn p256_from_montgomery(_: &FeWords) -> FeWords {
- unimplemented!()
-}
-
-const fn p256_to_montgomery(w: &FeWords) -> FeWords {
- *w
-}
-
-const fn p256_add(_: &FeWords, _: &FeWords) -> FeWords {
- unimplemented!()
-}
-
-const fn p256_sub(_: &FeWords, _: &FeWords) -> FeWords {
- unimplemented!()
-}
-
-const fn p256_mul(_: &FeWords, _: &FeWords) -> FeWords {
- unimplemented!()
-}
-
-const fn p256_opp(_: &FeWords) -> FeWords {
- unimplemented!()
-}
-
-const fn p256_square(_: &FeWords) -> FeWords {
- unimplemented!()
-}
-
#[cfg(test)]
mod tests {
use super::Scalar;
diff --git a/vendor/elliptic-curve/src/ecdh.rs b/vendor/elliptic-curve/src/ecdh.rs
index 1e9f7bc31..c64a696aa 100644
--- a/vendor/elliptic-curve/src/ecdh.rs
+++ b/vendor/elliptic-curve/src/ecdh.rs
@@ -1,7 +1,7 @@
//! Elliptic Curve Diffie-Hellman Support.
//!
//! This module contains a generic ECDH implementation which is usable with
-//! any elliptic curve which implements the [`ProjectiveArithmetic`] trait (presently
+//! any elliptic curve which implements the [`CurveArithmetic`] trait (presently
//! the `k256` and `p256` crates)
//!
//! # ECDH Ephemeral (ECDHE) Usage
@@ -27,14 +27,14 @@
//! [SIGMA]: https://webee.technion.ac.il/~hugo/sigma-pdf.pdf
use crate::{
- AffineArithmetic, AffinePoint, AffineXCoordinate, Curve, FieldBytes, NonZeroScalar,
- ProjectiveArithmetic, ProjectivePoint, PublicKey,
+ 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::{CryptoRng, RngCore};
+use rand_core::CryptoRngCore;
use zeroize::{Zeroize, ZeroizeOnDrop};
/// Low-level Elliptic Curve Diffie-Hellman (ECDH) function.
@@ -62,7 +62,7 @@ pub fn diffie_hellman<C>(
public_key: impl Borrow<AffinePoint<C>>,
) -> SharedSecret<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
let public_point = ProjectivePoint::<C>::from(*public_key.borrow());
let secret_point = (public_point * secret_key.borrow().as_ref()).to_affine();
@@ -92,17 +92,17 @@ where
/// takes further steps to authenticate the peers in a key exchange.
pub struct EphemeralSecret<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
scalar: NonZeroScalar<C>,
}
impl<C> EphemeralSecret<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
/// Generate a cryptographically random [`EphemeralSecret`].
- pub fn random(rng: impl CryptoRng + RngCore) -> Self {
+ pub fn random(rng: &mut impl CryptoRngCore) -> Self {
Self {
scalar: NonZeroScalar::random(rng),
}
@@ -118,13 +118,13 @@ where
/// 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())
+ diffie_hellman(self.scalar, public_key.as_affine())
}
}
impl<C> From<&EphemeralSecret<C>> for PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
fn from(ephemeral_secret: &EphemeralSecret<C>) -> Self {
ephemeral_secret.public_key()
@@ -133,18 +133,18 @@ where
impl<C> Zeroize for EphemeralSecret<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
fn zeroize(&mut self) {
self.scalar.zeroize()
}
}
-impl<C> ZeroizeOnDrop for EphemeralSecret<C> where C: Curve + ProjectiveArithmetic {}
+impl<C> ZeroizeOnDrop for EphemeralSecret<C> where C: CurveArithmetic {}
impl<C> Drop for EphemeralSecret<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
fn drop(&mut self) {
self.zeroize();
@@ -162,7 +162,7 @@ impl<C: Curve> SharedSecret<C> {
#[inline]
fn new(point: AffinePoint<C>) -> Self
where
- C: AffineArithmetic,
+ C: CurveArithmetic,
{
Self {
secret_bytes: point.x(),
diff --git a/vendor/elliptic-curve/src/field.rs b/vendor/elliptic-curve/src/field.rs
new file mode 100644
index 000000000..66055abc2
--- /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/group_digest.rs b/vendor/elliptic-curve/src/hash2curve/group_digest.rs
index dbcb1512b..ea7f0471f 100644
--- a/vendor/elliptic-curve/src/hash2curve/group_digest.rs
+++ b/vendor/elliptic-curve/src/hash2curve/group_digest.rs
@@ -1,11 +1,11 @@
//! Traits for handling hash to curve.
use super::{hash_to_field, ExpandMsg, FromOkm, MapToCurve};
-use crate::{ProjectiveArithmetic, ProjectivePoint, Result};
+use crate::{CurveArithmetic, ProjectivePoint, Result};
use group::cofactor::CofactorGroup;
/// Adds hashing arbitrary byte sequences to a valid group element
-pub trait GroupDigest: ProjectiveArithmetic
+pub trait GroupDigest: CurveArithmetic
where
ProjectivePoint<Self>: CofactorGroup,
{
@@ -48,10 +48,10 @@ where
/// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof
fn hash_from_bytes<'a, X: ExpandMsg<'a>>(
msgs: &[&[u8]],
- dst: &'a [u8],
+ dsts: &'a [&'a [u8]],
) -> Result<ProjectivePoint<Self>> {
let mut u = [Self::FieldElement::default(), Self::FieldElement::default()];
- hash_to_field::<X, _>(msgs, dst, &mut u)?;
+ 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
@@ -88,10 +88,10 @@ where
/// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof
fn encode_from_bytes<'a, X: ExpandMsg<'a>>(
msgs: &[&[u8]],
- dst: &'a [u8],
+ dsts: &'a [&'a [u8]],
) -> Result<ProjectivePoint<Self>> {
let mut u = [Self::FieldElement::default()];
- hash_to_field::<X, _>(msgs, dst, &mut u)?;
+ hash_to_field::<X, _>(msgs, dsts, &mut u)?;
let q0 = u[0].map_to_curve();
Ok(q0.clear_cofactor().into())
}
@@ -109,12 +109,15 @@ where
///
/// [`ExpandMsgXmd`]: crate::hash2curve::ExpandMsgXmd
/// [`ExpandMsgXof`]: crate::hash2curve::ExpandMsgXof
- fn hash_to_scalar<'a, X: ExpandMsg<'a>>(msgs: &[&[u8]], dst: &'a [u8]) -> Result<Self::Scalar>
+ 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, dst, &mut u)?;
+ 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
index 6cd0723aa..67ede111c 100644
--- a/vendor/elliptic-curve/src/hash2curve/hash2field.rs
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field.rs
@@ -6,7 +6,7 @@ mod expand_msg;
pub use expand_msg::{xmd::*, xof::*, *};
-use crate::Result;
+use crate::{Error, Result};
use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
/// The trait for helping to convert to a field element.
@@ -32,12 +32,12 @@ pub trait FromOkm {
/// [`ExpandMsgXmd`]: crate::hash2field::ExpandMsgXmd
/// [`ExpandMsgXof`]: crate::hash2field::ExpandMsgXof
#[doc(hidden)]
-pub fn hash_to_field<'a, E, T>(data: &[&[u8]], domain: &'a [u8], out: &mut [T]) -> Result<()>
+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() * out.len();
+ 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() {
diff --git a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs
index dfb3bab9c..96a659b9a 100644
--- a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg.rs
@@ -25,8 +25,11 @@ pub trait ExpandMsg<'a> {
///
/// Returns an expander that can be used to call `read` until enough
/// bytes have been consumed
- fn expand_message(msgs: &[&[u8]], dst: &'a [u8], len_in_bytes: usize)
- -> Result<Self::Expander>;
+ 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.
@@ -47,54 +50,66 @@ where
/// > 255
Hashed(GenericArray<u8, L>),
/// <= 255
- Array(&'a [u8]),
+ Array(&'a [&'a [u8]]),
}
impl<'a, L> Domain<'a, L>
where
L: ArrayLength<u8> + IsLess<U256>,
{
- pub fn xof<X>(dst: &'a [u8]) -> Result<Self>
+ pub fn xof<X>(dsts: &'a [&'a [u8]]) -> Result<Self>
where
X: Default + ExtendableOutput + Update,
{
- if dst.is_empty() {
+ if dsts.is_empty() {
Err(Error)
- } else if dst.len() > MAX_DST_LEN {
+ } else if dsts.iter().map(|dst| dst.len()).sum::<usize>() > MAX_DST_LEN {
let mut data = GenericArray::<u8, L>::default();
- X::default()
- .chain(OVERSIZE_DST_SALT)
- .chain(dst)
- .finalize_xof()
- .read(&mut data);
+ 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(dst))
+ Ok(Self::Array(dsts))
}
}
- pub fn xmd<X>(dst: &'a [u8]) -> Result<Self>
+ pub fn xmd<X>(dsts: &'a [&'a [u8]]) -> Result<Self>
where
X: Digest<OutputSize = L>,
{
- if dst.is_empty() {
+ if dsts.is_empty() {
Err(Error)
- } else if dst.len() > MAX_DST_LEN {
+ } 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);
- hash.update(dst);
+
+ for dst in dsts {
+ hash.update(dst);
+ }
+
hash.finalize()
}))
} else {
- Ok(Self::Array(dst))
+ Ok(Self::Array(dsts))
}
}
- pub fn data(&self) -> &[u8] {
+ pub fn update_hash<HashT: Update>(&self, hash: &mut HashT) {
match self {
- Self::Hashed(d) => &d[..],
- Self::Array(d) => *d,
+ Self::Hashed(d) => hash.update(d),
+ Self::Array(d) => {
+ for d in d.iter() {
+ hash.update(d)
+ }
+ }
}
}
@@ -103,13 +118,28 @@ where
// 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.len()).expect("length overflow"),
+ 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]) {
- assert_eq!(self.data(), &bytes[..bytes.len() - 1]);
+ 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
index 876b012f5..50edb648b 100644
--- a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xmd.rs
@@ -1,5 +1,8 @@
//! `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};
@@ -10,7 +13,7 @@ use digest::{
typenum::{IsLess, IsLessOrEqual, Unsigned, U256},
GenericArray,
},
- Digest,
+ FixedOutput, HashMarker,
};
/// Placeholder type for implementing `expand_message_xmd` based on a hash function
@@ -22,14 +25,14 @@ use digest::{
/// - `len_in_bytes > 255 * HashT::OutputSize`
pub struct ExpandMsgXmd<HashT>(PhantomData<HashT>)
where
- HashT: Digest + BlockSizeUser,
+ 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: Digest + BlockSizeUser,
+ 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
@@ -42,7 +45,7 @@ where
fn expand_message(
msgs: &[&[u8]],
- dst: &'a [u8],
+ dsts: &'a [&'a [u8]],
len_in_bytes: usize,
) -> Result<Self::Expander> {
if len_in_bytes == 0 {
@@ -54,26 +57,26 @@ where
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>(dst)?;
- let mut b_0 = HashT::new();
- b_0.update(GenericArray::<u8, HashT::BlockSize>::default());
+ 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]);
- b_0.update(domain.data());
- b_0.update([domain.len()]);
- let b_0 = b_0.finalize();
+ 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::new();
+ let mut b_vals = HashT::default();
b_vals.update(&b_0[..]);
- b_vals.update([1u8]);
- b_vals.update(domain.data());
- b_vals.update([domain.len()]);
- let b_vals = b_vals.finalize();
+ 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,
@@ -89,7 +92,7 @@ where
/// [`Expander`] type for [`ExpandMsgXmd`].
pub struct ExpanderXmd<'a, HashT>
where
- HashT: Digest + BlockSizeUser,
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
HashT::OutputSize: IsLess<U256>,
HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
{
@@ -103,7 +106,7 @@ where
impl<'a, HashT> ExpanderXmd<'a, HashT>
where
- HashT: Digest + BlockSizeUser,
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
HashT::OutputSize: IsLess<U256>,
HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
{
@@ -118,12 +121,12 @@ where
.zip(&self.b_vals[..])
.enumerate()
.for_each(|(j, (b0val, bi1val))| tmp[j] = b0val ^ bi1val);
- let mut b_vals = HashT::new();
- b_vals.update(tmp);
- b_vals.update([self.index]);
- b_vals.update(self.domain.data());
- b_vals.update([self.domain.len()]);
- self.b_vals = b_vals.finalize();
+ 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
@@ -133,7 +136,7 @@ where
impl<'a, HashT> Expander for ExpanderXmd<'a, HashT>
where
- HashT: Digest + BlockSizeUser,
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
HashT::OutputSize: IsLess<U256>,
HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
{
@@ -165,7 +168,7 @@ mod test {
len_in_bytes: u16,
bytes: &[u8],
) where
- HashT: Digest + BlockSizeUser,
+ HashT: BlockSizeUser + Default + FixedOutput + HashMarker,
HashT::OutputSize: IsLess<U256>,
{
let block = HashT::BlockSize::to_usize();
@@ -183,8 +186,8 @@ mod test {
let pad = l + mem::size_of::<u8>();
assert_eq!([0], &bytes[l..pad]);
- let dst = pad + domain.data().len();
- assert_eq!(domain.data(), &bytes[pad..dst]);
+ 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]);
@@ -205,13 +208,14 @@ mod test {
domain: &Domain<'_, HashT::OutputSize>,
) -> Result<()>
where
- HashT: Digest + BlockSizeUser,
+ 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())?;
+ ExpandMsgXmd::<HashT>::expand_message(&[self.msg], &dst, L::to_usize())?;
let mut uniform_bytes = GenericArray::<u8, L>::default();
expander.fill_bytes(&mut uniform_bytes);
@@ -227,8 +231,8 @@ mod test {
const DST_PRIME: &[u8] =
&hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826");
- let dst_prime = Domain::xmd::<Sha256>(DST)?;
- dst_prime.assert(DST_PRIME);
+ let dst_prime = Domain::xmd::<Sha256>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
const TEST_VECTORS_32: &[TestVector] = &[
TestVector {
@@ -299,8 +303,8 @@ mod test {
const DST_PRIME: &[u8] =
&hex!("412717974da474d0f8c420f320ff81e8432adb7c927d9bd082b4fb4d16c0a23620");
- let dst_prime = Domain::xmd::<Sha256>(DST)?;
- dst_prime.assert(DST_PRIME);
+ let dst_prime = Domain::xmd::<Sha256>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
const TEST_VECTORS_32: &[TestVector] = &[
TestVector {
@@ -377,8 +381,8 @@ mod test {
const DST_PRIME: &[u8] =
&hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348413531322d32353626");
- let dst_prime = Domain::xmd::<Sha512>(DST)?;
- dst_prime.assert(DST_PRIME);
+ let dst_prime = Domain::xmd::<Sha512>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
const TEST_VECTORS_32: &[TestVector] = &[
TestVector {
diff --git a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs
index 107ac5e06..9a5ff19e9 100644
--- a/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs
+++ b/vendor/elliptic-curve/src/hash2curve/hash2field/expand_msg/xof.rs
@@ -27,7 +27,7 @@ where
fn expand_message(
msgs: &[&[u8]],
- dst: &'a [u8],
+ dsts: &'a [&'a [u8]],
len_in_bytes: usize,
) -> Result<Self::Expander> {
if len_in_bytes == 0 {
@@ -36,18 +36,17 @@ where
let len_in_bytes = u16::try_from(len_in_bytes).map_err(|_| Error)?;
- let domain = Domain::<U32>::xof::<HashT>(dst)?;
+ let domain = Domain::<U32>::xof::<HashT>(dsts)?;
let mut reader = HashT::default();
for msg in msgs {
reader = reader.chain(msg);
}
- let reader = reader
- .chain(len_in_bytes.to_be_bytes())
- .chain(domain.data())
- .chain([domain.len()])
- .finalize_xof();
+ 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 })
}
}
@@ -87,8 +86,8 @@ mod test {
&bytes[msg_len..len_in_bytes_len]
);
- let dst = len_in_bytes_len + domain.data().len();
- assert_eq!(domain.data(), &bytes[len_in_bytes_len..dst]);
+ 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]);
@@ -111,7 +110,7 @@ mod test {
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())?;
+ ExpandMsgXof::<HashT>::expand_message(&[self.msg], &[dst], L::to_usize())?;
let mut uniform_bytes = GenericArray::<u8, L>::default();
expander.fill_bytes(&mut uniform_bytes);
@@ -127,8 +126,8 @@ mod test {
const DST_PRIME: &[u8] =
&hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348414b4531323824");
- let dst_prime = Domain::<U32>::xof::<Shake128>(DST)?;
- dst_prime.assert(DST_PRIME);
+ let dst_prime = Domain::<U32>::xof::<Shake128>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
const TEST_VECTORS_32: &[TestVector] = &[
TestVector {
@@ -203,8 +202,8 @@ mod test {
const DST_PRIME: &[u8] =
&hex!("acb9736c0867fdfbd6385519b90fc8c034b5af04a958973212950132d035792f20");
- let dst_prime = Domain::<U32>::xof::<Shake128>(DST)?;
- dst_prime.assert(DST_PRIME);
+ let dst_prime = Domain::<U32>::xof::<Shake128>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
const TEST_VECTORS_32: &[TestVector] = &[
TestVector {
@@ -281,8 +280,8 @@ mod test {
const DST_PRIME: &[u8] =
&hex!("515555582d5630312d435330322d776974682d657870616e6465722d5348414b4532353624");
- let dst_prime = Domain::<U32>::xof::<Shake256>(DST)?;
- dst_prime.assert(DST_PRIME);
+ let dst_prime = Domain::<U32>::xof::<Shake256>(&[DST])?;
+ dst_prime.assert_dst(DST_PRIME);
const TEST_VECTORS_32: &[TestVector] = &[
TestVector {
diff --git a/vendor/elliptic-curve/src/hash2curve/isogeny.rs b/vendor/elliptic-curve/src/hash2curve/isogeny.rs
index fc197246a..7a28983dd 100644
--- a/vendor/elliptic-curve/src/hash2curve/isogeny.rs
+++ b/vendor/elliptic-curve/src/hash2curve/isogeny.rs
@@ -26,9 +26,10 @@ pub trait Isogeny: Field + AddAssign + Mul<Output = Self> {
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[0] = Self::ONE;
xs[1] = x;
xs[2] = x.square();
for i in 3..Self::Degree::to_usize() {
@@ -48,7 +49,7 @@ pub trait Isogeny: Field + AddAssign + Mul<Output = Self> {
/// Compute the ISO transform
fn compute_iso(xxs: &[Self], k: &[Self]) -> Self {
- let mut xx = Self::zero();
+ let mut xx = Self::ZERO;
for (xi, ki) in xxs.iter().zip(k.iter()) {
xx += *xi * ki;
}
diff --git a/vendor/elliptic-curve/src/hash2curve/osswu.rs b/vendor/elliptic-curve/src/hash2curve/osswu.rs
index f803863b1..3c3669ac3 100644
--- a/vendor/elliptic-curve/src/hash2curve/osswu.rs
+++ b/vendor/elliptic-curve/src/hash2curve/osswu.rs
@@ -1,9 +1,11 @@
//! Optimized simplified Shallue-van de Woestijne-Ulas methods.
//!
-//! <https://eprint.iacr.org/2009/340.pdf>
+//! <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>
@@ -11,7 +13,7 @@ where
F: Field,
{
/// The first constant term
- pub c1: [u64; 4],
+ pub c1: &'static [u64],
/// The second constant term
pub c2: F,
/// The ISO A variable or Curve A variable
@@ -38,50 +40,91 @@ pub trait OsswuMap: Field + Sgn0 {
/// 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) {
- let tv1 = self.square(); // u^2
- let tv3 = Self::PARAMS.z * tv1; // Z * u^2
- let mut tv2 = tv3.square(); // tv3^2
- let mut xd = tv2 + tv3; // tv3^2 + tv3
- let x1n = Self::PARAMS.map_b * (xd + Self::one()); // B * (xd + 1)
- xd *= -Self::PARAMS.map_a; // -A * xd
-
- let tv = Self::PARAMS.z * Self::PARAMS.map_a;
- xd.conditional_assign(&tv, xd.is_zero());
-
- tv2 = xd.square(); //xd^2
- let gxd = tv2 * xd; // xd^3
- tv2 *= Self::PARAMS.map_a; // A * tv2
-
- let mut gx1 = x1n * (tv2 + x1n.square()); //x1n *(tv2 + x1n^2)
- tv2 = gxd * Self::PARAMS.map_b; // B * gxd
- gx1 += tv2; // gx1 + tv2
-
- let mut tv4 = gxd.square(); // gxd^2
- tv2 = gx1 * gxd; // gx1 * gxd
- tv4 *= tv2;
-
- let y1 = tv4.pow_vartime(&Self::PARAMS.c1) * tv2; // tv4^C1 * tv2
- let x2n = tv3 * x1n; // tv3 * x1n
-
- let y2 = y1 * Self::PARAMS.c2 * tv1 * self; // y1 * c2 * tv1 * u
-
- tv2 = y1.square() * gxd; //y1^2 * gxd
-
- let e2 = tv2.ct_eq(&gx1);
-
- // if e2 , x = x1, else x = x2
- let mut x = Self::conditional_select(&x2n, &x1n, e2);
- // xn / xd
- x *= xd.invert().unwrap();
-
- // if e2, y = y1, else y = y2
- let mut y = Self::conditional_select(&y2, &y1, e2);
-
- y.conditional_assign(&-y, self.sgn0() ^ y.sgn0());
+ // 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
index ff5e6e638..e0233cc00 100644
--- a/vendor/elliptic-curve/src/jwk.rs
+++ b/vendor/elliptic-curve/src/jwk.rs
@@ -6,7 +6,7 @@
use crate::{
sec1::{Coordinates, EncodedPoint, ModulusSize, ValidatePublicKey},
secret_key::SecretKey,
- Curve, Error, FieldBytes, FieldSize, Result,
+ Curve, Error, FieldBytes, FieldBytesSize, Result,
};
use alloc::{
borrow::ToOwned,
@@ -26,7 +26,7 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::{
public_key::PublicKey,
sec1::{FromEncodedPoint, ToEncodedPoint},
- AffinePoint, ProjectiveArithmetic,
+ AffinePoint, CurveArithmetic,
};
/// Key Type (`kty`) for elliptic curve keys.
@@ -42,7 +42,6 @@ const JWK_TYPE_NAME: &str = "JwkEcKey";
const FIELDS: &[&str] = &["kty", "crv", "x", "y", "d"];
/// Elliptic curve parameters used by JSON Web Keys.
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub trait JwkParameters: Curve {
/// The `crv` parameter which identifies a particular elliptic curve
/// as defined in RFC 7518 Section 6.2.1.1:
@@ -64,7 +63,6 @@ pub trait JwkParameters: Curve {
/// [1]: https://tools.ietf.org/html/rfc7518#section-6
// TODO(tarcieri): eagerly decode or validate `x`, `y`, and `d` as Base64
#[derive(Clone)]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub struct JwkEcKey {
/// The `crv` parameter which identifies a particular elliptic curve
/// as defined in RFC 7518 Section 6.2.1.1:
@@ -110,12 +108,11 @@ impl JwkEcKey {
/// Decode a JWK into a [`PublicKey`].
#[cfg(feature = "arithmetic")]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub fn to_public_key<C>(&self) -> Result<PublicKey<C>>
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
PublicKey::from_sec1_bytes(self.to_encoded_point::<C>()?.as_bytes())
}
@@ -124,7 +121,7 @@ impl JwkEcKey {
pub fn from_encoded_point<C>(point: &EncodedPoint<C>) -> Option<Self>
where
C: Curve + JwkParameters,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
match point.coordinates() {
Coordinates::Uncompressed { x, y } => Some(JwkEcKey {
@@ -141,7 +138,7 @@ impl JwkEcKey {
pub fn to_encoded_point<C>(&self) -> Result<EncodedPoint<C>>
where
C: Curve + JwkParameters,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
if self.crv != C::CRV {
return Err(Error);
@@ -154,11 +151,10 @@ impl JwkEcKey {
/// Decode a JWK into a [`SecretKey`].
#[cfg(feature = "arithmetic")]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub fn to_secret_key<C>(&self) -> Result<SecretKey<C>>
where
C: Curve + JwkParameters + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
self.try_into()
}
@@ -178,11 +174,10 @@ impl ToString for JwkEcKey {
}
}
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<JwkEcKey> for SecretKey<C>
where
C: Curve + JwkParameters + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Error = Error;
@@ -191,11 +186,10 @@ where
}
}
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<&JwkEcKey> for SecretKey<C>
where
C: Curve + JwkParameters + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Error = Error;
@@ -203,7 +197,7 @@ where
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_be_bytes(&d_bytes);
+ let result = SecretKey::from_slice(&d_bytes);
d_bytes.zeroize();
result.and_then(|secret_key| {
@@ -217,13 +211,11 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<SecretKey<C>> for JwkEcKey
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn from(sk: SecretKey<C>) -> JwkEcKey {
(&sk).into()
@@ -231,17 +223,15 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<&SecretKey<C>> for JwkEcKey
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn from(sk: &SecretKey<C>) -> JwkEcKey {
let mut jwk = sk.public_key().to_jwk();
- let mut d = sk.to_be_bytes();
+ let mut d = sk.to_bytes();
jwk.d = Some(Base64Url::encode_string(&d));
d.zeroize();
jwk
@@ -249,13 +239,11 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<JwkEcKey> for PublicKey<C>
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Error = Error;
@@ -265,13 +253,11 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<&JwkEcKey> for PublicKey<C>
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Error = Error;
@@ -281,13 +267,11 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<PublicKey<C>> for JwkEcKey
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn from(pk: PublicKey<C>) -> JwkEcKey {
(&pk).into()
@@ -295,13 +279,11 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<&PublicKey<C>> for JwkEcKey
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn from(pk: &PublicKey<C>) -> JwkEcKey {
Self::from_encoded_point::<C>(&pk.to_encoded_point(false)).expect("JWK encoding error")
@@ -458,7 +440,7 @@ impl<'de> Deserialize<'de> for JwkEcKey {
.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)));
+ return Err(de::Error::custom(format!("unsupported JWK kty: {kty:?}")));
}
let crv = de::SeqAccess::next_element::<String>(&mut seq)?
@@ -530,7 +512,7 @@ impl<'de> Deserialize<'de> for JwkEcKey {
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)));
+ return Err(de::Error::custom(format!("unsupported JWK kty: {kty}")));
}
let crv = crv.ok_or_else(|| de::Error::missing_field("crv"))?;
diff --git a/vendor/elliptic-curve/src/lib.rs b/vendor/elliptic-curve/src/lib.rs
index 62ac7856b..5f2a6c62e 100644
--- a/vendor/elliptic-curve/src/lib.rs
+++ b/vendor/elliptic-curve/src/lib.rs
@@ -1,12 +1,29 @@
#![no_std]
-#![cfg_attr(docsrs, feature(doc_cfg))]
+#![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, clippy::unwrap_used)]
-#![warn(missing_docs, rust_2018_idioms, unused_qualifications)]
+#![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
//!
@@ -20,8 +37,10 @@
//! - [`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
@@ -42,7 +61,7 @@
//!
//! - [`JwkEcKey`]
//! - [`PublicKey`]
-//! - [`ScalarCore`]
+//! - [`ScalarPrimitive`]
//!
//! Please see type-specific documentation for more information.
//!
@@ -50,50 +69,37 @@
//! [`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;
-#[cfg(feature = "rand_core")]
-#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
-pub use rand_core;
-
-#[macro_use]
-mod macros;
-
-pub mod ops;
+pub mod point;
+pub mod scalar;
#[cfg(feature = "dev")]
-#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
pub mod dev;
-
#[cfg(feature = "ecdh")]
-#[cfg_attr(docsrs, doc(cfg(feature = "ecdh")))]
pub mod ecdh;
-
#[cfg(feature = "hash2curve")]
-#[cfg_attr(docsrs, doc(cfg(feature = "hash2curve")))]
pub mod hash2curve;
-
+#[cfg(feature = "arithmetic")]
+pub mod ops;
#[cfg(feature = "sec1")]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
pub mod sec1;
-
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub mod weierstrass;
mod error;
-mod point;
-mod scalar;
+mod field;
mod secret_key;
#[cfg(feature = "arithmetic")]
@@ -104,12 +110,13 @@ mod public_key;
#[cfg(feature = "jwk")]
mod jwk;
+#[cfg(feature = "voprf")]
+mod voprf;
+
pub use crate::{
error::{Error, Result},
- point::{
- AffineXCoordinate, DecompactPoint, DecompressPoint, PointCompaction, PointCompression,
- },
- scalar::{core::ScalarCore, IsHigh},
+ field::{FieldBytes, FieldBytesEncoding, FieldBytesSize},
+ scalar::ScalarPrimitive,
secret_key::SecretKey,
};
pub use crypto_bigint as bigint;
@@ -121,34 +128,35 @@ pub use zeroize;
#[cfg(feature = "arithmetic")]
pub use {
crate::{
- arithmetic::{
- AffineArithmetic, PrimeCurveArithmetic, ProjectiveArithmetic, ScalarArithmetic,
- },
+ arithmetic::{CurveArithmetic, PrimeCurveArithmetic},
+ point::{AffinePoint, ProjectivePoint},
public_key::PublicKey,
- scalar::{nonzero::NonZeroScalar, Scalar},
+ scalar::{NonZeroScalar, Scalar},
},
ff::{self, Field, PrimeField},
group::{self, Group},
};
-#[cfg(feature = "bits")]
-pub use crate::scalar::ScalarBits;
-
#[cfg(feature = "jwk")]
pub use crate::jwk::{JwkEcKey, JwkParameters};
#[cfg(feature = "pkcs8")]
pub use pkcs8;
-use core::fmt::Debug;
-use generic_array::GenericArray;
+#[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")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
pub const ALGORITHM_OID: pkcs8::ObjectIdentifier =
pkcs8::ObjectIdentifier::new_unwrap("1.2.840.10045.2.1");
@@ -161,60 +169,29 @@ pub const ALGORITHM_OID: pkcs8::ObjectIdentifier =
/// 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.
- // TODO(tarcieri): replace this with an e.g. `const Curve::MODULUS: UInt`.
- // Requires rust-lang/rust#60551, i.e. `const_evaluatable_checked`
- type UInt: bigint::AddMod<Output = Self::UInt>
- + bigint::ArrayEncoding
+ type Uint: bigint::ArrayEncoding
+ + bigint::AddMod<Output = Self::Uint>
+ bigint::Encoding
+ bigint::Integer
- + bigint::NegMod<Output = Self::UInt>
+ + bigint::NegMod<Output = Self::Uint>
+ bigint::Random
+ bigint::RandomMod
- + bigint::SubMod<Output = Self::UInt>
- + zeroize::Zeroize;
-
- /// Order constant.
- ///
- /// Subdivided into either 32-bit or 64-bit "limbs" (depending on the
- /// target CPU's word size), specified from least to most significant.
- const ORDER: Self::UInt;
+ + 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 {}
-
-/// Size of field elements of this elliptic curve.
-pub type FieldSize<C> = <<C as Curve>::UInt as bigint::ArrayEncoding>::ByteSize;
-
-/// Byte representation of a base/scalar field element of a given curve.
-pub type FieldBytes<C> = GenericArray<u8, FieldSize<C>>;
-
-/// Affine point type for a given curve with a [`ProjectiveArithmetic`]
-/// implementation.
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg(feature = "arithmetic")]
-pub type AffinePoint<C> = <C as AffineArithmetic>::AffinePoint;
-
-/// Projective point type for a given curve with a [`ProjectiveArithmetic`]
-/// implementation.
-#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub type ProjectivePoint<C> = <C as ProjectiveArithmetic>::ProjectivePoint;
-
-/// Elliptic curve parameters used by VOPRF.
-#[cfg(feature = "voprf")]
-#[cfg_attr(docsrs, doc(cfg(feature = "voprf")))]
-pub trait VoprfParameters: Curve {
- /// The `ID` parameter which identifies a particular elliptic curve
- /// as defined in [section 4 of `draft-irtf-cfrg-voprf-08`][voprf].
- ///
- /// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-08.html#section-4
- const ID: u16;
-
- /// The `Hash` parameter which assigns a particular hash function to this
- /// ciphersuite as defined in [section 4 of `draft-irtf-cfrg-voprf-08`][voprf].
- ///
- /// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-08.html#section-4
- type Hash: digest::Digest;
-}
diff --git a/vendor/elliptic-curve/src/macros.rs b/vendor/elliptic-curve/src/macros.rs
deleted file mode 100644
index 6ceadc833..000000000
--- a/vendor/elliptic-curve/src/macros.rs
+++ /dev/null
@@ -1,440 +0,0 @@
-/// Provides both inherent and trait impls for a field element type which are
-/// backed by a core set of arithmetic functions specified as macro arguments.
-///
-/// # Inherent impls
-/// - `const ZERO: Self`
-/// - `const ONE: Self` (multiplicative identity)
-/// - `pub fn from_be_bytes`
-/// - `pub fn from_be_slice`
-/// - `pub fn from_le_bytes`
-/// - `pub fn from_le_slice`
-/// - `pub fn from_uint`
-/// - `fn from_uint_unchecked`
-/// - `pub fn to_be_bytes`
-/// - `pub fn to_le_bytes`
-/// - `pub fn to_canonical`
-/// - `pub fn is_odd`
-/// - `pub fn is_zero`
-/// - `pub fn double`
-///
-/// NOTE: field implementations must provide their own inherent impls of
-/// the following methods in order for the code generated by this macro to
-/// compile:
-///
-/// - `pub fn invert`
-/// - `pub fn sqrt`
-///
-/// # Trait impls
-/// - `AsRef<$arr>`
-/// - `ConditionallySelectable`
-/// - `ConstantTimeEq`
-/// - `ConstantTimeGreater`
-/// - `ConstantTimeLess`
-/// - `Default`
-/// - `DefaultIsZeroes`
-/// - `Eq`
-/// - `Field`
-/// - `PartialEq`
-///
-/// ## Ops
-/// - `Add`
-/// - `AddAssign`
-/// - `Sub`
-/// - `SubAssign`
-/// - `Mul`
-/// - `MulAssign`
-/// - `Neg`
-#[macro_export]
-macro_rules! impl_field_element {
- (
- $fe:tt,
- $bytes:ty,
- $uint:ty,
- $modulus:expr,
- $arr:ty,
- $from_mont:ident,
- $to_mont:ident,
- $add:ident,
- $sub:ident,
- $mul:ident,
- $neg:ident,
- $square:ident
- ) => {
- impl $fe {
- /// Zero element.
- pub const ZERO: Self = Self(<$uint>::ZERO);
-
- /// Multiplicative identity.
- pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE);
-
- /// Create a [`
- #[doc = stringify!($fe)]
- /// `] from a canonical big-endian representation.
- pub fn from_be_bytes(repr: $bytes) -> $crate::subtle::CtOption<Self> {
- use $crate::bigint::ArrayEncoding as _;
- Self::from_uint(<$uint>::from_be_byte_array(repr))
- }
-
- /// Decode [`
- #[doc = stringify!($fe)]
- /// `] from a big endian byte slice.
- pub fn from_be_slice(slice: &[u8]) -> $crate::Result<Self> {
- <$uint as $crate::bigint::Encoding>::Repr::try_from(slice)
- .ok()
- .and_then(|array| Self::from_be_bytes(array.into()).into())
- .ok_or($crate::Error)
- }
-
- /// Create a [`
- #[doc = stringify!($fe)]
- /// `] from a canonical little-endian representation.
- pub fn from_le_bytes(repr: $bytes) -> $crate::subtle::CtOption<Self> {
- use $crate::bigint::ArrayEncoding as _;
- Self::from_uint(<$uint>::from_le_byte_array(repr))
- }
-
- /// Decode [`
- #[doc = stringify!($fe)]
- /// `] from a little endian byte slice.
- pub fn from_le_slice(slice: &[u8]) -> $crate::Result<Self> {
- <$uint as $crate::bigint::Encoding>::Repr::try_from(slice)
- .ok()
- .and_then(|array| Self::from_le_bytes(array.into()).into())
- .ok_or($crate::Error)
- }
-
- /// Decode [`
- #[doc = stringify!($fe)]
- /// `]
- /// from [`
- #[doc = stringify!($uint)]
- /// `] converting it into Montgomery form:
- ///
- /// ```text
- /// w * R^2 * R^-1 mod p = wR mod p
- /// ```
- pub fn from_uint(uint: $uint) -> $crate::subtle::CtOption<Self> {
- use $crate::subtle::ConstantTimeLess as _;
- let is_some = uint.ct_lt(&$modulus);
- $crate::subtle::CtOption::new(Self::from_uint_unchecked(uint), is_some)
- }
-
- /// Parse a [`
- #[doc = stringify!($fe)]
- /// `] from big endian hex-encoded bytes.
- ///
- /// Does *not* perform a check that the field element does not overflow the order.
- ///
- /// This method is primarily intended for defining internal constants.
- #[allow(dead_code)]
- pub(crate) const fn from_be_hex(hex: &str) -> Self {
- Self::from_uint_unchecked(<$uint>::from_be_hex(hex))
- }
-
- /// Parse a [`
- #[doc = stringify!($fe)]
- /// `] from little endian hex-encoded bytes.
- ///
- /// Does *not* perform a check that the field element does not overflow the order.
- ///
- /// This method is primarily intended for defining internal constants.
- #[allow(dead_code)]
- pub(crate) const fn from_le_hex(hex: &str) -> Self {
- Self::from_uint_unchecked(<$uint>::from_le_hex(hex))
- }
-
- /// Decode [`
- #[doc = stringify!($fe)]
- /// `] from [`
- #[doc = stringify!($uint)]
- /// `] converting it into Montgomery form.
- ///
- /// Does *not* perform a check that the field element does not overflow the order.
- ///
- /// Used incorrectly this can lead to invalid results!
- pub(crate) const fn from_uint_unchecked(w: $uint) -> Self {
- Self(<$uint>::from_words($to_mont(w.as_words())))
- }
-
- /// Returns the big-endian encoding of this [`
- #[doc = stringify!($fe)]
- /// `].
- pub fn to_be_bytes(self) -> $bytes {
- use $crate::bigint::ArrayEncoding as _;
- self.to_canonical().to_be_byte_array()
- }
-
- /// Returns the little-endian encoding of this [`
- #[doc = stringify!($fe)]
- /// `].
- pub fn to_le_bytes(self) -> $bytes {
- use $crate::bigint::ArrayEncoding as _;
- self.to_canonical().to_le_byte_array()
- }
-
- /// Translate [`
- #[doc = stringify!($fe)]
- /// `] out of the Montgomery domain, returning a [`
- #[doc = stringify!($uint)]
- /// `] in canonical form.
- #[inline]
- pub const fn to_canonical(self) -> $uint {
- <$uint>::from_words($from_mont(self.0.as_words()))
- }
-
- /// Determine if this [`
- #[doc = stringify!($fe)]
- /// `] is odd in the SEC1 sense: `self mod 2 == 1`.
- ///
- /// # Returns
- ///
- /// If odd, return `Choice(1)`. Otherwise, return `Choice(0)`.
- pub fn is_odd(&self) -> Choice {
- use $crate::bigint::Integer;
- self.to_canonical().is_odd()
- }
-
- /// Determine if this [`
- #[doc = stringify!($fe)]
- /// `] is even in the SEC1 sense: `self mod 2 == 0`.
- ///
- /// # Returns
- ///
- /// If even, return `Choice(1)`. Otherwise, return `Choice(0)`.
- pub fn is_even(&self) -> Choice {
- !self.is_odd()
- }
-
- /// Determine if this [`
- #[doc = stringify!($fe)]
- /// `] is zero.
- ///
- /// # Returns
- ///
- /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`.
- pub fn is_zero(&self) -> Choice {
- self.ct_eq(&Self::ZERO)
- }
-
- /// Add elements.
- pub const fn add(&self, rhs: &Self) -> Self {
- Self(<$uint>::from_words($add(
- self.0.as_words(),
- rhs.0.as_words(),
- )))
- }
-
- /// Double element (add it to itself).
- #[must_use]
- pub const fn double(&self) -> Self {
- self.add(self)
- }
-
- /// Subtract elements.
- pub const fn sub(&self, rhs: &Self) -> Self {
- Self(<$uint>::from_words($sub(
- self.0.as_words(),
- rhs.0.as_words(),
- )))
- }
-
- /// Multiply elements.
- pub const fn mul(&self, rhs: &Self) -> Self {
- Self(<$uint>::from_words($mul(
- self.0.as_words(),
- rhs.0.as_words(),
- )))
- }
-
- /// Negate element.
- pub const fn neg(&self) -> Self {
- Self(<$uint>::from_words($neg(self.0.as_words())))
- }
-
- /// Compute modular square.
- #[must_use]
- pub const fn square(&self) -> Self {
- Self(<$uint>::from_words($square(self.0.as_words())))
- }
- }
-
- impl AsRef<$arr> for $fe {
- fn as_ref(&self) -> &$arr {
- self.0.as_ref()
- }
- }
-
- impl Default for $fe {
- fn default() -> Self {
- Self::ZERO
- }
- }
-
- impl Eq for $fe {}
-
- impl PartialEq for $fe {
- fn eq(&self, rhs: &Self) -> bool {
- self.0.ct_eq(&(rhs.0)).into()
- }
- }
-
- impl $crate::subtle::ConditionallySelectable for $fe {
- fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
- Self(<$uint>::conditional_select(&a.0, &b.0, choice))
- }
- }
-
- impl $crate::subtle::ConstantTimeEq for $fe {
- fn ct_eq(&self, other: &Self) -> $crate::subtle::Choice {
- self.0.ct_eq(&other.0)
- }
- }
-
- impl $crate::subtle::ConstantTimeGreater for $fe {
- fn ct_gt(&self, other: &Self) -> $crate::subtle::Choice {
- self.0.ct_gt(&other.0)
- }
- }
-
- impl $crate::subtle::ConstantTimeLess for $fe {
- fn ct_lt(&self, other: &Self) -> $crate::subtle::Choice {
- self.0.ct_lt(&other.0)
- }
- }
-
- impl $crate::zeroize::DefaultIsZeroes for $fe {}
-
- impl $crate::ff::Field for $fe {
- fn random(mut rng: impl $crate::rand_core::RngCore) -> Self {
- // NOTE: can't use ScalarCore::random due to CryptoRng bound
- let mut bytes = <$bytes>::default();
-
- loop {
- rng.fill_bytes(&mut bytes);
- if let Some(fe) = Self::from_be_bytes(bytes).into() {
- return fe;
- }
- }
- }
-
- fn zero() -> Self {
- Self::ZERO
- }
-
- fn one() -> Self {
- Self::ONE
- }
-
- fn is_zero(&self) -> Choice {
- Self::ZERO.ct_eq(self)
- }
-
- #[must_use]
- fn square(&self) -> Self {
- self.square()
- }
-
- #[must_use]
- fn double(&self) -> Self {
- self.double()
- }
-
- fn invert(&self) -> CtOption<Self> {
- self.invert()
- }
-
- fn sqrt(&self) -> CtOption<Self> {
- self.sqrt()
- }
- }
-
- $crate::impl_field_op!($fe, $uint, Add, add, $add);
- $crate::impl_field_op!($fe, $uint, Sub, sub, $sub);
- $crate::impl_field_op!($fe, $uint, Mul, mul, $mul);
-
- impl AddAssign<$fe> for $fe {
- #[inline]
- fn add_assign(&mut self, other: $fe) {
- *self = *self + other;
- }
- }
-
- impl AddAssign<&$fe> for $fe {
- #[inline]
- fn add_assign(&mut self, other: &$fe) {
- *self = *self + other;
- }
- }
-
- impl SubAssign<$fe> for $fe {
- #[inline]
- fn sub_assign(&mut self, other: $fe) {
- *self = *self - other;
- }
- }
-
- impl SubAssign<&$fe> for $fe {
- #[inline]
- fn sub_assign(&mut self, other: &$fe) {
- *self = *self - other;
- }
- }
-
- impl MulAssign<&$fe> for $fe {
- #[inline]
- fn mul_assign(&mut self, other: &$fe) {
- *self = *self * other;
- }
- }
-
- impl MulAssign for $fe {
- #[inline]
- fn mul_assign(&mut self, other: $fe) {
- *self = *self * other;
- }
- }
-
- impl Neg for $fe {
- type Output = $fe;
-
- #[inline]
- fn neg(self) -> $fe {
- Self($neg(self.as_ref()).into())
- }
- }
- };
-}
-
-/// Emit impls for a `core::ops` trait for all combinations of reference types,
-/// which thunk to the given function.
-#[macro_export]
-macro_rules! impl_field_op {
- ($fe:tt, $uint:ty, $op:tt, $op_fn:ident, $func:ident) => {
- impl ::core::ops::$op for $fe {
- type Output = $fe;
-
- #[inline]
- fn $op_fn(self, rhs: $fe) -> $fe {
- $fe($func(self.as_ref(), rhs.as_ref()).into())
- }
- }
-
- impl ::core::ops::$op<&$fe> for $fe {
- type Output = $fe;
-
- #[inline]
- fn $op_fn(self, rhs: &$fe) -> $fe {
- $fe($func(self.as_ref(), rhs.as_ref()).into())
- }
- }
-
- impl ::core::ops::$op<&$fe> for &$fe {
- type Output = $fe;
-
- #[inline]
- fn $op_fn(self, rhs: &$fe) -> $fe {
- $fe($func(self.as_ref(), rhs.as_ref()).into())
- }
- }
- };
-}
diff --git a/vendor/elliptic-curve/src/ops.rs b/vendor/elliptic-curve/src/ops.rs
index 580c5aefc..b7e9e3d46 100644
--- a/vendor/elliptic-curve/src/ops.rs
+++ b/vendor/elliptic-curve/src/ops.rs
@@ -1,14 +1,9 @@
//! Traits for arithmetic operations on elliptic curve field elements.
-pub use core::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
+pub use core::ops::{Add, AddAssign, Mul, Neg, Shr, ShrAssign, Sub, SubAssign};
-use crypto_bigint::{ArrayEncoding, ByteArray, Integer};
-
-#[cfg(feature = "arithmetic")]
-use {group::Group, subtle::CtOption};
-
-#[cfg(feature = "digest")]
-use digest::FixedOutput;
+use crypto_bigint::Integer;
+use group::Group;
/// Perform an inversion on a field element (i.e. base field element or scalar)
pub trait Invert {
@@ -17,14 +12,16 @@ pub trait Invert {
/// Invert a field element.
fn invert(&self) -> Self::Output;
-}
-
-#[cfg(feature = "arithmetic")]
-impl<F: ff::Field> Invert for F {
- type Output = CtOption<F>;
- fn invert(&self) -> CtOption<F> {
- ff::Field::invert(self)
+ /// 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()
}
}
@@ -34,8 +31,6 @@ impl<F: ff::Field> Invert for F {
/// 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)
-#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub trait LinearCombination: Group {
/// Calculates `x * k + y * l`.
fn lincomb(x: &Self, k: &Self::Scalar, y: &Self, l: &Self::Scalar) -> Self {
@@ -43,44 +38,28 @@ pub trait LinearCombination: Group {
}
}
-/// Modular reduction.
-pub trait Reduce<UInt: Integer + ArrayEncoding>: Sized {
- /// Perform a modular reduction, returning a field element.
- fn from_uint_reduced(n: UInt) -> Self;
-
- /// Interpret the given byte array as a big endian integer and perform
- /// a modular reduction.
- fn from_be_bytes_reduced(bytes: ByteArray<UInt>) -> Self {
- Self::from_uint_reduced(UInt::from_be_byte_array(bytes))
+/// 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
}
+}
- /// Interpret the given byte array as a little endian integer and perform a
- /// modular reduction.
- fn from_le_bytes_reduced(bytes: ByteArray<UInt>) -> Self {
- Self::from_uint_reduced(UInt::from_le_byte_array(bytes))
- }
+/// Modular reduction.
+pub trait Reduce<Uint: Integer>: Sized {
+ /// Bytes used as input to [`Reduce::reduce_bytes`].
+ type Bytes: AsRef<[u8]>;
- /// Interpret a digest as a big endian integer and perform a modular
- /// reduction.
- #[cfg(feature = "digest")]
- #[cfg_attr(docsrs, doc(cfg(feature = "digest")))]
- fn from_be_digest_reduced<D>(digest: D) -> Self
- where
- D: FixedOutput<OutputSize = UInt::ByteSize>,
- {
- Self::from_be_bytes_reduced(digest.finalize_fixed())
- }
+ /// Perform a modular reduction, returning a field element.
+ fn reduce(n: Uint) -> Self;
- /// Interpret a digest as a little endian integer and perform a modular
- /// reduction.
- #[cfg(feature = "digest")]
- #[cfg_attr(docsrs, doc(cfg(feature = "digest")))]
- fn from_le_digest_reduced<D>(digest: D) -> Self
- where
- D: FixedOutput<OutputSize = UInt::ByteSize>,
- {
- Self::from_le_bytes_reduced(digest.finalize_fixed())
- }
+ /// 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.
@@ -90,7 +69,11 @@ pub trait Reduce<UInt: Integer + ArrayEncoding>: Sized {
///
/// End users should use the [`Reduce`] impl on
/// [`NonZeroScalar`][`crate::NonZeroScalar`] instead.
-pub trait ReduceNonZero<UInt: Integer + ArrayEncoding>: Sized {
+pub trait ReduceNonZero<Uint: Integer>: Reduce<Uint> + Sized {
/// Perform a modular reduction, returning a field element.
- fn from_uint_reduced_nonzero(n: UInt) -> Self;
+ 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
index 7257be66c..25b872a0e 100644
--- a/vendor/elliptic-curve/src/point.rs
+++ b/vendor/elliptic-curve/src/point.rs
@@ -1,12 +1,41 @@
//! 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};
-/// Obtain the affine x-coordinate of an elliptic curve point.
-pub trait AffineXCoordinate<C: Curve> {
+/// 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) -> FieldBytes<C>;
+ 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.
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 000000000..81c31cd19
--- /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
index 1dc858581..e2d71b3f0 100644
--- a/vendor/elliptic-curve/src/public_key.rs
+++ b/vendor/elliptic-curve/src/public_key.rs
@@ -1,19 +1,19 @@
//! Elliptic curve public keys.
use crate::{
- AffinePoint, Curve, Error, NonZeroScalar, ProjectiveArithmetic, ProjectivePoint, Result,
+ point::NonIdentity, AffinePoint, CurveArithmetic, Error, NonZeroScalar, ProjectivePoint, Result,
};
use core::fmt::Debug;
-use group::{Curve as _, Group};
+use group::{Curve, Group};
+
+#[cfg(feature = "alloc")]
+use alloc::boxed::Box;
#[cfg(feature = "jwk")]
use crate::{JwkEcKey, JwkParameters};
-#[cfg(all(feature = "sec1", feature = "pkcs8"))]
-use crate::{
- pkcs8::{self, AssociatedOid, DecodePublicKey},
- ALGORITHM_OID,
-};
+#[cfg(feature = "pkcs8")]
+use pkcs8::spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, ObjectIdentifier};
#[cfg(feature = "pem")]
use core::str::FromStr;
@@ -21,22 +21,35 @@ use core::str::FromStr;
#[cfg(feature = "sec1")]
use {
crate::{
- sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
- FieldSize, PointCompression,
+ point::PointCompression,
+ sec1::{CompressedPoint, EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
+ FieldBytesSize,
},
core::cmp::Ordering,
subtle::CtOption,
};
-#[cfg(feature = "serde")]
-use serdect::serde::{de, ser, Deserialize, Serialize};
-
#[cfg(all(feature = "alloc", feature = "pkcs8"))]
use pkcs8::EncodePublicKey;
#[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
@@ -73,18 +86,17 @@ use alloc::string::{String, ToString};
/// Subject Public Key Info (SPKI) as the encoding format.
///
/// For a more text-friendly encoding of public keys, use [`JwkEcKey`] instead.
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
point: AffinePoint<C>,
}
impl<C> PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
/// Convert an [`AffinePoint`] into a [`PublicKey`]
pub fn from_affine(point: AffinePoint<C>) -> Result<Self> {
@@ -113,14 +125,29 @@ where
#[cfg(feature = "sec1")]
pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self>
where
- C: Curve,
- FieldSize<C>: ModulusSize,
+ 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(feature = "alloc")]
+ 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.
@@ -133,50 +160,51 @@ where
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")]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn from_jwk(jwk: &JwkEcKey) -> Result<Self>
where
- C: Curve + JwkParameters,
+ C: JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
jwk.to_public_key::<C>()
}
/// Parse a string containing a JSON Web Key (JWK) into a [`PublicKey`].
#[cfg(feature = "jwk")]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn from_jwk_str(jwk: &str) -> Result<Self>
where
- C: Curve + JwkParameters,
+ C: JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ 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")]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn to_jwk(&self) -> JwkEcKey
where
- C: Curve + JwkParameters,
+ C: JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
self.into()
}
/// Serialize this public key as JSON Web Key (JWK) string.
#[cfg(feature = "jwk")]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn to_jwk_string(&self) -> String
where
- C: Curve + JwkParameters,
+ C: JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
self.to_jwk().to_string()
}
@@ -184,22 +212,21 @@ where
impl<C> AsRef<AffinePoint<C>> for PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
fn as_ref(&self) -> &AffinePoint<C> {
self.as_affine()
}
}
-impl<C> Copy for PublicKey<C> where C: Curve + ProjectiveArithmetic {}
+impl<C> Copy for PublicKey<C> where C: CurveArithmetic {}
#[cfg(feature = "sec1")]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> FromEncodedPoint<C> for PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
/// Initialize [`PublicKey`] from an [`EncodedPoint`]
fn from_encoded_point(encoded_point: &EncodedPoint<C>) -> CtOption<Self> {
@@ -211,12 +238,11 @@ where
}
#[cfg(feature = "sec1")]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> ToEncodedPoint<C> for PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
/// Serialize this [`PublicKey`] as a SEC1 [`EncodedPoint`], optionally applying
/// point compression
@@ -226,12 +252,35 @@ where
}
#[cfg(feature = "sec1")]
-#[cfg_attr(docsrs, doc(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: Curve + ProjectiveArithmetic + PointCompression,
+ C: CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn from(public_key: PublicKey<C>) -> EncodedPoint<C> {
EncodedPoint::<C>::from(&public_key)
@@ -239,25 +288,63 @@ where
}
#[cfg(feature = "sec1")]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> From<&PublicKey<C>> for EncodedPoint<C>
where
- C: Curve + ProjectiveArithmetic + PointCompression,
+ C: CurveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ 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")]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> PartialOrd for PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
@@ -265,12 +352,11 @@ where
}
#[cfg(feature = "sec1")]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> Ord for PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn cmp(&self, other: &Self) -> Ordering {
// TODO(tarcieri): more efficient implementation?
@@ -280,64 +366,136 @@ where
}
}
-#[cfg(all(feature = "pkcs8", feature = "sec1"))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "pkcs8", feature = "sec1"))))]
-impl<C> TryFrom<pkcs8::SubjectPublicKeyInfo<'_>> for PublicKey<C>
+#[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: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: CurveArithmetic,
+ FieldBytesSize<C>: ModulusSize,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+{
+ 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::SubjectPublicKeyInfo<'_>) -> pkcs8::spki::Result<Self> {
- spki.algorithm.assert_oids(ALGORITHM_OID, C::OID)?;
- Self::from_sec1_bytes(spki.subject_public_key)
- .map_err(|_| der::Tag::BitString.value_error().into())
+ fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result<Self> {
+ Self::try_from(&spki)
}
}
-#[cfg(all(feature = "pkcs8", feature = "sec1"))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "pkcs8", feature = "sec1"))))]
-impl<C> DecodePublicKey for PublicKey<C>
+#[cfg(feature = "pkcs8")]
+impl<C> TryFrom<&pkcs8::SubjectPublicKeyInfoRef<'_>> for PublicKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ 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"))]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))]
impl<C> EncodePublicKey for PublicKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn to_public_key_der(&self) -> pkcs8::spki::Result<der::Document> {
- let algorithm = pkcs8::AlgorithmIdentifier {
- oid: ALGORITHM_OID,
- parameters: Some((&C::OID).into()),
- };
-
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,
- subject_public_key: public_key_bytes.as_ref(),
+ algorithm: Self::ALGORITHM_IDENTIFIER,
+ subject_public_key,
}
.try_into()
}
}
#[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl<C> FromStr for PublicKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Err = Error;
@@ -347,12 +505,11 @@ where
}
#[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl<C> ToString for PublicKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn to_string(&self) -> String {
self.to_public_key_pem(Default::default())
@@ -361,12 +518,11 @@ where
}
#[cfg(feature = "serde")]
-#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<C> Serialize for PublicKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
where
@@ -378,12 +534,11 @@ where
}
#[cfg(feature = "serde")]
-#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de, C> Deserialize<'de> for PublicKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
where
diff --git a/vendor/elliptic-curve/src/scalar.rs b/vendor/elliptic-curve/src/scalar.rs
index 72d796847..eb992493a 100644
--- a/vendor/elliptic-curve/src/scalar.rs
+++ b/vendor/elliptic-curve/src/scalar.rs
@@ -1,25 +1,46 @@
//! Scalar types.
-use subtle::Choice;
-
-pub(crate) mod core;
+#[cfg(feature = "arithmetic")]
+mod blinded;
+#[cfg(feature = "arithmetic")]
+mod nonzero;
+mod primitive;
+pub use self::primitive::ScalarPrimitive;
#[cfg(feature = "arithmetic")]
-pub(crate) mod nonzero;
+pub use self::{blinded::BlindedScalar, nonzero::NonZeroScalar};
+
+use crypto_bigint::Integer;
+use subtle::Choice;
#[cfg(feature = "arithmetic")]
-use crate::ScalarArithmetic;
+use crate::CurveArithmetic;
/// Scalar field element for a particular elliptic curve.
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub type Scalar<C> = <C as ScalarArithmetic>::Scalar;
+pub type Scalar<C> = <C as CurveArithmetic>::Scalar;
/// Bit representation of a scalar field element of a given curve.
#[cfg(feature = "bits")]
-#[cfg_attr(docsrs, doc(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
diff --git a/vendor/elliptic-curve/src/scalar/blinded.rs b/vendor/elliptic-curve/src/scalar/blinded.rs
new file mode 100644
index 000000000..29cfea98c
--- /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
index 7450537a9..c0e45740f 100644
--- a/vendor/elliptic-curve/src/scalar/nonzero.rs
+++ b/vendor/elliptic-curve/src/scalar/nonzero.rs
@@ -1,11 +1,9 @@
//! Non-zero scalar type.
use crate::{
- bigint::Encoding as _,
ops::{Invert, Reduce, ReduceNonZero},
- rand_core::{CryptoRng, RngCore},
- Curve, Error, FieldBytes, IsHigh, PrimeCurve, Result, Scalar, ScalarArithmetic, ScalarCore,
- SecretKey,
+ scalar::IsHigh,
+ CurveArithmetic, Error, FieldBytes, PrimeCurve, Scalar, ScalarPrimitive, SecretKey,
};
use base16ct::HexDisplay;
use core::{
@@ -15,10 +13,14 @@ use core::{
};
use crypto_bigint::{ArrayEncoding, Integer};
use ff::{Field, PrimeField};
-use generic_array::GenericArray;
+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*`.
@@ -27,21 +29,20 @@ use zeroize::Zeroize;
///
/// In the context of ECC, it's useful for ensuring that scalar multiplication
/// cannot result in the point at infinity.
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
#[derive(Clone)]
pub struct NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
scalar: Scalar<C>,
}
impl<C> NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
/// Generate a random `NonZeroScalar`.
- pub fn random(mut rng: impl CryptoRng + RngCore) -> Self {
+ 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`.
@@ -62,15 +63,15 @@ where
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> {
- ScalarCore::new(uint).and_then(|scalar| Self::new(scalar.into()))
+ /// 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: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn as_ref(&self) -> &Scalar<C> {
&self.scalar
@@ -79,7 +80,7 @@ where
impl<C> ConditionallySelectable for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Self {
@@ -90,18 +91,18 @@ where
impl<C> ConstantTimeEq for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn ct_eq(&self, other: &Self) -> Choice {
self.scalar.ct_eq(&other.scalar)
}
}
-impl<C> Copy for NonZeroScalar<C> where C: Curve + ScalarArithmetic {}
+impl<C> Copy for NonZeroScalar<C> where C: CurveArithmetic {}
impl<C> Deref for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
type Target = Scalar<C>;
@@ -112,7 +113,7 @@ where
impl<C> From<NonZeroScalar<C>> for FieldBytes<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn from(scalar: NonZeroScalar<C>) -> FieldBytes<C> {
Self::from(&scalar)
@@ -121,34 +122,35 @@ where
impl<C> From<&NonZeroScalar<C>> for FieldBytes<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn from(scalar: &NonZeroScalar<C>) -> FieldBytes<C> {
scalar.to_repr()
}
}
-impl<C> From<NonZeroScalar<C>> for ScalarCore<C>
+impl<C> From<NonZeroScalar<C>> for ScalarPrimitive<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
- fn from(scalar: NonZeroScalar<C>) -> ScalarCore<C> {
- ScalarCore::from_be_bytes(scalar.to_repr()).unwrap()
+ #[inline]
+ fn from(scalar: NonZeroScalar<C>) -> ScalarPrimitive<C> {
+ Self::from(&scalar)
}
}
-impl<C> From<&NonZeroScalar<C>> for ScalarCore<C>
+impl<C> From<&NonZeroScalar<C>> for ScalarPrimitive<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
- fn from(scalar: &NonZeroScalar<C>) -> ScalarCore<C> {
- ScalarCore::from_be_bytes(scalar.to_repr()).unwrap()
+ fn from(scalar: &NonZeroScalar<C>) -> ScalarPrimitive<C> {
+ ScalarPrimitive::from_bytes(&scalar.to_repr()).unwrap()
}
}
impl<C> From<SecretKey<C>> for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn from(sk: SecretKey<C>) -> NonZeroScalar<C> {
Self::from(&sk)
@@ -157,10 +159,10 @@ where
impl<C> From<&SecretKey<C>> for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn from(sk: &SecretKey<C>) -> NonZeroScalar<C> {
- let scalar = sk.as_scalar_core().to_scalar();
+ let scalar = sk.as_scalar_primitive().to_scalar();
debug_assert!(!bool::from(scalar.is_zero()));
Self { scalar }
}
@@ -168,21 +170,29 @@ where
impl<C> Invert for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ 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: ff::Field::invert(&self.scalar).unwrap(),
+ 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: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn is_high(&self) -> Choice {
self.scalar.is_high()
@@ -191,7 +201,7 @@ where
impl<C> Neg for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
type Output = NonZeroScalar<C>;
@@ -204,7 +214,7 @@ where
impl<C> Mul<NonZeroScalar<C>> for NonZeroScalar<C>
where
- C: PrimeCurve + ScalarArithmetic,
+ C: PrimeCurve + CurveArithmetic,
{
type Output = Self;
@@ -216,7 +226,7 @@ where
impl<C> Mul<&NonZeroScalar<C>> for NonZeroScalar<C>
where
- C: PrimeCurve + ScalarArithmetic,
+ C: PrimeCurve + CurveArithmetic,
{
type Output = Self;
@@ -229,39 +239,53 @@ where
}
}
-/// Note: implementation is the same as `ReduceNonZero`
+/// Note: this is a non-zero reduction, as it's impl'd for [`NonZeroScalar`].
impl<C, I> Reduce<I> for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
I: Integer + ArrayEncoding,
- Scalar<C>: ReduceNonZero<I>,
+ Scalar<C>: Reduce<I> + ReduceNonZero<I>,
{
- fn from_uint_reduced(n: I) -> Self {
- Self::from_uint_reduced_nonzero(n)
+ 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
- C: Curve + ScalarArithmetic,
+ Self: Reduce<I>,
+ C: CurveArithmetic,
I: Integer + ArrayEncoding,
- Scalar<C>: ReduceNonZero<I>,
+ Scalar<C>: Reduce<I, Bytes = Self::Bytes> + ReduceNonZero<I>,
{
- fn from_uint_reduced_nonzero(n: I) -> Self {
- let scalar = Scalar::<C>::from_uint_reduced_nonzero(n);
- debug_assert!(!bool::from(scalar.is_zero()));
- Self::new(scalar).unwrap()
+ 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: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
type Error = Error;
- fn try_from(bytes: &[u8]) -> Result<Self> {
- if bytes.len() == C::UInt::BYTE_SIZE {
+ fn try_from(bytes: &[u8]) -> Result<Self, Error> {
+ if bytes.len() == C::FieldBytesSize::USIZE {
Option::from(NonZeroScalar::from_repr(GenericArray::clone_from_slice(
bytes,
)))
@@ -274,7 +298,7 @@ where
impl<C> Zeroize for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn zeroize(&mut self) {
// Use zeroize's volatile writes to ensure value is cleared.
@@ -282,22 +306,22 @@ where
// Write a 1 instead of a 0 to ensure this type's non-zero invariant
// is upheld.
- self.scalar = Scalar::<C>::one();
+ self.scalar = Scalar::<C>::ONE;
}
}
impl<C> fmt::Display for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:X}", self)
+ write!(f, "{self:X}")
}
}
impl<C> fmt::LowerHex for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:x}", HexDisplay(&self.to_repr()))
@@ -306,7 +330,7 @@ where
impl<C> fmt::UpperHex for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:}", HexDisplay(&self.to_repr()))
@@ -315,11 +339,11 @@ where
impl<C> str::FromStr for NonZeroScalar<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
type Err = Error;
- fn from_str(hex: &str) -> Result<Self> {
+ fn from_str(hex: &str) -> Result<Self, Error> {
let mut bytes = FieldBytes::<C>::default();
if base16ct::mixed::decode(hex, &mut bytes)?.len() == bytes.len() {
@@ -330,6 +354,34 @@ where
}
}
+#[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};
@@ -348,6 +400,6 @@ mod tests {
fn zeroize() {
let mut scalar = NonZeroScalar::new(Scalar::from(42u64)).unwrap();
scalar.zeroize();
- assert_eq!(*scalar, Scalar::one());
+ assert_eq!(*scalar, Scalar::ONE);
}
}
diff --git a/vendor/elliptic-curve/src/scalar/core.rs b/vendor/elliptic-curve/src/scalar/primitive.rs
index 6a088ca55..a4f64cb58 100644
--- a/vendor/elliptic-curve/src/scalar/core.rs
+++ b/vendor/elliptic-curve/src/scalar/primitive.rs
@@ -1,34 +1,33 @@
-//! Generic scalar type with core functionality.
+//! Generic scalar type with primitive functionality.
use crate::{
bigint::{prelude::*, Limb, NonZero},
- rand_core::{CryptoRng, RngCore},
- subtle::{
- Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
- CtOption,
- },
- Curve, Error, FieldBytes, IsHigh, Result,
+ scalar::FromUintUnchecked,
+ scalar::IsHigh,
+ Curve, Error, FieldBytes, FieldBytesEncoding, Result,
};
use base16ct::HexDisplay;
use core::{
cmp::Ordering,
fmt,
- ops::{Add, AddAssign, Neg, Sub, SubAssign},
+ ops::{Add, AddAssign, Neg, ShrAssign, Sub, SubAssign},
str,
};
-use generic_array::GenericArray;
+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::{Scalar, ScalarArithmetic},
- group::ff::PrimeField,
-};
+use super::{CurveArithmetic, Scalar};
#[cfg(feature = "serde")]
use serdect::serde::{de, ser, Deserialize, Serialize};
-/// Generic scalar type with core functionality.
+/// 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
@@ -41,73 +40,58 @@ use serdect::serde::{de, ser, Deserialize, Serialize};
///
/// The serialization is a fixed-width big endian encoding. When used with
/// textual formats, the binary data is encoded as hexadecimal.
-// TODO(tarcieri): make this a fully generic `Scalar` type and use it for `ScalarArithmetic`
+// TODO(tarcieri): use `crypto-bigint`'s `Residue` type, expose more functionality?
#[derive(Copy, Clone, Debug, Default)]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-pub struct ScalarCore<C: Curve> {
+pub struct ScalarPrimitive<C: Curve> {
/// Inner unsigned integer type.
- inner: C::UInt,
+ inner: C::Uint,
}
-impl<C> ScalarCore<C>
+impl<C> ScalarPrimitive<C>
where
C: Curve,
{
/// Zero scalar.
pub const ZERO: Self = Self {
- inner: C::UInt::ZERO,
+ inner: C::Uint::ZERO,
};
/// Multiplicative identity.
pub const ONE: Self = Self {
- inner: C::UInt::ONE,
+ inner: C::Uint::ONE,
};
/// Scalar modulus.
- pub const MODULUS: C::UInt = C::ORDER;
+ pub const MODULUS: C::Uint = C::ORDER;
- /// Generate a random [`ScalarCore`].
- pub fn random(rng: impl CryptoRng + RngCore) -> Self {
+ /// Generate a random [`ScalarPrimitive`].
+ pub fn random(rng: &mut impl CryptoRngCore) -> Self {
Self {
- inner: C::UInt::random_mod(rng, &NonZero::new(Self::MODULUS).unwrap()),
+ 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> {
+ /// 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 [`ScalarCore`] from big endian bytes.
- pub fn from_be_bytes(bytes: FieldBytes<C>) -> CtOption<Self> {
- Self::new(C::UInt::from_be_byte_array(bytes))
+ /// 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 [`ScalarCore`] from a big endian byte slice.
- pub fn from_be_slice(slice: &[u8]) -> Result<Self> {
- if slice.len() == C::UInt::BYTE_SIZE {
- Option::from(Self::from_be_bytes(GenericArray::clone_from_slice(slice))).ok_or(Error)
+ /// 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)
}
}
- /// Decode [`ScalarCore`] from little endian bytes.
- pub fn from_le_bytes(bytes: FieldBytes<C>) -> CtOption<Self> {
- Self::new(C::UInt::from_le_byte_array(bytes))
- }
-
- /// Decode [`ScalarCore`] from a little endian byte slice.
- pub fn from_le_slice(slice: &[u8]) -> Result<Self> {
- if slice.len() == C::UInt::BYTE_SIZE {
- Option::from(Self::from_le_bytes(GenericArray::clone_from_slice(slice))).ok_or(Error)
- } else {
- Err(Error)
- }
- }
-
- /// Borrow the inner `C::UInt`.
- pub fn as_uint(&self) -> &C::UInt {
+ /// Borrow the inner `C::Uint`.
+ pub fn as_uint(&self) -> &C::Uint {
&self.inner
}
@@ -116,46 +100,56 @@ where
self.inner.as_ref()
}
- /// Is this [`ScalarCore`] value equal to zero?
+ /// Is this [`ScalarPrimitive`] value equal to zero?
pub fn is_zero(&self) -> Choice {
self.inner.is_zero()
}
- /// Is this [`ScalarCore`] value even?
+ /// Is this [`ScalarPrimitive`] value even?
pub fn is_even(&self) -> Choice {
self.inner.is_even()
}
- /// Is this [`ScalarCore`] value odd?
+ /// Is this [`ScalarPrimitive`] value odd?
pub fn is_odd(&self) -> Choice {
self.inner.is_odd()
}
- /// Encode [`ScalarCore`] as big endian bytes.
- pub fn to_be_bytes(self) -> FieldBytes<C> {
- self.inner.to_be_byte_array()
+ /// 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;
- /// Encode [`ScalarCore`] as little endian bytes.
- pub fn to_le_bytes(self) -> FieldBytes<C> {
- self.inner.to_le_byte_array()
+ fn from_uint_unchecked(uint: C::Uint) -> Self {
+ Self { inner: uint }
}
}
#[cfg(feature = "arithmetic")]
-impl<C> ScalarCore<C>
+impl<C> ScalarPrimitive<C>
where
- C: Curve + ScalarArithmetic,
+ C: CurveArithmetic,
{
- /// Convert [`ScalarCore`] into a given curve's scalar type
- // TODO(tarcieri): replace curve-specific scalars with `ScalarCore`
+ /// Convert [`ScalarPrimitive`] into a given curve's scalar type.
pub(super) fn to_scalar(self) -> Scalar<C> {
- Scalar::<C>::from_repr(self.to_be_bytes()).unwrap()
+ Scalar::<C>::from_uint_unchecked(self.inner)
}
}
// TODO(tarcieri): better encapsulate this?
-impl<C> AsRef<[Limb]> for ScalarCore<C>
+impl<C> AsRef<[Limb]> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -164,18 +158,18 @@ where
}
}
-impl<C> ConditionallySelectable for ScalarCore<C>
+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),
+ inner: C::Uint::conditional_select(&a.inner, &b.inner, choice),
}
}
}
-impl<C> ConstantTimeEq for ScalarCore<C>
+impl<C> ConstantTimeEq for ScalarPrimitive<C>
where
C: Curve,
{
@@ -184,7 +178,7 @@ where
}
}
-impl<C> ConstantTimeLess for ScalarCore<C>
+impl<C> ConstantTimeLess for ScalarPrimitive<C>
where
C: Curve,
{
@@ -193,7 +187,7 @@ where
}
}
-impl<C> ConstantTimeGreater for ScalarCore<C>
+impl<C> ConstantTimeGreater for ScalarPrimitive<C>
where
C: Curve,
{
@@ -202,11 +196,11 @@ where
}
}
-impl<C: Curve> DefaultIsZeroes for ScalarCore<C> {}
+impl<C: Curve> DefaultIsZeroes for ScalarPrimitive<C> {}
-impl<C: Curve> Eq for ScalarCore<C> {}
+impl<C: Curve> Eq for ScalarPrimitive<C> {}
-impl<C> PartialEq for ScalarCore<C>
+impl<C> PartialEq for ScalarPrimitive<C>
where
C: Curve,
{
@@ -215,7 +209,7 @@ where
}
}
-impl<C> PartialOrd for ScalarCore<C>
+impl<C> PartialOrd for ScalarPrimitive<C>
where
C: Curve,
{
@@ -224,7 +218,7 @@ where
}
}
-impl<C> Ord for ScalarCore<C>
+impl<C> Ord for ScalarPrimitive<C>
where
C: Curve,
{
@@ -233,18 +227,18 @@ where
}
}
-impl<C> From<u64> for ScalarCore<C>
+impl<C> From<u64> for ScalarPrimitive<C>
where
C: Curve,
{
fn from(n: u64) -> Self {
Self {
- inner: C::UInt::from(n),
+ inner: C::Uint::from(n),
}
}
}
-impl<C> Add<ScalarCore<C>> for ScalarCore<C>
+impl<C> Add<ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -255,7 +249,7 @@ where
}
}
-impl<C> Add<&ScalarCore<C>> for ScalarCore<C>
+impl<C> Add<&ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -268,7 +262,7 @@ where
}
}
-impl<C> AddAssign<ScalarCore<C>> for ScalarCore<C>
+impl<C> AddAssign<ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -277,7 +271,7 @@ where
}
}
-impl<C> AddAssign<&ScalarCore<C>> for ScalarCore<C>
+impl<C> AddAssign<&ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -286,7 +280,7 @@ where
}
}
-impl<C> Sub<ScalarCore<C>> for ScalarCore<C>
+impl<C> Sub<ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -297,7 +291,7 @@ where
}
}
-impl<C> Sub<&ScalarCore<C>> for ScalarCore<C>
+impl<C> Sub<&ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -310,7 +304,7 @@ where
}
}
-impl<C> SubAssign<ScalarCore<C>> for ScalarCore<C>
+impl<C> SubAssign<ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -319,7 +313,7 @@ where
}
}
-impl<C> SubAssign<&ScalarCore<C>> for ScalarCore<C>
+impl<C> SubAssign<&ScalarPrimitive<C>> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -328,7 +322,7 @@ where
}
}
-impl<C> Neg for ScalarCore<C>
+impl<C> Neg for ScalarPrimitive<C>
where
C: Curve,
{
@@ -341,18 +335,27 @@ where
}
}
-impl<C> Neg for &ScalarCore<C>
+impl<C> Neg for &ScalarPrimitive<C>
where
C: Curve,
{
- type Output = ScalarCore<C>;
+ type Output = ScalarPrimitive<C>;
- fn neg(self) -> ScalarCore<C> {
+ fn neg(self) -> ScalarPrimitive<C> {
-*self
}
}
-impl<C> IsHigh for ScalarCore<C>
+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,
{
@@ -362,34 +365,34 @@ where
}
}
-impl<C> fmt::Display for ScalarCore<C>
+impl<C> fmt::Display for ScalarPrimitive<C>
where
C: Curve,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:X}", self)
+ write!(f, "{self:X}")
}
}
-impl<C> fmt::LowerHex for ScalarCore<C>
+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_be_bytes()))
+ write!(f, "{:x}", HexDisplay(&self.to_bytes()))
}
}
-impl<C> fmt::UpperHex for ScalarCore<C>
+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_be_bytes()))
+ write!(f, "{:X}", HexDisplay(&self.to_bytes()))
}
}
-impl<C> str::FromStr for ScalarCore<C>
+impl<C> str::FromStr for ScalarPrimitive<C>
where
C: Curve,
{
@@ -398,13 +401,12 @@ where
fn from_str(hex: &str) -> Result<Self> {
let mut bytes = FieldBytes::<C>::default();
base16ct::lower::decode(hex, &mut bytes)?;
- Option::from(Self::from_be_bytes(bytes)).ok_or(Error)
+ Self::from_slice(&bytes)
}
}
#[cfg(feature = "serde")]
-#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
-impl<C> Serialize for ScalarCore<C>
+impl<C> Serialize for ScalarPrimitive<C>
where
C: Curve,
{
@@ -412,13 +414,12 @@ where
where
S: ser::Serializer,
{
- serdect::array::serialize_hex_upper_or_bin(&self.to_be_bytes(), serializer)
+ serdect::array::serialize_hex_upper_or_bin(&self.to_bytes(), serializer)
}
}
#[cfg(feature = "serde")]
-#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
-impl<'de, C> Deserialize<'de> for ScalarCore<C>
+impl<'de, C> Deserialize<'de> for ScalarPrimitive<C>
where
C: Curve,
{
@@ -428,7 +429,6 @@ where
{
let mut bytes = FieldBytes::<C>::default();
serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
- Option::from(Self::from_be_bytes(bytes))
- .ok_or_else(|| de::Error::custom("scalar out of range"))
+ 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
index 3e1635941..7673386b8 100644
--- a/vendor/elliptic-curve/src/sec1.rs
+++ b/vendor/elliptic-curve/src/sec1.rs
@@ -4,27 +4,27 @@
pub use sec1::point::{Coordinates, ModulusSize, Tag};
-use crate::{Curve, FieldSize, Result, SecretKey};
+use crate::{Curve, FieldBytesSize, Result, SecretKey};
use generic_array::GenericArray;
use subtle::CtOption;
#[cfg(feature = "arithmetic")]
-use crate::{AffinePoint, Error, ProjectiveArithmetic};
+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> = <FieldSize<C> as ModulusSize>::CompressedPointSize;
+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<FieldSize<C>>;
+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> = <FieldSize<C> as ModulusSize>::UncompressedPointSize;
+pub type UncompressedPointSize<C> = <FieldBytesSize<C> as ModulusSize>::UncompressedPointSize;
/// Trait for deserializing a value from a SEC1 encoded curve point.
///
@@ -33,7 +33,7 @@ pub trait FromEncodedPoint<C>
where
Self: Sized,
C: Curve,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
/// Deserialize the type this trait is impl'd on from an [`EncodedPoint`].
fn from_encoded_point(point: &EncodedPoint<C>) -> CtOption<Self>;
@@ -45,7 +45,7 @@ where
pub trait ToEncodedPoint<C>
where
C: Curve,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
/// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying
/// point compression.
@@ -58,7 +58,7 @@ where
pub trait ToCompactEncodedPoint<C>
where
C: Curve,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
/// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying
/// point compression.
@@ -68,12 +68,12 @@ where
/// Validate that the given [`EncodedPoint`] represents the encoded public key
/// value of the given secret.
///
-/// Curve implementations which also impl [`ProjectiveArithmetic`] will receive
+/// Curve implementations which also impl [`CurveArithmetic`] will receive
/// a blanket default impl of this trait.
pub trait ValidatePublicKey
where
Self: Curve,
- FieldSize<Self>: ModulusSize,
+ FieldBytesSize<Self>: ModulusSize,
{
/// Validate that the given [`EncodedPoint`] is a valid public key for the
/// provided secret value.
@@ -96,9 +96,9 @@ where
#[cfg(all(feature = "arithmetic"))]
impl<C> ValidatePublicKey for C
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn validate_public_key(secret_key: &SecretKey<C>, public_key: &EncodedPoint<C>) -> Result<()> {
let pk = secret_key
diff --git a/vendor/elliptic-curve/src/secret_key.rs b/vendor/elliptic-curve/src/secret_key.rs
index 0fc3dafb1..97b3d58bd 100644
--- a/vendor/elliptic-curve/src/secret_key.rs
+++ b/vendor/elliptic-curve/src/secret_key.rs
@@ -8,10 +8,9 @@
#[cfg(all(feature = "pkcs8", feature = "sec1"))]
mod pkcs8;
-use crate::{Curve, Error, FieldBytes, Result, ScalarCore};
+use crate::{Curve, Error, FieldBytes, Result, ScalarPrimitive};
use core::fmt::{self, Debug};
-use crypto_bigint::Encoding;
-use generic_array::GenericArray;
+use generic_array::typenum::Unsigned;
use subtle::{Choice, ConstantTimeEq};
use zeroize::{Zeroize, ZeroizeOnDrop};
@@ -22,19 +21,21 @@ use {
AffinePoint,
},
alloc::vec::Vec,
- der::Encode,
zeroize::Zeroizing,
};
#[cfg(feature = "arithmetic")]
-use crate::{
- rand_core::{CryptoRng, RngCore},
- NonZeroScalar, ProjectiveArithmetic, PublicKey,
-};
+use crate::{rand_core::CryptoRngCore, CurveArithmetic, NonZeroScalar, PublicKey};
#[cfg(feature = "jwk")]
use crate::jwk::{JwkEcKey, JwkParameters};
+#[cfg(feature = "sec1")]
+use sec1::der;
+
+#[cfg(all(feature = "alloc", feature = "arithmetic", feature = "sec1"))]
+use sec1::der::Encode;
+
#[cfg(all(feature = "arithmetic", any(feature = "jwk", feature = "pem")))]
use alloc::string::String;
@@ -47,10 +48,10 @@ use pem_rfc7468 as pem;
#[cfg(feature = "sec1")]
use crate::{
sec1::{EncodedPoint, ModulusSize, ValidatePublicKey},
- FieldSize,
+ FieldBytesSize,
};
-#[cfg(all(docsrs, feature = "pkcs8"))]
+#[cfg(all(doc, feature = "pkcs8"))]
use {crate::pkcs8::DecodePrivateKey, core::str::FromStr};
/// Type label for PEM-encoded SEC1 private keys.
@@ -83,7 +84,7 @@ pub(crate) const SEC1_PEM_TYPE_LABEL: &str = "EC PRIVATE KEY";
#[derive(Clone)]
pub struct SecretKey<C: Curve> {
/// Scalar value
- inner: ScalarCore<C>,
+ inner: ScalarPrimitive<C>,
}
impl<C> SecretKey<C>
@@ -92,10 +93,9 @@ where
{
/// Generate a random [`SecretKey`].
#[cfg(feature = "arithmetic")]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
- pub fn random(rng: impl CryptoRng + RngCore) -> Self
+ pub fn random(rng: &mut impl CryptoRngCore) -> Self
where
- C: ProjectiveArithmetic,
+ C: CurveArithmetic,
{
Self {
inner: NonZeroScalar::<C>::random(rng).into(),
@@ -103,18 +103,18 @@ where
}
/// Create a new secret key from a scalar value.
- pub fn new(scalar: ScalarCore<C>) -> Self {
+ pub fn new(scalar: ScalarPrimitive<C>) -> Self {
Self { inner: scalar }
}
- /// Borrow the inner secret [`ScalarCore`] value.
+ /// Borrow the inner secret [`ScalarPrimitive`] value.
///
/// # ⚠️ Warning
///
/// This value is key material.
///
/// Please treat it with the care it deserves!
- pub fn as_scalar_core(&self) -> &ScalarCore<C> {
+ pub fn as_scalar_primitive(&self) -> &ScalarPrimitive<C> {
&self.inner
}
@@ -126,54 +126,75 @@ where
///
/// Please treat it with the care it deserves!
#[cfg(feature = "arithmetic")]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub fn to_nonzero_scalar(&self) -> NonZeroScalar<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
self.into()
}
/// Get the [`PublicKey`] which corresponds to this secret key
#[cfg(feature = "arithmetic")]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub fn public_key(&self) -> PublicKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
PublicKey::from_secret_scalar(&self.to_nonzero_scalar())
}
- /// Deserialize raw secret scalar as a big endian integer.
- pub fn from_be_bytes(bytes: &[u8]) -> Result<Self> {
- if bytes.len() != C::UInt::BYTE_SIZE {
+ /// 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);
}
- let inner: ScalarCore<C> = Option::from(ScalarCore::from_be_bytes(
- GenericArray::clone_from_slice(bytes),
- ))
- .ok_or(Error)?;
+ Ok(Self { inner })
+ }
- if inner.is_zero().into() {
+ /// 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);
}
- Ok(Self { inner })
+ /// 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_be_bytes(&self) -> FieldBytes<C> {
- self.inner.to_be_bytes()
+ 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"))]
- #[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
pub fn from_sec1_der(der_bytes: &[u8]) -> Result<Self>
where
C: Curve + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
sec1::EcPrivateKey::try_from(der_bytes)?
.try_into()
@@ -182,18 +203,13 @@ where
/// Serialize secret key in the SEC1 ASN.1 DER `ECPrivateKey` format.
#[cfg(all(feature = "alloc", feature = "arithmetic", feature = "sec1"))]
- #[cfg_attr(
- docsrs,
- doc(cfg(all(feature = "alloc", feature = "arithmetic", feature = "sec1")))
- )]
pub fn to_sec1_der(&self) -> der::Result<Zeroizing<Vec<u8>>>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
- // TODO(tarcieri): wrap `secret_key_bytes` in `Zeroizing`
- let mut private_key_bytes = self.to_be_bytes();
+ 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(
@@ -202,12 +218,9 @@ where
parameters: None,
public_key: Some(public_key_bytes.as_bytes()),
}
- .to_vec()?,
+ .to_der()?,
);
- // TODO(tarcieri): wrap `private_key_bytes` in `Zeroizing`
- private_key_bytes.zeroize();
-
Ok(ec_private_key)
}
@@ -219,11 +232,10 @@ where
/// -----BEGIN EC PRIVATE KEY-----
/// ```
#[cfg(feature = "pem")]
- #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
pub fn from_sec1_pem(s: &str) -> Result<Self>
where
C: Curve + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
let (label, der_bytes) = pem::decode_vec(s.as_bytes()).map_err(|_| Error)?;
@@ -231,7 +243,7 @@ where
return Err(Error);
}
- Self::from_sec1_der(&*der_bytes).map_err(|_| Error)
+ Self::from_sec1_der(&der_bytes).map_err(|_| Error)
}
/// Serialize private key as self-zeroizing PEM-encoded SEC1 `ECPrivateKey`
@@ -239,12 +251,11 @@ where
///
/// Pass `Default::default()` to use the OS's native line endings.
#[cfg(feature = "pem")]
- #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
- pub fn to_pem(&self, line_ending: pem::LineEnding) -> Result<Zeroizing<String>>
+ pub fn to_sec1_pem(&self, line_ending: pem::LineEnding) -> Result<Zeroizing<String>>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
self.to_sec1_der()
.ok()
@@ -255,48 +266,42 @@ where
/// Parse a [`JwkEcKey`] JSON Web Key (JWK) into a [`SecretKey`].
#[cfg(feature = "jwk")]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn from_jwk(jwk: &JwkEcKey) -> Result<Self>
where
C: JwkParameters + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
Self::try_from(jwk)
}
/// Parse a string containing a JSON Web Key (JWK) into a [`SecretKey`].
#[cfg(feature = "jwk")]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn from_jwk_str(jwk: &str) -> Result<Self>
where
C: JwkParameters + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ 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"))]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn to_jwk(&self) -> JwkEcKey
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
self.into()
}
/// Serialize this secret key as JSON Web Key (JWK) string.
#[cfg(all(feature = "arithmetic", feature = "jwk"))]
- #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
- #[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn to_jwk_string(&self) -> Zeroizing<String>
where
- C: Curve + JwkParameters + ProjectiveArithmetic,
+ C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
Zeroizing::new(self.to_jwk().to_string())
}
@@ -316,8 +321,8 @@ where
C: Curve,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // TODO(tarcieri): use `debug_struct` and `finish_non_exhaustive` when stable
- write!(f, "SecretKey<{:?}>{{ ... }}", C::default())
+ f.debug_struct(core::any::type_name::<Self>())
+ .finish_non_exhaustive()
}
}
@@ -344,16 +349,15 @@ where
}
#[cfg(all(feature = "sec1"))]
-#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> TryFrom<sec1::EcPrivateKey<'_>> for SecretKey<C>
where
C: Curve + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Error = der::Error;
fn try_from(sec1_private_key: sec1::EcPrivateKey<'_>) -> der::Result<Self> {
- let secret_key = Self::from_be_bytes(sec1_private_key.private_key)
+ 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`?
@@ -371,10 +375,9 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
impl<C> From<NonZeroScalar<C>> for SecretKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
fn from(scalar: NonZeroScalar<C>) -> SecretKey<C> {
SecretKey::from(&scalar)
@@ -382,10 +385,9 @@ where
}
#[cfg(feature = "arithmetic")]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
impl<C> From<&NonZeroScalar<C>> for SecretKey<C>
where
- C: Curve + ProjectiveArithmetic,
+ C: CurveArithmetic,
{
fn from(scalar: &NonZeroScalar<C>) -> SecretKey<C> {
SecretKey {
diff --git a/vendor/elliptic-curve/src/secret_key/pkcs8.rs b/vendor/elliptic-curve/src/secret_key/pkcs8.rs
index 3c1a509bf..92c81f18a 100644
--- a/vendor/elliptic-curve/src/secret_key/pkcs8.rs
+++ b/vendor/elliptic-curve/src/secret_key/pkcs8.rs
@@ -2,22 +2,21 @@
use super::SecretKey;
use crate::{
- pkcs8::{self, AssociatedOid, DecodePrivateKey},
+ pkcs8::{self, der::Decode, AssociatedOid},
sec1::{ModulusSize, ValidatePublicKey},
- Curve, FieldSize, ALGORITHM_OID,
+ Curve, FieldBytesSize, ALGORITHM_OID,
};
-use der::Decode;
+use pkcs8::spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier, ObjectIdentifier};
use sec1::EcPrivateKey;
// Imports for the `EncodePrivateKey` impl
-// TODO(tarcieri): use weak activation of `pkcs8/alloc` for gating `EncodePrivateKey` impl
-#[cfg(all(feature = "arithmetic", feature = "pem"))]
+#[cfg(all(feature = "alloc", feature = "arithmetic"))]
use {
crate::{
sec1::{FromEncodedPoint, ToEncodedPoint},
- AffinePoint, ProjectiveArithmetic,
+ AffinePoint, CurveArithmetic,
},
- pkcs8::EncodePrivateKey,
+ pkcs8::{der, EncodePrivateKey},
};
// Imports for actual PEM support
@@ -25,13 +24,25 @@ use {
use {
crate::{error::Error, Result},
core::str::FromStr,
+ pkcs8::DecodePrivateKey,
};
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
+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: Curve + AssociatedOid + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ C: AssociatedOid + Curve + ValidatePublicKey,
+ FieldBytesSize<C>: ModulusSize,
{
type Error = pkcs8::Error;
@@ -45,28 +56,16 @@ where
}
}
-#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
-impl<C> DecodePrivateKey for SecretKey<C>
-where
- C: Curve + AssociatedOid + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
-{
-}
-
-// TODO(tarcieri): use weak activation of `pkcs8/alloc` for this when possible
-// It doesn't strictly depend on `pkcs8/pem` but we can't easily activate `pkcs8/alloc`
-// without adding a separate crate feature just for this functionality.
-#[cfg(all(feature = "arithmetic", feature = "pem"))]
-#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
+#[cfg(all(feature = "alloc", feature = "arithmetic"))]
impl<C> EncodePrivateKey for SecretKey<C>
where
- C: Curve + AssociatedOid + ProjectiveArithmetic,
+ C: AssociatedOid + CurveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
fn to_pkcs8_der(&self) -> pkcs8::Result<der::SecretDocument> {
- let algorithm_identifier = pkcs8::AlgorithmIdentifier {
+ // TODO(tarcieri): make `PrivateKeyInfo` generic around `Params`
+ let algorithm_identifier = pkcs8::AlgorithmIdentifierRef {
oid: ALGORITHM_OID,
parameters: Some((&C::OID).into()),
};
@@ -78,11 +77,10 @@ where
}
#[cfg(feature = "pem")]
-#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl<C> FromStr for SecretKey<C>
where
C: Curve + AssociatedOid + ValidatePublicKey,
- FieldSize<C>: ModulusSize,
+ FieldBytesSize<C>: ModulusSize,
{
type Err = Error;
diff --git a/vendor/elliptic-curve/src/voprf.rs b/vendor/elliptic-curve/src/voprf.rs
new file mode 100644
index 000000000..68f2abf18
--- /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;
+}