chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

59
vendor/p256/src/arithmetic.rs vendored Normal file
View File

@@ -0,0 +1,59 @@
//! Pure Rust implementation of group operations on secp256r1.
//!
//! Curve parameters can be found in [NIST SP 800-186] § G.1.2: Curve P-256.
//!
//! [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final
pub(crate) mod field;
#[cfg(feature = "hash2curve")]
mod hash2curve;
pub(crate) mod scalar;
pub(crate) mod util;
use self::{field::FieldElement, scalar::Scalar};
use crate::NistP256;
use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic};
use primeorder::{point_arithmetic, PrimeCurveParams};
/// Elliptic curve point in affine coordinates.
pub type AffinePoint = primeorder::AffinePoint<NistP256>;
/// Elliptic curve point in projective coordinates.
pub type ProjectivePoint = primeorder::ProjectivePoint<NistP256>;
impl CurveArithmetic for NistP256 {
type AffinePoint = AffinePoint;
type ProjectivePoint = ProjectivePoint;
type Scalar = Scalar;
}
impl PrimeCurveArithmetic for NistP256 {
type CurveGroup = ProjectivePoint;
}
/// Adapted from [NIST SP 800-186] § G.1.2: Curve P-256.
///
/// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final
impl PrimeCurveParams for NistP256 {
type FieldElement = FieldElement;
type PointArithmetic = point_arithmetic::EquationAIsMinusThree;
/// a = -3
const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg();
const EQUATION_B: FieldElement =
FieldElement::from_hex("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b");
/// Base point of P-256.
///
/// Defined in NIST SP 800-186 § G.1.2:
///
/// ```text
/// Gₓ = 6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296
/// Gᵧ = 4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5
/// ```
const GENERATOR: (FieldElement, FieldElement) = (
FieldElement::from_hex("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"),
FieldElement::from_hex("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"),
);
}

309
vendor/p256/src/arithmetic/field.rs vendored Normal file
View File

@@ -0,0 +1,309 @@
//! Field arithmetic modulo p = 2^{224}(2^{32} 1) + 2^{192} + 2^{96} 1
#![allow(clippy::assign_op_pattern, clippy::op_ref)]
#[cfg_attr(target_pointer_width = "32", path = "field/field32.rs")]
#[cfg_attr(target_pointer_width = "64", path = "field/field64.rs")]
mod field_impl;
use self::field_impl::*;
use crate::{FieldBytes, NistP256};
use core::{
fmt::{self, Debug},
iter::{Product, Sum},
ops::{AddAssign, Mul, MulAssign, Neg, SubAssign},
};
use elliptic_curve::{
bigint::U256,
ff::PrimeField,
subtle::{Choice, ConstantTimeEq, CtOption},
};
/// Field modulus serialized as hex.
/// p = 2^{224}(2^{32} 1) + 2^{192} + 2^{96} 1
const MODULUS_HEX: &str = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff";
/// Constant representing the modulus.
pub const MODULUS: U256 = U256::from_be_hex(MODULUS_HEX);
/// R^2 = 2^512 mod p
const R_2: U256 =
U256::from_be_hex("00000004fffffffdfffffffffffffffefffffffbffffffff0000000000000003");
/// An element in the finite field modulo p = 2^{224}(2^{32} 1) + 2^{192} + 2^{96} 1.
///
/// The internal representation is in little-endian order. Elements are always in
/// Montgomery form; i.e., FieldElement(a) = aR mod p, with R = 2^256.
#[derive(Clone, Copy)]
pub struct FieldElement(pub(crate) U256);
primeorder::impl_mont_field_element!(
NistP256,
FieldElement,
FieldBytes,
U256,
MODULUS,
Fe,
fe_from_montgomery,
fe_to_montgomery,
fe_add,
fe_sub,
fe_mul,
fe_neg,
fe_square
);
impl FieldElement {
/// Returns the multiplicative inverse of self, if self is non-zero.
pub fn invert(&self) -> CtOption<Self> {
CtOption::new(self.invert_unchecked(), !self.is_zero())
}
/// Returns the multiplicative inverse of self.
///
/// Does not check that self is non-zero.
const fn invert_unchecked(&self) -> Self {
// We need to find b such that b * a ≡ 1 mod p. As we are in a prime
// field, we can apply Fermat's Little Theorem:
//
// a^p ≡ a mod p
// a^(p-1) ≡ 1 mod p
// a^(p-2) * a ≡ 1 mod p
//
// Thus inversion can be implemented with a single exponentiation.
let t111 = self.multiply(&self.multiply(&self.square()).square());
let t111111 = t111.multiply(&t111.sqn(3));
let x15 = t111111.sqn(6).multiply(&t111111).sqn(3).multiply(&t111);
let x16 = x15.square().multiply(self);
let i53 = x16.sqn(16).multiply(&x16).sqn(15);
let x47 = x15.multiply(&i53);
x47.multiply(&i53.sqn(17).multiply(self).sqn(143).multiply(&x47).sqn(47))
.sqn(2)
.multiply(self)
}
/// Returns the square root of self mod p, or `None` if no square root exists.
pub fn sqrt(&self) -> CtOption<Self> {
// We need to find alpha such that alpha^2 = beta mod p. For secp256r1,
// p ≡ 3 mod 4. By Euler's Criterion, beta^(p-1)/2 ≡ 1 mod p. So:
//
// alpha^2 = beta beta^((p - 1) / 2) mod p ≡ beta^((p + 1) / 2) mod p
// alpha = ± beta^((p + 1) / 4) mod p
//
// Thus sqrt can be implemented with a single exponentiation.
let t11 = self.mul(&self.square());
let t1111 = t11.mul(&t11.sqn(2));
let t11111111 = t1111.mul(&t1111.sqn(4));
let x16 = t11111111.sqn(8).mul(&t11111111);
let sqrt = x16
.sqn(16)
.mul(&x16)
.sqn(32)
.mul(self)
.sqn(96)
.mul(self)
.sqn(94);
CtOption::new(
sqrt,
(&sqrt * &sqrt).ct_eq(self), // Only return Some if it's the square root.
)
}
/// Returns self^(2^n) mod p
const fn sqn(&self, n: usize) -> Self {
let mut x = *self;
let mut i = 0;
while i < n {
x = x.square();
i += 1;
}
x
}
}
impl PrimeField for FieldElement {
type Repr = FieldBytes;
const MODULUS: &'static str = MODULUS_HEX;
const NUM_BITS: u32 = 256;
const CAPACITY: u32 = 255;
const TWO_INV: Self = Self::from_u64(2).invert_unchecked();
const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(6);
const S: u32 = 1;
const ROOT_OF_UNITY: Self =
Self::from_hex("ffffffff00000001000000000000000000000000fffffffffffffffffffffffe");
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
const DELTA: Self = Self::from_u64(36);
#[inline]
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
Self::from_bytes(&bytes)
}
#[inline]
fn to_repr(&self) -> FieldBytes {
self.to_bytes()
}
#[inline]
fn is_odd(&self) -> Choice {
self.is_odd()
}
}
impl Debug for FieldElement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "FieldElement(0x{:X})", &self.0)
}
}
#[cfg(test)]
mod tests {
use super::FieldElement;
use crate::{test_vectors::field::DBL_TEST_VECTORS, FieldBytes};
use elliptic_curve::{bigint::U256, ff::PrimeField};
use primeorder::{
impl_field_identity_tests, impl_field_invert_tests, impl_field_sqrt_tests,
impl_primefield_tests,
};
use proptest::{num, prelude::*};
/// t = (modulus - 1) >> S
const T: [u64; 4] = [
0xffffffffffffffff,
0x000000007fffffff,
0x8000000000000000,
0x7fffffff80000000,
];
impl_field_identity_tests!(FieldElement);
impl_field_invert_tests!(FieldElement);
impl_field_sqrt_tests!(FieldElement);
impl_primefield_tests!(FieldElement, T);
#[test]
fn from_bytes() {
assert_eq!(
FieldElement::from_bytes(&FieldBytes::default()).unwrap(),
FieldElement::ZERO
);
assert_eq!(
FieldElement::from_bytes(
&[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1
]
.into()
)
.unwrap(),
FieldElement::ONE
);
assert!(bool::from(
FieldElement::from_bytes(&[0xff; 32].into()).is_none()
));
}
#[test]
fn to_bytes() {
assert_eq!(FieldElement::ZERO.to_bytes(), FieldBytes::default());
assert_eq!(
FieldElement::ONE.to_bytes(),
[
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1
]
.into()
);
}
#[test]
fn repeated_add() {
let mut r = FieldElement::ONE;
for i in 0..DBL_TEST_VECTORS.len() {
assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into());
r = r + &r;
}
}
#[test]
fn repeated_double() {
let mut r = FieldElement::ONE;
for i in 0..DBL_TEST_VECTORS.len() {
assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into());
r = r.double();
}
}
#[test]
fn repeated_mul() {
let mut r = FieldElement::ONE;
let two = r + &r;
for i in 0..DBL_TEST_VECTORS.len() {
assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into());
r = r * &two;
}
}
#[test]
fn negation() {
let two = FieldElement::ONE.double();
let neg_two = -two;
assert_eq!(two + &neg_two, FieldElement::ZERO);
assert_eq!(-neg_two, two);
}
#[test]
fn pow_vartime() {
let one = FieldElement::ONE;
let two = one + &one;
let four = two.square();
assert_eq!(two.pow_vartime(&[2, 0, 0, 0]), four);
}
proptest! {
/// This checks behaviour well within the field ranges, because it doesn't set the
/// highest limb.
#[cfg(target_pointer_width = "32")]
#[test]
fn add_then_sub(
a0 in num::u32::ANY,
a1 in num::u32::ANY,
a2 in num::u32::ANY,
a3 in num::u32::ANY,
a4 in num::u32::ANY,
a5 in num::u32::ANY,
a6 in num::u32::ANY,
b0 in num::u32::ANY,
b1 in num::u32::ANY,
b2 in num::u32::ANY,
b3 in num::u32::ANY,
b4 in num::u32::ANY,
b5 in num::u32::ANY,
b6 in num::u32::ANY,
) {
let a = FieldElement(U256::from_words([a0, a1, a2, a3, a4, a5, a6, 0]));
let b = FieldElement(U256::from_words([b0, b1, b2, b3, b4, b5, b6, 0]));
assert_eq!(a.add(&b).sub(&a), b);
}
/// This checks behaviour well within the field ranges, because it doesn't set the
/// highest limb.
#[cfg(target_pointer_width = "64")]
#[test]
fn add_then_sub(
a0 in num::u64::ANY,
a1 in num::u64::ANY,
a2 in num::u64::ANY,
b0 in num::u64::ANY,
b1 in num::u64::ANY,
b2 in num::u64::ANY,
) {
let a = FieldElement(U256::from_words([a0, a1, a2, 0]));
let b = FieldElement(U256::from_words([b0, b1, b2, 0]));
assert_eq!(a.add(&b).sub(&a), b);
}
}
}

View File

@@ -0,0 +1,206 @@
//! 32-bit secp256r1 base field implementation
// TODO(tarcieri): adapt 64-bit arithmetic to proper 32-bit arithmetic
use super::{MODULUS, R_2};
use crate::arithmetic::util::{adc, mac, sbb};
/// Raw field element.
pub type Fe = [u32; 8];
/// Translate a field element out of the Montgomery domain.
#[inline]
pub const fn fe_from_montgomery(w: &Fe) -> Fe {
let w = fe32_to_fe64(w);
montgomery_reduce(&[w[0], w[1], w[2], w[3], 0, 0, 0, 0])
}
/// Translate a field element into the Montgomery domain.
#[inline]
pub const fn fe_to_montgomery(w: &Fe) -> Fe {
fe_mul(w, R_2.as_words())
}
/// Returns `a + b mod p`.
pub const fn fe_add(a: &Fe, b: &Fe) -> Fe {
let a = fe32_to_fe64(a);
let b = fe32_to_fe64(b);
// Bit 256 of p is set, so addition can result in five words.
let (w0, carry) = adc(a[0], b[0], 0);
let (w1, carry) = adc(a[1], b[1], carry);
let (w2, carry) = adc(a[2], b[2], carry);
let (w3, w4) = adc(a[3], b[3], carry);
// Attempt to subtract the modulus, to ensure the result is in the field.
let modulus = fe32_to_fe64(MODULUS.as_words());
sub_inner(
&[w0, w1, w2, w3, w4],
&[modulus[0], modulus[1], modulus[2], modulus[3], 0],
)
}
/// Returns `a - b mod p`.
pub const fn fe_sub(a: &Fe, b: &Fe) -> Fe {
let a = fe32_to_fe64(a);
let b = fe32_to_fe64(b);
sub_inner(&[a[0], a[1], a[2], a[3], 0], &[b[0], b[1], b[2], b[3], 0])
}
/// Returns `a * b mod p`.
pub const fn fe_mul(a: &Fe, b: &Fe) -> Fe {
let a = fe32_to_fe64(a);
let b = fe32_to_fe64(b);
let (w0, carry) = mac(0, a[0], b[0], 0);
let (w1, carry) = mac(0, a[0], b[1], carry);
let (w2, carry) = mac(0, a[0], b[2], carry);
let (w3, w4) = mac(0, a[0], b[3], carry);
let (w1, carry) = mac(w1, a[1], b[0], 0);
let (w2, carry) = mac(w2, a[1], b[1], carry);
let (w3, carry) = mac(w3, a[1], b[2], carry);
let (w4, w5) = mac(w4, a[1], b[3], carry);
let (w2, carry) = mac(w2, a[2], b[0], 0);
let (w3, carry) = mac(w3, a[2], b[1], carry);
let (w4, carry) = mac(w4, a[2], b[2], carry);
let (w5, w6) = mac(w5, a[2], b[3], carry);
let (w3, carry) = mac(w3, a[3], b[0], 0);
let (w4, carry) = mac(w4, a[3], b[1], carry);
let (w5, carry) = mac(w5, a[3], b[2], carry);
let (w6, w7) = mac(w6, a[3], b[3], carry);
montgomery_reduce(&[w0, w1, w2, w3, w4, w5, w6, w7])
}
/// Returns `-w mod p`.
pub const fn fe_neg(w: &Fe) -> Fe {
fe_sub(&[0; 8], w)
}
/// Returns `w * w mod p`.
pub const fn fe_square(w: &Fe) -> Fe {
fe_mul(w, w)
}
/// Montgomery Reduction
///
/// The general algorithm is:
/// ```text
/// A <- input (2n b-limbs)
/// for i in 0..n {
/// k <- A[i] p' mod b
/// A <- A + k p b^i
/// }
/// A <- A / b^n
/// if A >= p {
/// A <- A - p
/// }
/// ```
///
/// For secp256r1, we have the following simplifications:
///
/// - `p'` is 1, so our multiplicand is simply the first limb of the intermediate A.
///
/// - The first limb of p is 2^64 - 1; multiplications by this limb can be simplified
/// to a shift and subtraction:
/// ```text
/// a_i * (2^64 - 1) = a_i * 2^64 - a_i = (a_i << 64) - a_i
/// ```
/// However, because `p' = 1`, the first limb of p is multiplied by limb i of the
/// intermediate A and then immediately added to that same limb, so we simply
/// initialize the carry to limb i of the intermediate.
///
/// - The third limb of p is zero, so we can ignore any multiplications by it and just
/// add the carry.
///
/// References:
/// - Handbook of Applied Cryptography, Chapter 14
/// Algorithm 14.32
/// http://cacr.uwaterloo.ca/hac/about/chap14.pdf
///
/// - Efficient and Secure Elliptic Curve Cryptography Implementation of Curve P-256
/// Algorithm 7) Montgomery Word-by-Word Reduction
/// https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf
#[inline]
#[allow(clippy::too_many_arguments)]
const fn montgomery_reduce(r: &[u64; 8]) -> Fe {
let r0 = r[0];
let r1 = r[1];
let r2 = r[2];
let r3 = r[3];
let r4 = r[4];
let r5 = r[5];
let r6 = r[6];
let r7 = r[7];
let modulus = fe32_to_fe64(MODULUS.as_words());
let (r1, carry) = mac(r1, r0, modulus[1], r0);
let (r2, carry) = adc(r2, 0, carry);
let (r3, carry) = mac(r3, r0, modulus[3], carry);
let (r4, carry2) = adc(r4, 0, carry);
let (r2, carry) = mac(r2, r1, modulus[1], r1);
let (r3, carry) = adc(r3, 0, carry);
let (r4, carry) = mac(r4, r1, modulus[3], carry);
let (r5, carry2) = adc(r5, carry2, carry);
let (r3, carry) = mac(r3, r2, modulus[1], r2);
let (r4, carry) = adc(r4, 0, carry);
let (r5, carry) = mac(r5, r2, modulus[3], carry);
let (r6, carry2) = adc(r6, carry2, carry);
let (r4, carry) = mac(r4, r3, modulus[1], r3);
let (r5, carry) = adc(r5, 0, carry);
let (r6, carry) = mac(r6, r3, modulus[3], carry);
let (r7, r8) = adc(r7, carry2, carry);
// Result may be within MODULUS of the correct value
sub_inner(
&[r4, r5, r6, r7, r8],
&[modulus[0], modulus[1], modulus[2], modulus[3], 0],
)
}
#[inline]
#[allow(clippy::too_many_arguments)]
const fn sub_inner(l: &[u64; 5], r: &[u64; 5]) -> Fe {
let (w0, borrow) = sbb(l[0], r[0], 0);
let (w1, borrow) = sbb(l[1], r[1], borrow);
let (w2, borrow) = sbb(l[2], r[2], borrow);
let (w3, borrow) = sbb(l[3], r[3], borrow);
let (_, borrow) = sbb(l[4], r[4], borrow);
// If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise
// borrow = 0x000...000. Thus, we use it as a mask to conditionally add the
// modulus.
let modulus = fe32_to_fe64(MODULUS.as_words());
let (w0, carry) = adc(w0, modulus[0] & borrow, 0);
let (w1, carry) = adc(w1, modulus[1] & borrow, carry);
let (w2, carry) = adc(w2, modulus[2] & borrow, carry);
let (w3, _) = adc(w3, modulus[3] & borrow, carry);
[
(w0 & 0xFFFFFFFF) as u32,
(w0 >> 32) as u32,
(w1 & 0xFFFFFFFF) as u32,
(w1 >> 32) as u32,
(w2 & 0xFFFFFFFF) as u32,
(w2 >> 32) as u32,
(w3 & 0xFFFFFFFF) as u32,
(w3 >> 32) as u32,
]
}
// TODO(tarcieri): replace this with proper 32-bit arithmetic
#[inline]
const fn fe32_to_fe64(fe32: &Fe) -> [u64; 4] {
[
(fe32[0] as u64) | ((fe32[1] as u64) << 32),
(fe32[2] as u64) | ((fe32[3] as u64) << 32),
(fe32[4] as u64) | ((fe32[5] as u64) << 32),
(fe32[6] as u64) | ((fe32[7] as u64) << 32),
]
}

View File

@@ -0,0 +1,175 @@
//! 64-bit secp256r1 base field implementation
use super::{MODULUS, R_2};
use crate::arithmetic::util::{adc, mac, sbb};
/// Raw field element.
pub type Fe = [u64; 4];
/// Translate a field element out of the Montgomery domain.
#[inline]
pub const fn fe_from_montgomery(w: &Fe) -> Fe {
montgomery_reduce(&[w[0], w[1], w[2], w[3], 0, 0, 0, 0])
}
/// Translate a field element into the Montgomery domain.
#[inline]
pub const fn fe_to_montgomery(w: &Fe) -> Fe {
fe_mul(w, R_2.as_words())
}
/// Returns `a + b mod p`.
pub const fn fe_add(a: &Fe, b: &Fe) -> Fe {
// Bit 256 of p is set, so addition can result in five words.
let (w0, carry) = adc(a[0], b[0], 0);
let (w1, carry) = adc(a[1], b[1], carry);
let (w2, carry) = adc(a[2], b[2], carry);
let (w3, w4) = adc(a[3], b[3], carry);
// Attempt to subtract the modulus, to ensure the result is in the field.
let modulus = MODULUS.as_words();
sub_inner(
&[w0, w1, w2, w3, w4],
&[modulus[0], modulus[1], modulus[2], modulus[3], 0],
)
}
/// Returns `a - b mod p`.
pub const fn fe_sub(a: &Fe, b: &Fe) -> Fe {
sub_inner(&[a[0], a[1], a[2], a[3], 0], &[b[0], b[1], b[2], b[3], 0])
}
/// Returns `a * b mod p`.
pub const fn fe_mul(a: &Fe, b: &Fe) -> Fe {
let (w0, carry) = mac(0, a[0], b[0], 0);
let (w1, carry) = mac(0, a[0], b[1], carry);
let (w2, carry) = mac(0, a[0], b[2], carry);
let (w3, w4) = mac(0, a[0], b[3], carry);
let (w1, carry) = mac(w1, a[1], b[0], 0);
let (w2, carry) = mac(w2, a[1], b[1], carry);
let (w3, carry) = mac(w3, a[1], b[2], carry);
let (w4, w5) = mac(w4, a[1], b[3], carry);
let (w2, carry) = mac(w2, a[2], b[0], 0);
let (w3, carry) = mac(w3, a[2], b[1], carry);
let (w4, carry) = mac(w4, a[2], b[2], carry);
let (w5, w6) = mac(w5, a[2], b[3], carry);
let (w3, carry) = mac(w3, a[3], b[0], 0);
let (w4, carry) = mac(w4, a[3], b[1], carry);
let (w5, carry) = mac(w5, a[3], b[2], carry);
let (w6, w7) = mac(w6, a[3], b[3], carry);
montgomery_reduce(&[w0, w1, w2, w3, w4, w5, w6, w7])
}
/// Returns `-w mod p`.
pub const fn fe_neg(w: &Fe) -> Fe {
fe_sub(&[0, 0, 0, 0], w)
}
/// Returns `w * w mod p`.
pub const fn fe_square(w: &Fe) -> Fe {
fe_mul(w, w)
}
/// Montgomery Reduction
///
/// The general algorithm is:
/// ```text
/// A <- input (2n b-limbs)
/// for i in 0..n {
/// k <- A[i] p' mod b
/// A <- A + k p b^i
/// }
/// A <- A / b^n
/// if A >= p {
/// A <- A - p
/// }
/// ```
///
/// For secp256r1, we have the following simplifications:
///
/// - `p'` is 1, so our multiplicand is simply the first limb of the intermediate A.
///
/// - The first limb of p is 2^64 - 1; multiplications by this limb can be simplified
/// to a shift and subtraction:
/// ```text
/// a_i * (2^64 - 1) = a_i * 2^64 - a_i = (a_i << 64) - a_i
/// ```
/// However, because `p' = 1`, the first limb of p is multiplied by limb i of the
/// intermediate A and then immediately added to that same limb, so we simply
/// initialize the carry to limb i of the intermediate.
///
/// - The third limb of p is zero, so we can ignore any multiplications by it and just
/// add the carry.
///
/// References:
/// - Handbook of Applied Cryptography, Chapter 14
/// Algorithm 14.32
/// http://cacr.uwaterloo.ca/hac/about/chap14.pdf
///
/// - Efficient and Secure Elliptic Curve Cryptography Implementation of Curve P-256
/// Algorithm 7) Montgomery Word-by-Word Reduction
/// https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf
#[inline]
#[allow(clippy::too_many_arguments)]
const fn montgomery_reduce(r: &[u64; 8]) -> Fe {
let r0 = r[0];
let r1 = r[1];
let r2 = r[2];
let r3 = r[3];
let r4 = r[4];
let r5 = r[5];
let r6 = r[6];
let r7 = r[7];
let modulus = MODULUS.as_words();
let (r1, carry) = mac(r1, r0, modulus[1], r0);
let (r2, carry) = adc(r2, 0, carry);
let (r3, carry) = mac(r3, r0, modulus[3], carry);
let (r4, carry2) = adc(r4, 0, carry);
let (r2, carry) = mac(r2, r1, modulus[1], r1);
let (r3, carry) = adc(r3, 0, carry);
let (r4, carry) = mac(r4, r1, modulus[3], carry);
let (r5, carry2) = adc(r5, carry2, carry);
let (r3, carry) = mac(r3, r2, modulus[1], r2);
let (r4, carry) = adc(r4, 0, carry);
let (r5, carry) = mac(r5, r2, modulus[3], carry);
let (r6, carry2) = adc(r6, carry2, carry);
let (r4, carry) = mac(r4, r3, modulus[1], r3);
let (r5, carry) = adc(r5, 0, carry);
let (r6, carry) = mac(r6, r3, modulus[3], carry);
let (r7, r8) = adc(r7, carry2, carry);
// Result may be within MODULUS of the correct value
sub_inner(
&[r4, r5, r6, r7, r8],
&[modulus[0], modulus[1], modulus[2], modulus[3], 0],
)
}
#[inline]
#[allow(clippy::too_many_arguments)]
const fn sub_inner(l: &[u64; 5], r: &[u64; 5]) -> Fe {
let (w0, borrow) = sbb(l[0], r[0], 0);
let (w1, borrow) = sbb(l[1], r[1], borrow);
let (w2, borrow) = sbb(l[2], r[2], borrow);
let (w3, borrow) = sbb(l[3], r[3], borrow);
let (_, borrow) = sbb(l[4], r[4], borrow);
// If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise
// borrow = 0x000...000. Thus, we use it as a mask to conditionally add the
// modulus.
let modulus = MODULUS.as_words();
let (w0, carry) = adc(w0, modulus[0] & borrow, 0);
let (w1, carry) = adc(w1, modulus[1] & borrow, carry);
let (w2, carry) = adc(w2, modulus[2] & borrow, carry);
let (w3, _) = adc(w3, modulus[3] & borrow, carry);
[w0, w1, w2, w3]
}

320
vendor/p256/src/arithmetic/hash2curve.rs vendored Normal file
View File

@@ -0,0 +1,320 @@
use super::FieldElement;
use crate::{AffinePoint, FieldBytes, NistP256, ProjectivePoint, Scalar};
use elliptic_curve::{
bigint::{ArrayEncoding, U256},
consts::U48,
generic_array::GenericArray,
hash2curve::{FromOkm, GroupDigest, MapToCurve, OsswuMap, OsswuMapParams, Sgn0},
point::DecompressPoint,
subtle::Choice,
};
impl GroupDigest for NistP256 {
type FieldElement = FieldElement;
}
impl FromOkm for FieldElement {
type Length = U48;
fn from_okm(data: &GenericArray<u8, Self::Length>) -> Self {
const F_2_192: FieldElement = FieldElement(U256::from_be_hex(
"00000000000000030000000200000000fffffffffffffffefffffffeffffffff",
));
let mut d0_bytes = FieldBytes::default();
d0_bytes[8..].copy_from_slice(&data[..24]);
let d0 = FieldElement::from_uint_unchecked(U256::from_be_byte_array(d0_bytes));
let mut d1_bytes = FieldBytes::default();
d1_bytes[8..].copy_from_slice(&data[24..]);
let d1 = FieldElement::from_uint_unchecked(U256::from_be_byte_array(d1_bytes));
d0 * F_2_192 + d1
}
}
impl Sgn0 for FieldElement {
fn sgn0(&self) -> Choice {
self.is_odd()
}
}
impl OsswuMap for FieldElement {
const PARAMS: OsswuMapParams<Self> = OsswuMapParams {
c1: &[
0xffff_ffff_ffff_ffff,
0x0000_0000_3fff_ffff,
0x4000_0000_0000_0000,
0x3fff_ffff_c000_0000,
],
c2: FieldElement(U256::from_be_hex(
"a3323851ba997e271ac5d59c3298bf50b2806c63966a1a6653e43951f64fdbe7",
)),
map_a: FieldElement(U256::from_be_hex(
"fffffffc00000004000000000000000000000003fffffffffffffffffffffffc",
)),
map_b: FieldElement(U256::from_be_hex(
"dc30061d04874834e5a220abf7212ed6acf005cd78843090d89cdf6229c4bddf",
)),
z: FieldElement(U256::from_be_hex(
"fffffff50000000b00000000000000000000000afffffffffffffffffffffff5",
)),
};
}
impl MapToCurve for FieldElement {
type Output = ProjectivePoint;
fn map_to_curve(&self) -> Self::Output {
let (qx, qy) = self.osswu();
// TODO(tarcieri): assert that `qy` is correct? less circuitous conversion?
AffinePoint::decompress(&qx.to_bytes(), qy.is_odd())
.unwrap()
.into()
}
}
impl FromOkm for Scalar {
type Length = U48;
fn from_okm(data: &GenericArray<u8, Self::Length>) -> Self {
const F_2_192: Scalar = Scalar(U256::from_be_hex(
"0000000000000001000000000000000000000000000000000000000000000000",
));
let mut d0 = GenericArray::default();
d0[8..].copy_from_slice(&data[0..24]);
let d0 = Scalar(U256::from_be_byte_array(d0));
let mut d1 = GenericArray::default();
d1[8..].copy_from_slice(&data[24..]);
let d1 = Scalar(U256::from_be_byte_array(d1));
d0 * F_2_192 + d1
}
}
#[cfg(test)]
mod tests {
use crate::{FieldElement, NistP256, Scalar, U256};
use elliptic_curve::{
bigint::{ArrayEncoding, NonZero, U384},
consts::U48,
generic_array::GenericArray,
group::cofactor::CofactorGroup,
hash2curve::{self, ExpandMsgXmd, FromOkm, GroupDigest, MapToCurve},
sec1::{self, ToEncodedPoint},
Curve, Field,
};
use hex_literal::hex;
use proptest::{num::u64::ANY, prelude::ProptestConfig, proptest};
use sha2::Sha256;
#[allow(dead_code)] // TODO(tarcieri): fix commented out code
#[test]
fn hash_to_curve() {
struct TestVector {
msg: &'static [u8],
p_x: [u8; 32],
p_y: [u8; 32],
u_0: [u8; 32],
u_1: [u8; 32],
q0_x: [u8; 32],
q0_y: [u8; 32],
q1_x: [u8; 32],
q1_y: [u8; 32],
}
const DST: &[u8] = b"QUUX-V01-CS02-with-P256_XMD:SHA-256_SSWU_RO_";
const TEST_VECTORS: &[TestVector] = &[
TestVector {
msg: b"",
p_x: hex!("2c15230b26dbc6fc9a37051158c95b79656e17a1a920b11394ca91c44247d3e4"),
p_y: hex!("8a7a74985cc5c776cdfe4b1f19884970453912e9d31528c060be9ab5c43e8415"),
u_0: hex!("ad5342c66a6dd0ff080df1da0ea1c04b96e0330dd89406465eeba11582515009"),
u_1: hex!("8c0f1d43204bd6f6ea70ae8013070a1518b43873bcd850aafa0a9e220e2eea5a"),
q0_x: hex!("ab640a12220d3ff283510ff3f4b1953d09fad35795140b1c5d64f313967934d5"),
q0_y: hex!("dccb558863804a881d4fff3455716c836cef230e5209594ddd33d85c565b19b1"),
q1_x: hex!("51cce63c50d972a6e51c61334f0f4875c9ac1cd2d3238412f84e31da7d980ef5"),
q1_y: hex!("b45d1a36d00ad90e5ec7840a60a4de411917fbe7c82c3949a6e699e5a1b66aac"),
},
TestVector {
msg: b"abc",
p_x: hex!("0bb8b87485551aa43ed54f009230450b492fead5f1cc91658775dac4a3388a0f"),
p_y: hex!("5c41b3d0731a27a7b14bc0bf0ccded2d8751f83493404c84a88e71ffd424212e"),
u_0: hex!("afe47f2ea2b10465cc26ac403194dfb68b7f5ee865cda61e9f3e07a537220af1"),
u_1: hex!("379a27833b0bfe6f7bdca08e1e83c760bf9a338ab335542704edcd69ce9e46e0"),
q0_x: hex!("5219ad0ddef3cc49b714145e91b2f7de6ce0a7a7dc7406c7726c7e373c58cb48"),
q0_y: hex!("7950144e52d30acbec7b624c203b1996c99617d0b61c2442354301b191d93ecf"),
q1_x: hex!("019b7cb4efcfeaf39f738fe638e31d375ad6837f58a852d032ff60c69ee3875f"),
q1_y: hex!("589a62d2b22357fed5449bc38065b760095ebe6aeac84b01156ee4252715446e"),
},
TestVector {
msg: b"abcdef0123456789",
p_x: hex!("65038ac8f2b1def042a5df0b33b1f4eca6bff7cb0f9c6c1526811864e544ed80"),
p_y: hex!("cad44d40a656e7aff4002a8de287abc8ae0482b5ae825822bb870d6df9b56ca3"),
u_0: hex!("0fad9d125a9477d55cf9357105b0eb3a5c4259809bf87180aa01d651f53d312c"),
u_1: hex!("b68597377392cd3419d8fcc7d7660948c8403b19ea78bbca4b133c9d2196c0fb"),
q0_x: hex!("a17bdf2965eb88074bc01157e644ed409dac97cfcf0c61c998ed0fa45e79e4a2"),
q0_y: hex!("4f1bc80c70d411a3cc1d67aeae6e726f0f311639fee560c7f5a664554e3c9c2e"),
q1_x: hex!("7da48bb67225c1a17d452c983798113f47e438e4202219dd0715f8419b274d66"),
q1_y: hex!("b765696b2913e36db3016c47edb99e24b1da30e761a8a3215dc0ec4d8f96e6f9"),
},
TestVector {
msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
p_x: hex!("4be61ee205094282ba8a2042bcb48d88dfbb609301c49aa8b078533dc65a0b5d"),
p_y: hex!("98f8df449a072c4721d241a3b1236d3caccba603f916ca680f4539d2bfb3c29e"),
u_0: hex!("3bbc30446f39a7befad080f4d5f32ed116b9534626993d2cc5033f6f8d805919"),
u_1: hex!("76bb02db019ca9d3c1e02f0c17f8baf617bbdae5c393a81d9ce11e3be1bf1d33"),
q0_x: hex!("c76aaa823aeadeb3f356909cb08f97eee46ecb157c1f56699b5efebddf0e6398"),
q0_y: hex!("776a6f45f528a0e8d289a4be12c4fab80762386ec644abf2bffb9b627e4352b1"),
q1_x: hex!("418ac3d85a5ccc4ea8dec14f750a3a9ec8b85176c95a7022f391826794eb5a75"),
q1_y: hex!("fd6604f69e9d9d2b74b072d14ea13050db72c932815523305cb9e807cc900aff"),
},
TestVector {
msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
p_x: hex!("457ae2981f70ca85d8e24c308b14db22f3e3862c5ea0f652ca38b5e49cd64bc5"),
p_y: hex!("ecb9f0eadc9aeed232dabc53235368c1394c78de05dd96893eefa62b0f4757dc"),
u_0: hex!("4ebc95a6e839b1ae3c63b847798e85cb3c12d3817ec6ebc10af6ee51adb29fec"),
u_1: hex!("4e21af88e22ea80156aff790750121035b3eefaa96b425a8716e0d20b4e269ee"),
q0_x: hex!("d88b989ee9d1295df413d4456c5c850b8b2fb0f5402cc5c4c7e815412e926db8"),
q0_y: hex!("bb4a1edeff506cf16def96afff41b16fc74f6dbd55c2210e5b8f011ba32f4f40"),
q1_x: hex!("a281e34e628f3a4d2a53fa87ff973537d68ad4fbc28d3be5e8d9f6a2571c5a4b"),
q1_y: hex!("f6ed88a7aab56a488100e6f1174fa9810b47db13e86be999644922961206e184"),
},
];
for test_vector in TEST_VECTORS {
// in parts
let mut u = [FieldElement::default(), FieldElement::default()];
hash2curve::hash_to_field::<ExpandMsgXmd<Sha256>, FieldElement>(
&[test_vector.msg],
&[DST],
&mut u,
)
.unwrap();
/// Assert that the provided projective point matches the given test vector.
// TODO(tarcieri): use coordinate APIs. See zkcrypto/group#30
macro_rules! assert_point_eq {
($actual:expr, $expected_x:expr, $expected_y:expr) => {
let point = $actual.to_affine().to_encoded_point(false);
let (actual_x, actual_y) = match point.coordinates() {
sec1::Coordinates::Uncompressed { x, y } => (x, y),
_ => unreachable!(),
};
assert_eq!(&$expected_x, actual_x.as_slice());
assert_eq!(&$expected_y, actual_y.as_slice());
};
}
assert_eq!(u[0].to_bytes().as_slice(), test_vector.u_0);
assert_eq!(u[1].to_bytes().as_slice(), test_vector.u_1);
let q0 = u[0].map_to_curve();
assert_point_eq!(q0, test_vector.q0_x, test_vector.q0_y);
let q1 = u[1].map_to_curve();
assert_point_eq!(q1, test_vector.q1_x, test_vector.q1_y);
let p = q0.clear_cofactor() + q1.clear_cofactor();
assert_point_eq!(p, test_vector.p_x, test_vector.p_y);
// complete run
let pt = NistP256::hash_from_bytes::<ExpandMsgXmd<Sha256>>(&[test_vector.msg], &[DST])
.unwrap();
assert_point_eq!(pt, test_vector.p_x, test_vector.p_y);
}
}
/// Taken from <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-16.html#name-oprfp-256-sha-256-2>.
#[test]
fn hash_to_scalar_voprf() {
struct TestVector {
dst: &'static [u8],
key_info: &'static [u8],
seed: &'static [u8],
sk_sm: &'static [u8],
}
const TEST_VECTORS: &[TestVector] = &[
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x00\x00\x03",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("274d7747cf2e26352ecea6bd768c426087da3dfcd466b6841b441ada8412fb33"),
},
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x01\x00\x03",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("b3d12edba73e40401fdc27c0094a56337feb3646d1633345af7e7142a6b1559d"),
},
TestVector {
dst: b"DeriveKeyPairVOPRF10-\x02\x00\x03",
key_info: b"test key",
seed: &hex!("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3"),
sk_sm: &hex!("59519f6c7da344f340ad35ad895a5b97437673cc3ac8b964b823cdb52c932f86"),
},
];
'outer: for test_vector in TEST_VECTORS {
let key_info_len = u16::try_from(test_vector.key_info.len())
.unwrap()
.to_be_bytes();
for counter in 0_u8..=u8::MAX {
let scalar = NistP256::hash_to_scalar::<ExpandMsgXmd<Sha256>>(
&[
test_vector.seed,
&key_info_len,
test_vector.key_info,
&counter.to_be_bytes(),
],
&[test_vector.dst],
)
.unwrap();
if !bool::from(scalar.is_zero()) {
assert_eq!(scalar.to_bytes().as_slice(), test_vector.sk_sm);
continue 'outer;
}
}
panic!("deriving key failed");
}
}
#[test]
fn from_okm_fuzz() {
let mut wide_order = GenericArray::default();
wide_order[16..].copy_from_slice(&NistP256::ORDER.to_be_byte_array());
let wide_order = NonZero::new(U384::from_be_byte_array(wide_order)).unwrap();
let simple_from_okm = move |data: GenericArray<u8, U48>| -> Scalar {
let data = U384::from_be_slice(&data);
let scalar = data % wide_order;
let reduced_scalar = U256::from_be_slice(&scalar.to_be_byte_array()[16..]);
Scalar(reduced_scalar)
};
proptest!(ProptestConfig::with_cases(1000), |(b0 in ANY, b1 in ANY, b2 in ANY, b3 in ANY, b4 in ANY, b5 in ANY)| {
let mut data = GenericArray::default();
data[..8].copy_from_slice(&b0.to_be_bytes());
data[8..16].copy_from_slice(&b1.to_be_bytes());
data[16..24].copy_from_slice(&b2.to_be_bytes());
data[24..32].copy_from_slice(&b3.to_be_bytes());
data[32..40].copy_from_slice(&b4.to_be_bytes());
data[40..].copy_from_slice(&b5.to_be_bytes());
let from_okm = Scalar::from_okm(&data);
let simple_from_okm = simple_from_okm(data);
assert_eq!(from_okm, simple_from_okm);
});
}
}

828
vendor/p256/src/arithmetic/scalar.rs vendored Normal file
View File

@@ -0,0 +1,828 @@
//! Scalar field arithmetic modulo n = 115792089210356248762697446949407573529996955224135760342422259061068512044369
#[cfg_attr(target_pointer_width = "32", path = "scalar/scalar32.rs")]
#[cfg_attr(target_pointer_width = "64", path = "scalar/scalar64.rs")]
mod scalar_impl;
use self::scalar_impl::barrett_reduce;
use crate::{FieldBytes, NistP256, SecretKey, ORDER_HEX};
use core::{
fmt::{self, Debug},
iter::{Product, Sum},
ops::{Add, AddAssign, Mul, MulAssign, Neg, Shr, ShrAssign, Sub, SubAssign},
};
use elliptic_curve::{
bigint::{prelude::*, Limb, U256},
group::ff::{self, Field, PrimeField},
ops::{Invert, Reduce, ReduceNonZero},
rand_core::RngCore,
scalar::{FromUintUnchecked, IsHigh},
subtle::{
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
CtOption,
},
zeroize::DefaultIsZeroes,
Curve, ScalarPrimitive,
};
#[cfg(feature = "bits")]
use {crate::ScalarBits, elliptic_curve::group::ff::PrimeFieldBits};
#[cfg(feature = "serde")]
use serdect::serde::{de, ser, Deserialize, Serialize};
/// Constant representing the modulus
/// n = FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551
pub(crate) const MODULUS: U256 = NistP256::ORDER;
/// `MODULUS / 2`
const FRAC_MODULUS_2: Scalar = Scalar(MODULUS.shr_vartime(1));
/// MU = floor(2^512 / n)
/// = 115792089264276142090721624801893421302707618245269942344307673200490803338238
/// = 0x100000000fffffffffffffffeffffffff43190552df1a6c21012ffd85eedf9bfe
pub const MU: [u64; 5] = [
0x012f_fd85_eedf_9bfe,
0x4319_0552_df1a_6c21,
0xffff_fffe_ffff_ffff,
0x0000_0000_ffff_ffff,
0x0000_0000_0000_0001,
];
/// Scalars are elements in the finite field modulo n.
///
/// # Trait impls
///
/// Much of the important functionality of scalars is provided by traits from
/// the [`ff`](https://docs.rs/ff/) crate, which is re-exported as
/// `p256::elliptic_curve::ff`:
///
/// - [`Field`](https://docs.rs/ff/latest/ff/trait.Field.html) -
/// represents elements of finite fields and provides:
/// - [`Field::random`](https://docs.rs/ff/latest/ff/trait.Field.html#tymethod.random) -
/// generate a random scalar
/// - `double`, `square`, and `invert` operations
/// - Bounds for [`Add`], [`Sub`], [`Mul`], and [`Neg`] (as well as `*Assign` equivalents)
/// - Bounds for [`ConditionallySelectable`] from the `subtle` crate
/// - [`PrimeField`](https://docs.rs/ff/latest/ff/trait.PrimeField.html) -
/// represents elements of prime fields and provides:
/// - `from_repr`/`to_repr` for converting field elements from/to big integers.
/// - `multiplicative_generator` and `root_of_unity` constants.
/// - [`PrimeFieldBits`](https://docs.rs/ff/latest/ff/trait.PrimeFieldBits.html) -
/// operations over field elements represented as bits (requires `bits` feature)
///
/// Please see the documentation for the relevant traits for more information.
///
/// # `serde` support
///
/// When the `serde` feature of this crate is enabled, the `Serialize` and
/// `Deserialize` traits are impl'd for this type.
///
/// The serialization is a fixed-width big endian encoding. When used with
/// textual formats, the binary data is encoded as hexadecimal.
#[derive(Clone, Copy, Default)]
pub struct Scalar(pub(crate) U256);
impl Scalar {
/// Zero scalar.
pub const ZERO: Self = Self(U256::ZERO);
/// Multiplicative identity.
pub const ONE: Self = Self(U256::ONE);
/// Returns the SEC1 encoding of this scalar.
pub fn to_bytes(&self) -> FieldBytes {
self.0.to_be_byte_array()
}
/// Returns self + rhs mod n
pub const fn add(&self, rhs: &Self) -> Self {
Self(self.0.add_mod(&rhs.0, &NistP256::ORDER))
}
/// Returns 2*self.
pub const fn double(&self) -> Self {
self.add(self)
}
/// Returns self - rhs mod n.
pub const fn sub(&self, rhs: &Self) -> Self {
Self(self.0.sub_mod(&rhs.0, &NistP256::ORDER))
}
/// Returns self * rhs mod n
pub const fn multiply(&self, rhs: &Self) -> Self {
let (lo, hi) = self.0.mul_wide(&rhs.0);
Self(barrett_reduce(lo, hi))
}
/// Returns self * self mod p
pub const fn square(&self) -> Self {
// Schoolbook multiplication.
self.multiply(self)
}
/// Right shifts the scalar.
///
/// Note: not constant-time with respect to the `shift` parameter.
pub const fn shr_vartime(&self, shift: usize) -> Scalar {
Self(self.0.shr_vartime(shift))
}
/// Returns the multiplicative inverse of self, if self is non-zero
pub fn invert(&self) -> CtOption<Self> {
CtOption::new(self.invert_unchecked(), !self.is_zero())
}
/// Returns the multiplicative inverse of self.
///
/// Does not check that self is non-zero.
const fn invert_unchecked(&self) -> Self {
// We need to find b such that b * a ≡ 1 mod p. As we are in a prime
// field, we can apply Fermat's Little Theorem:
//
// a^p ≡ a mod p
// a^(p-1) ≡ 1 mod p
// a^(p-2) * a ≡ 1 mod p
//
// Thus inversion can be implemented with a single exponentiation.
//
// This is `n - 2`, so the top right two digits are `4f` instead of `51`.
self.pow_vartime(&[
0xf3b9_cac2_fc63_254f,
0xbce6_faad_a717_9e84,
0xffff_ffff_ffff_ffff,
0xffff_ffff_0000_0000,
])
}
/// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer
/// exponent.
pub const fn pow_vartime(&self, exp: &[u64]) -> Self {
let mut res = Self::ONE;
let mut i = exp.len();
while i > 0 {
i -= 1;
let mut j = 64;
while j > 0 {
j -= 1;
res = res.square();
if ((exp[i] >> j) & 1) == 1 {
res = res.multiply(self);
}
}
}
res
}
/// Is integer representing equivalence class odd?
pub fn is_odd(&self) -> Choice {
self.0.is_odd()
}
/// Is integer representing equivalence class even?
pub fn is_even(&self) -> Choice {
!self.is_odd()
}
}
impl AsRef<Scalar> for Scalar {
fn as_ref(&self) -> &Scalar {
self
}
}
impl Field for Scalar {
const ZERO: Self = Self::ZERO;
const ONE: Self = Self::ONE;
fn random(mut rng: impl RngCore) -> Self {
let mut bytes = FieldBytes::default();
// Generate a uniformly random scalar using rejection sampling,
// which produces a uniformly random distribution of scalars.
//
// This method is not constant time, but should be secure so long as
// rejected RNG outputs are unrelated to future ones (which is a
// necessary property of a `CryptoRng`).
//
// With an unbiased RNG, the probability of failing to complete after 4
// iterations is vanishingly small.
loop {
rng.fill_bytes(&mut bytes);
if let Some(scalar) = Scalar::from_repr(bytes).into() {
return scalar;
}
}
}
#[must_use]
fn square(&self) -> Self {
Scalar::square(self)
}
#[must_use]
fn double(&self) -> Self {
self.add(self)
}
fn invert(&self) -> CtOption<Self> {
Scalar::invert(self)
}
/// Tonelli-Shank's algorithm for q mod 16 = 1
/// <https://eprint.iacr.org/2012/685.pdf> (page 12, algorithm 5)
#[allow(clippy::many_single_char_names)]
fn sqrt(&self) -> CtOption<Self> {
// Note: `pow_vartime` is constant-time with respect to `self`
let w = self.pow_vartime(&[
0x279dce5617e3192a,
0xfde737d56d38bcf4,
0x07ffffffffffffff,
0x07fffffff8000000,
]);
let mut v = Self::S;
let mut x = *self * w;
let mut b = x * w;
let mut z = Self::ROOT_OF_UNITY;
for max_v in (1..=Self::S).rev() {
let mut k = 1;
let mut tmp = b.square();
let mut j_less_than_v = Choice::from(1);
for j in 2..max_v {
let tmp_is_one = tmp.ct_eq(&Self::ONE);
let squared = Self::conditional_select(&tmp, &z, tmp_is_one).square();
tmp = Self::conditional_select(&squared, &tmp, tmp_is_one);
let new_z = Self::conditional_select(&z, &squared, tmp_is_one);
j_less_than_v &= !j.ct_eq(&v);
k = u32::conditional_select(&j, &k, tmp_is_one);
z = Self::conditional_select(&z, &new_z, j_less_than_v);
}
let result = x * z;
x = Self::conditional_select(&result, &x, b.ct_eq(&Self::ONE));
z = z.square();
b *= z;
v = k;
}
CtOption::new(x, x.square().ct_eq(self))
}
fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
ff::helpers::sqrt_ratio_generic(num, div)
}
}
impl PrimeField for Scalar {
type Repr = FieldBytes;
const MODULUS: &'static str = ORDER_HEX;
const NUM_BITS: u32 = 256;
const CAPACITY: u32 = 255;
const TWO_INV: Self = Self(U256::from_u8(2)).invert_unchecked();
const MULTIPLICATIVE_GENERATOR: Self = Self(U256::from_u8(7));
const S: u32 = 4;
const ROOT_OF_UNITY: Self = Self(U256::from_be_hex(
"ffc97f062a770992ba807ace842a3dfc1546cad004378daf0592d7fbb41e6602",
));
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
const DELTA: Self = Self(U256::from_u64(33232930569601));
/// Attempts to parse the given byte array as an SEC1-encoded scalar.
///
/// Returns None if the byte array does not contain a big-endian integer in the range
/// [0, p).
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
let inner = U256::from_be_byte_array(bytes);
CtOption::new(Self(inner), inner.ct_lt(&NistP256::ORDER))
}
fn to_repr(&self) -> FieldBytes {
self.to_bytes()
}
fn is_odd(&self) -> Choice {
self.0.is_odd()
}
}
#[cfg(feature = "bits")]
impl PrimeFieldBits for Scalar {
#[cfg(target_pointer_width = "32")]
type ReprBits = [u32; 8];
#[cfg(target_pointer_width = "64")]
type ReprBits = [u64; 4];
fn to_le_bits(&self) -> ScalarBits {
self.into()
}
fn char_le_bits() -> ScalarBits {
NistP256::ORDER.to_words().into()
}
}
impl DefaultIsZeroes for Scalar {}
impl Eq for Scalar {}
impl FromUintUnchecked for Scalar {
type Uint = U256;
fn from_uint_unchecked(uint: Self::Uint) -> Self {
Self(uint)
}
}
impl Invert for Scalar {
type Output = CtOption<Self>;
fn invert(&self) -> CtOption<Self> {
self.invert()
}
/// Fast variable-time inversion using Stein's algorithm.
///
/// Returns none if the scalar is zero.
///
/// <https://link.springer.com/article/10.1007/s13389-016-0135-4>
///
/// ⚠️ WARNING!
///
/// This method should not be used with (unblinded) secret scalars, as its
/// variable-time operation can potentially leak secrets through
/// sidechannels.
#[allow(non_snake_case)]
fn invert_vartime(&self) -> CtOption<Self> {
let mut u = *self;
let mut v = Self(MODULUS);
let mut A = Self::ONE;
let mut C = Self::ZERO;
while !bool::from(u.is_zero()) {
// u-loop
while bool::from(u.is_even()) {
u >>= 1;
let was_odd: bool = A.is_odd().into();
A >>= 1;
if was_odd {
A += FRAC_MODULUS_2;
A += Self::ONE;
}
}
// v-loop
while bool::from(v.is_even()) {
v >>= 1;
let was_odd: bool = C.is_odd().into();
C >>= 1;
if was_odd {
C += FRAC_MODULUS_2;
C += Self::ONE;
}
}
// sub-step
if u >= v {
u -= &v;
A -= &C;
} else {
v -= &u;
C -= &A;
}
}
CtOption::new(C, !self.is_zero())
}
}
impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
self.0.ct_gt(&FRAC_MODULUS_2.0)
}
}
impl Shr<usize> for Scalar {
type Output = Self;
fn shr(self, rhs: usize) -> Self::Output {
self.shr_vartime(rhs)
}
}
impl Shr<usize> for &Scalar {
type Output = Scalar;
fn shr(self, rhs: usize) -> Self::Output {
self.shr_vartime(rhs)
}
}
impl ShrAssign<usize> for Scalar {
fn shr_assign(&mut self, rhs: usize) {
*self = *self >> rhs;
}
}
impl PartialEq for Scalar {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).into()
}
}
impl PartialOrd for Scalar {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Scalar {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl From<u32> for Scalar {
fn from(k: u32) -> Self {
Scalar(k.into())
}
}
impl From<u64> for Scalar {
fn from(k: u64) -> Self {
Scalar(k.into())
}
}
impl From<u128> for Scalar {
fn from(k: u128) -> Self {
Scalar(k.into())
}
}
impl From<Scalar> for FieldBytes {
fn from(scalar: Scalar) -> Self {
scalar.to_bytes()
}
}
impl From<&Scalar> for FieldBytes {
fn from(scalar: &Scalar) -> Self {
scalar.to_bytes()
}
}
impl From<ScalarPrimitive<NistP256>> for Scalar {
fn from(scalar: ScalarPrimitive<NistP256>) -> Scalar {
Scalar(*scalar.as_uint())
}
}
impl From<&ScalarPrimitive<NistP256>> for Scalar {
fn from(scalar: &ScalarPrimitive<NistP256>) -> Scalar {
Scalar(*scalar.as_uint())
}
}
impl From<Scalar> for ScalarPrimitive<NistP256> {
fn from(scalar: Scalar) -> ScalarPrimitive<NistP256> {
ScalarPrimitive::from(&scalar)
}
}
impl From<&Scalar> for ScalarPrimitive<NistP256> {
fn from(scalar: &Scalar) -> ScalarPrimitive<NistP256> {
ScalarPrimitive::new(scalar.0).unwrap()
}
}
impl From<&SecretKey> for Scalar {
fn from(secret_key: &SecretKey) -> Scalar {
*secret_key.to_nonzero_scalar()
}
}
impl From<Scalar> for U256 {
fn from(scalar: Scalar) -> U256 {
scalar.0
}
}
impl From<&Scalar> for U256 {
fn from(scalar: &Scalar) -> U256 {
scalar.0
}
}
#[cfg(feature = "bits")]
impl From<&Scalar> for ScalarBits {
fn from(scalar: &Scalar) -> ScalarBits {
scalar.0.to_words().into()
}
}
impl Add<Scalar> for Scalar {
type Output = Scalar;
fn add(self, other: Scalar) -> Scalar {
Scalar::add(&self, &other)
}
}
impl Add<&Scalar> for &Scalar {
type Output = Scalar;
fn add(self, other: &Scalar) -> Scalar {
Scalar::add(self, other)
}
}
impl Add<&Scalar> for Scalar {
type Output = Scalar;
fn add(self, other: &Scalar) -> Scalar {
Scalar::add(&self, other)
}
}
impl AddAssign<Scalar> for Scalar {
fn add_assign(&mut self, rhs: Scalar) {
*self = Scalar::add(self, &rhs);
}
}
impl AddAssign<&Scalar> for Scalar {
fn add_assign(&mut self, rhs: &Scalar) {
*self = Scalar::add(self, rhs);
}
}
impl Sub<Scalar> for Scalar {
type Output = Scalar;
fn sub(self, other: Scalar) -> Scalar {
Scalar::sub(&self, &other)
}
}
impl Sub<&Scalar> for &Scalar {
type Output = Scalar;
fn sub(self, other: &Scalar) -> Scalar {
Scalar::sub(self, other)
}
}
impl Sub<&Scalar> for Scalar {
type Output = Scalar;
fn sub(self, other: &Scalar) -> Scalar {
Scalar::sub(&self, other)
}
}
impl SubAssign<Scalar> for Scalar {
fn sub_assign(&mut self, rhs: Scalar) {
*self = Scalar::sub(self, &rhs);
}
}
impl SubAssign<&Scalar> for Scalar {
fn sub_assign(&mut self, rhs: &Scalar) {
*self = Scalar::sub(self, rhs);
}
}
impl Mul<Scalar> for Scalar {
type Output = Scalar;
fn mul(self, other: Scalar) -> Scalar {
Scalar::multiply(&self, &other)
}
}
impl Mul<&Scalar> for &Scalar {
type Output = Scalar;
fn mul(self, other: &Scalar) -> Scalar {
Scalar::multiply(self, other)
}
}
impl Mul<&Scalar> for Scalar {
type Output = Scalar;
fn mul(self, other: &Scalar) -> Scalar {
Scalar::multiply(&self, other)
}
}
impl MulAssign<Scalar> for Scalar {
fn mul_assign(&mut self, rhs: Scalar) {
*self = Scalar::multiply(self, &rhs);
}
}
impl MulAssign<&Scalar> for Scalar {
fn mul_assign(&mut self, rhs: &Scalar) {
*self = Scalar::multiply(self, rhs);
}
}
impl Neg for Scalar {
type Output = Scalar;
fn neg(self) -> Scalar {
Scalar::ZERO - self
}
}
impl<'a> Neg for &'a Scalar {
type Output = Scalar;
fn neg(self) -> Scalar {
Scalar::ZERO - self
}
}
impl Reduce<U256> for Scalar {
type Bytes = FieldBytes;
fn reduce(w: U256) -> Self {
let (r, underflow) = w.sbb(&NistP256::ORDER, Limb::ZERO);
let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
Self(U256::conditional_select(&w, &r, !underflow))
}
fn reduce_bytes(bytes: &FieldBytes) -> Self {
Self::reduce(U256::from_be_byte_array(*bytes))
}
}
impl ReduceNonZero<U256> for Scalar {
fn reduce_nonzero(w: U256) -> Self {
const ORDER_MINUS_ONE: U256 = NistP256::ORDER.wrapping_sub(&U256::ONE);
let (r, underflow) = w.sbb(&ORDER_MINUS_ONE, Limb::ZERO);
let underflow = Choice::from((underflow.0 >> (Limb::BITS - 1)) as u8);
Self(U256::conditional_select(&w, &r, !underflow).wrapping_add(&U256::ONE))
}
fn reduce_nonzero_bytes(bytes: &FieldBytes) -> Self {
Self::reduce_nonzero(U256::from_be_byte_array(*bytes))
}
}
impl Sum for Scalar {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.reduce(core::ops::Add::add).unwrap_or(Self::ZERO)
}
}
impl<'a> Sum<&'a Scalar> for Scalar {
fn sum<I: Iterator<Item = &'a Scalar>>(iter: I) -> Self {
iter.copied().sum()
}
}
impl Product for Scalar {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.reduce(core::ops::Mul::mul).unwrap_or(Self::ONE)
}
}
impl<'a> Product<&'a Scalar> for Scalar {
fn product<I: Iterator<Item = &'a Scalar>>(iter: I) -> Self {
iter.copied().product()
}
}
impl ConditionallySelectable for Scalar {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Self(U256::conditional_select(&a.0, &b.0, choice))
}
}
impl ConstantTimeEq for Scalar {
fn ct_eq(&self, other: &Self) -> Choice {
self.0.ct_eq(&other.0)
}
}
impl Debug for Scalar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Scalar(0x{:X})", &self.0)
}
}
#[cfg(feature = "serde")]
impl Serialize for Scalar {
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> Deserialize<'de> for Scalar {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
Ok(ScalarPrimitive::deserialize(deserializer)?.into())
}
}
#[cfg(test)]
mod tests {
use super::Scalar;
use crate::{FieldBytes, SecretKey};
use elliptic_curve::group::ff::{Field, PrimeField};
use primeorder::{
impl_field_identity_tests, impl_field_invert_tests, impl_field_sqrt_tests,
impl_primefield_tests,
};
/// t = (modulus - 1) >> S
const T: [u64; 4] = [
0x4f3b9cac2fc63255,
0xfbce6faada7179e8,
0x0fffffffffffffff,
0x0ffffffff0000000,
];
impl_field_identity_tests!(Scalar);
impl_field_invert_tests!(Scalar);
impl_field_sqrt_tests!(Scalar);
impl_primefield_tests!(Scalar, T);
#[test]
fn from_to_bytes_roundtrip() {
let k: u64 = 42;
let mut bytes = FieldBytes::default();
bytes[24..].copy_from_slice(k.to_be_bytes().as_ref());
let scalar = Scalar::from_repr(bytes).unwrap();
assert_eq!(bytes, scalar.to_bytes());
}
/// Basic tests that multiplication works.
#[test]
fn multiply() {
let one = Scalar::ONE;
let two = one + &one;
let three = two + &one;
let six = three + &three;
assert_eq!(six, two * &three);
let minus_two = -two;
let minus_three = -three;
assert_eq!(two, -minus_two);
assert_eq!(minus_three * &minus_two, minus_two * &minus_three);
assert_eq!(six, minus_two * &minus_three);
}
/// Tests that a Scalar can be safely converted to a SecretKey and back
#[test]
fn from_ec_secret() {
let scalar = Scalar::ONE;
let secret = SecretKey::from_bytes(&scalar.to_bytes()).unwrap();
let rederived_scalar = Scalar::from(&secret);
assert_eq!(scalar.0, rederived_scalar.0);
}
#[test]
#[cfg(all(feature = "bits", target_pointer_width = "32"))]
fn scalar_into_scalarbits() {
use crate::ScalarBits;
let minus_one = ScalarBits::from([
0xfc63_2550,
0xf3b9_cac2,
0xa717_9e84,
0xbce6_faad,
0xffff_ffff,
0xffff_ffff,
0x0000_0000,
0xffff_ffff,
]);
let scalar_bits = ScalarBits::from(&-Scalar::from(1u32));
assert_eq!(minus_one, scalar_bits);
}
}

View File

@@ -0,0 +1,188 @@
//! 32-bit secp256r1 scalar field algorithms.
// TODO(tarcieri): adapt 64-bit arithmetic to proper 32-bit arithmetic
use super::{MODULUS, MU};
use crate::{
arithmetic::util::{adc, mac, sbb},
U256,
};
/// Barrett Reduction
///
/// The general algorithm is:
/// ```text
/// p = n = order of group
/// b = 2^64 = 64bit machine word
/// k = 4
/// a \in [0, 2^512]
/// mu := floor(b^{2k} / p)
/// q1 := floor(a / b^{k - 1})
/// q2 := q1 * mu
/// q3 := <- floor(a / b^{k - 1})
/// r1 := a mod b^{k + 1}
/// r2 := q3 * m mod b^{k + 1}
/// r := r1 - r2
///
/// if r < 0: r := r + b^{k + 1}
/// while r >= p: do r := r - p (at most twice)
/// ```
///
/// References:
/// - Handbook of Applied Cryptography, Chapter 14
/// Algorithm 14.42
/// http://cacr.uwaterloo.ca/hac/about/chap14.pdf
///
/// - Efficient and Secure Elliptic Curve Cryptography Implementation of Curve P-256
/// Algorithm 6) Barrett Reduction modulo p
/// https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf
#[inline]
#[allow(clippy::too_many_arguments)]
pub(super) const fn barrett_reduce(lo: U256, hi: U256) -> U256 {
let lo = u256_to_u64x4(lo);
let hi = u256_to_u64x4(hi);
let a0 = lo[0];
let a1 = lo[1];
let a2 = lo[2];
let a3 = lo[3];
let a4 = hi[0];
let a5 = hi[1];
let a6 = hi[2];
let a7 = hi[3];
let q1: [u64; 5] = [a3, a4, a5, a6, a7];
let q3 = q1_times_mu_shift_five(&q1);
let r1: [u64; 5] = [a0, a1, a2, a3, a4];
let r2: [u64; 5] = q3_times_n_keep_five(&q3);
let r: [u64; 5] = sub_inner_five(r1, r2);
// Result is in range (0, 3*n - 1),
// and 90% of the time, no subtraction will be needed.
let r = subtract_n_if_necessary(r[0], r[1], r[2], r[3], r[4]);
let r = subtract_n_if_necessary(r[0], r[1], r[2], r[3], r[4]);
U256::from_words([
(r[0] & 0xFFFFFFFF) as u32,
(r[0] >> 32) as u32,
(r[1] & 0xFFFFFFFF) as u32,
(r[1] >> 32) as u32,
(r[2] & 0xFFFFFFFF) as u32,
(r[2] >> 32) as u32,
(r[3] & 0xFFFFFFFF) as u32,
(r[3] >> 32) as u32,
])
}
const fn q1_times_mu_shift_five(q1: &[u64; 5]) -> [u64; 5] {
// Schoolbook multiplication.
let (_w0, carry) = mac(0, q1[0], MU[0], 0);
let (w1, carry) = mac(0, q1[0], MU[1], carry);
let (w2, carry) = mac(0, q1[0], MU[2], carry);
let (w3, carry) = mac(0, q1[0], MU[3], carry);
let (w4, w5) = mac(0, q1[0], MU[4], carry);
let (_w1, carry) = mac(w1, q1[1], MU[0], 0);
let (w2, carry) = mac(w2, q1[1], MU[1], carry);
let (w3, carry) = mac(w3, q1[1], MU[2], carry);
let (w4, carry) = mac(w4, q1[1], MU[3], carry);
let (w5, w6) = mac(w5, q1[1], MU[4], carry);
let (_w2, carry) = mac(w2, q1[2], MU[0], 0);
let (w3, carry) = mac(w3, q1[2], MU[1], carry);
let (w4, carry) = mac(w4, q1[2], MU[2], carry);
let (w5, carry) = mac(w5, q1[2], MU[3], carry);
let (w6, w7) = mac(w6, q1[2], MU[4], carry);
let (_w3, carry) = mac(w3, q1[3], MU[0], 0);
let (w4, carry) = mac(w4, q1[3], MU[1], carry);
let (w5, carry) = mac(w5, q1[3], MU[2], carry);
let (w6, carry) = mac(w6, q1[3], MU[3], carry);
let (w7, w8) = mac(w7, q1[3], MU[4], carry);
let (_w4, carry) = mac(w4, q1[4], MU[0], 0);
let (w5, carry) = mac(w5, q1[4], MU[1], carry);
let (w6, carry) = mac(w6, q1[4], MU[2], carry);
let (w7, carry) = mac(w7, q1[4], MU[3], carry);
let (w8, w9) = mac(w8, q1[4], MU[4], carry);
// let q2 = [_w0, _w1, _w2, _w3, _w4, w5, w6, w7, w8, w9];
[w5, w6, w7, w8, w9]
}
const fn q3_times_n_keep_five(q3: &[u64; 5]) -> [u64; 5] {
// Schoolbook multiplication.
let modulus = u256_to_u64x4(MODULUS);
let (w0, carry) = mac(0, q3[0], modulus[0], 0);
let (w1, carry) = mac(0, q3[0], modulus[1], carry);
let (w2, carry) = mac(0, q3[0], modulus[2], carry);
let (w3, carry) = mac(0, q3[0], modulus[3], carry);
let (w4, _) = mac(0, q3[0], 0, carry);
let (w1, carry) = mac(w1, q3[1], modulus[0], 0);
let (w2, carry) = mac(w2, q3[1], modulus[1], carry);
let (w3, carry) = mac(w3, q3[1], modulus[2], carry);
let (w4, _) = mac(w4, q3[1], modulus[3], carry);
let (w2, carry) = mac(w2, q3[2], modulus[0], 0);
let (w3, carry) = mac(w3, q3[2], modulus[1], carry);
let (w4, _) = mac(w4, q3[2], modulus[2], carry);
let (w3, carry) = mac(w3, q3[3], modulus[0], 0);
let (w4, _) = mac(w4, q3[3], modulus[1], carry);
let (w4, _) = mac(w4, q3[4], modulus[0], 0);
[w0, w1, w2, w3, w4]
}
#[inline]
#[allow(clippy::too_many_arguments)]
const fn sub_inner_five(l: [u64; 5], r: [u64; 5]) -> [u64; 5] {
let (w0, borrow) = sbb(l[0], r[0], 0);
let (w1, borrow) = sbb(l[1], r[1], borrow);
let (w2, borrow) = sbb(l[2], r[2], borrow);
let (w3, borrow) = sbb(l[3], r[3], borrow);
let (w4, _borrow) = sbb(l[4], r[4], borrow);
// If underflow occurred on the final limb - don't care (= add b^{k+1}).
[w0, w1, w2, w3, w4]
}
#[inline]
#[allow(clippy::too_many_arguments)]
const fn subtract_n_if_necessary(r0: u64, r1: u64, r2: u64, r3: u64, r4: u64) -> [u64; 5] {
let modulus = u256_to_u64x4(MODULUS);
let (w0, borrow) = sbb(r0, modulus[0], 0);
let (w1, borrow) = sbb(r1, modulus[1], borrow);
let (w2, borrow) = sbb(r2, modulus[2], borrow);
let (w3, borrow) = sbb(r3, modulus[3], borrow);
let (w4, borrow) = sbb(r4, 0, borrow);
// If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise
// borrow = 0x000...000. Thus, we use it as a mask to conditionally add the
// modulus.
let (w0, carry) = adc(w0, modulus[0] & borrow, 0);
let (w1, carry) = adc(w1, modulus[1] & borrow, carry);
let (w2, carry) = adc(w2, modulus[2] & borrow, carry);
let (w3, carry) = adc(w3, modulus[3] & borrow, carry);
let (w4, _carry) = adc(w4, 0, carry);
[w0, w1, w2, w3, w4]
}
// TODO(tarcieri): replace this with proper 32-bit arithmetic
#[inline]
const fn u256_to_u64x4(u256: U256) -> [u64; 4] {
let words = u256.as_words();
[
(words[0] as u64) | ((words[1] as u64) << 32),
(words[2] as u64) | ((words[3] as u64) << 32),
(words[4] as u64) | ((words[5] as u64) << 32),
(words[6] as u64) | ((words[7] as u64) << 32),
]
}

View File

@@ -0,0 +1,163 @@
//! 64-bit secp256r1 scalar field algorithms.
use super::{MODULUS, MU};
use crate::{
arithmetic::util::{adc, mac, sbb},
U256,
};
/// Barrett Reduction
///
/// The general algorithm is:
/// ```text
/// p = n = order of group
/// b = 2^64 = 64bit machine word
/// k = 4
/// a \in [0, 2^512]
/// mu := floor(b^{2k} / p)
/// q1 := floor(a / b^{k - 1})
/// q2 := q1 * mu
/// q3 := <- floor(a / b^{k - 1})
/// r1 := a mod b^{k + 1}
/// r2 := q3 * m mod b^{k + 1}
/// r := r1 - r2
///
/// if r < 0: r := r + b^{k + 1}
/// while r >= p: do r := r - p (at most twice)
/// ```
///
/// References:
/// - Handbook of Applied Cryptography, Chapter 14
/// Algorithm 14.42
/// http://cacr.uwaterloo.ca/hac/about/chap14.pdf
///
/// - Efficient and Secure Elliptic Curve Cryptography Implementation of Curve P-256
/// Algorithm 6) Barrett Reduction modulo p
/// https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-adalier-mehmet.pdf
#[inline]
#[allow(clippy::too_many_arguments)]
pub(super) const fn barrett_reduce(lo: U256, hi: U256) -> U256 {
let lo = lo.as_words();
let hi = hi.as_words();
let a0 = lo[0];
let a1 = lo[1];
let a2 = lo[2];
let a3 = lo[3];
let a4 = hi[0];
let a5 = hi[1];
let a6 = hi[2];
let a7 = hi[3];
let q1: [u64; 5] = [a3, a4, a5, a6, a7];
let q3 = q1_times_mu_shift_five(&q1);
let r1: [u64; 5] = [a0, a1, a2, a3, a4];
let r2: [u64; 5] = q3_times_n_keep_five(&q3);
let r: [u64; 5] = sub_inner_five(r1, r2);
// Result is in range (0, 3*n - 1),
// and 90% of the time, no subtraction will be needed.
let r = subtract_n_if_necessary(r[0], r[1], r[2], r[3], r[4]);
let r = subtract_n_if_necessary(r[0], r[1], r[2], r[3], r[4]);
U256::from_words([r[0], r[1], r[2], r[3]])
}
const fn q1_times_mu_shift_five(q1: &[u64; 5]) -> [u64; 5] {
// Schoolbook multiplication.
let (_w0, carry) = mac(0, q1[0], MU[0], 0);
let (w1, carry) = mac(0, q1[0], MU[1], carry);
let (w2, carry) = mac(0, q1[0], MU[2], carry);
let (w3, carry) = mac(0, q1[0], MU[3], carry);
let (w4, w5) = mac(0, q1[0], MU[4], carry);
let (_w1, carry) = mac(w1, q1[1], MU[0], 0);
let (w2, carry) = mac(w2, q1[1], MU[1], carry);
let (w3, carry) = mac(w3, q1[1], MU[2], carry);
let (w4, carry) = mac(w4, q1[1], MU[3], carry);
let (w5, w6) = mac(w5, q1[1], MU[4], carry);
let (_w2, carry) = mac(w2, q1[2], MU[0], 0);
let (w3, carry) = mac(w3, q1[2], MU[1], carry);
let (w4, carry) = mac(w4, q1[2], MU[2], carry);
let (w5, carry) = mac(w5, q1[2], MU[3], carry);
let (w6, w7) = mac(w6, q1[2], MU[4], carry);
let (_w3, carry) = mac(w3, q1[3], MU[0], 0);
let (w4, carry) = mac(w4, q1[3], MU[1], carry);
let (w5, carry) = mac(w5, q1[3], MU[2], carry);
let (w6, carry) = mac(w6, q1[3], MU[3], carry);
let (w7, w8) = mac(w7, q1[3], MU[4], carry);
let (_w4, carry) = mac(w4, q1[4], MU[0], 0);
let (w5, carry) = mac(w5, q1[4], MU[1], carry);
let (w6, carry) = mac(w6, q1[4], MU[2], carry);
let (w7, carry) = mac(w7, q1[4], MU[3], carry);
let (w8, w9) = mac(w8, q1[4], MU[4], carry);
// let q2 = [_w0, _w1, _w2, _w3, _w4, w5, w6, w7, w8, w9];
[w5, w6, w7, w8, w9]
}
const fn q3_times_n_keep_five(q3: &[u64; 5]) -> [u64; 5] {
// Schoolbook multiplication.
let modulus = MODULUS.as_words();
let (w0, carry) = mac(0, q3[0], modulus[0], 0);
let (w1, carry) = mac(0, q3[0], modulus[1], carry);
let (w2, carry) = mac(0, q3[0], modulus[2], carry);
let (w3, carry) = mac(0, q3[0], modulus[3], carry);
let (w4, _) = mac(0, q3[0], 0, carry);
let (w1, carry) = mac(w1, q3[1], modulus[0], 0);
let (w2, carry) = mac(w2, q3[1], modulus[1], carry);
let (w3, carry) = mac(w3, q3[1], modulus[2], carry);
let (w4, _) = mac(w4, q3[1], modulus[3], carry);
let (w2, carry) = mac(w2, q3[2], modulus[0], 0);
let (w3, carry) = mac(w3, q3[2], modulus[1], carry);
let (w4, _) = mac(w4, q3[2], modulus[2], carry);
let (w3, carry) = mac(w3, q3[3], modulus[0], 0);
let (w4, _) = mac(w4, q3[3], modulus[1], carry);
let (w4, _) = mac(w4, q3[4], modulus[0], 0);
[w0, w1, w2, w3, w4]
}
#[inline]
#[allow(clippy::too_many_arguments)]
const fn sub_inner_five(l: [u64; 5], r: [u64; 5]) -> [u64; 5] {
let (w0, borrow) = sbb(l[0], r[0], 0);
let (w1, borrow) = sbb(l[1], r[1], borrow);
let (w2, borrow) = sbb(l[2], r[2], borrow);
let (w3, borrow) = sbb(l[3], r[3], borrow);
let (w4, _borrow) = sbb(l[4], r[4], borrow);
// If underflow occurred on the final limb - don't care (= add b^{k+1}).
[w0, w1, w2, w3, w4]
}
#[inline]
#[allow(clippy::too_many_arguments)]
const fn subtract_n_if_necessary(r0: u64, r1: u64, r2: u64, r3: u64, r4: u64) -> [u64; 5] {
let modulus = MODULUS.as_words();
let (w0, borrow) = sbb(r0, modulus[0], 0);
let (w1, borrow) = sbb(r1, modulus[1], borrow);
let (w2, borrow) = sbb(r2, modulus[2], borrow);
let (w3, borrow) = sbb(r3, modulus[3], borrow);
let (w4, borrow) = sbb(r4, 0, borrow);
// If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise
// borrow = 0x000...000. Thus, we use it as a mask to conditionally add the
// modulus.
let (w0, carry) = adc(w0, modulus[0] & borrow, 0);
let (w1, carry) = adc(w1, modulus[1] & borrow, carry);
let (w2, carry) = adc(w2, modulus[2] & borrow, carry);
let (w3, carry) = adc(w3, modulus[3] & borrow, carry);
let (w4, _carry) = adc(w4, 0, carry);
[w0, w1, w2, w3, w4]
}

23
vendor/p256/src/arithmetic/util.rs vendored Normal file
View File

@@ -0,0 +1,23 @@
//! Helper functions.
// TODO(tarcieri): replace these with `crypto-bigint`
/// Computes `a + b + carry`, returning the result along with the new carry. 64-bit version.
#[inline(always)]
pub const fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) {
let ret = (a as u128) + (b as u128) + (carry as u128);
(ret as u64, (ret >> 64) as u64)
}
/// Computes `a - (b + borrow)`, returning the result along with the new borrow. 64-bit version.
#[inline(always)]
pub const fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) {
let ret = (a as u128).wrapping_sub((b as u128) + ((borrow >> 63) as u128));
(ret as u64, (ret >> 64) as u64)
}
/// Computes `a + (b * c) + carry`, returning the result along with the new carry.
#[inline(always)]
pub const fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) {
let ret = (a as u128) + ((b as u128) * (c as u128)) + (carry as u128);
(ret as u64, (ret >> 64) as u64)
}

47
vendor/p256/src/ecdh.rs vendored Normal file
View File

@@ -0,0 +1,47 @@
//! Elliptic Curve Diffie-Hellman (Ephemeral) Support.
//!
//! This module contains a high-level interface for performing ephemeral
//! Diffie-Hellman key exchanges using the secp256r1 elliptic curve.
//!
//! # Usage
//!
//! This usage example is from the perspective of two participants in the
//! exchange, nicknamed "Alice" and "Bob".
//!
//! ```
//! use p256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret};
//! use rand_core::OsRng; // requires 'getrandom' feature
//!
//! // Alice
//! let alice_secret = EphemeralSecret::random(&mut OsRng);
//! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key());
//!
//! // Bob
//! let bob_secret = EphemeralSecret::random(&mut OsRng);
//! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key());
//!
//! // Alice decodes Bob's serialized public key and computes a shared secret from it
//! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref())
//! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this!
//!
//! let alice_shared = alice_secret.diffie_hellman(&bob_public);
//!
//! // Bob decodes Alice's serialized public key and computes the same shared secret
//! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref())
//! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this!
//!
//! let bob_shared = bob_secret.diffie_hellman(&alice_public);
//!
//! // Both participants arrive on the same shared secret
//! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes());
//! ```
pub use elliptic_curve::ecdh::diffie_hellman;
use crate::NistP256;
/// NIST P-256 Ephemeral Diffie-Hellman Secret.
pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret<NistP256>;
/// Shared secret value computed via ECDH key agreement.
pub type SharedSecret = elliptic_curve::ecdh::SharedSecret<NistP256>;

198
vendor/p256/src/ecdsa.rs vendored Normal file
View File

@@ -0,0 +1,198 @@
//! Elliptic Curve Digital Signature Algorithm (ECDSA)
//!
//! This module contains support for computing and verifying ECDSA signatures.
//! To use it, you will need to enable one of the two following Cargo features:
//!
//! - `ecdsa-core`: provides only the [`Signature`] type (which represents an
//! ECDSA/P-256 signature). Does not require the `arithmetic` feature.
//! This is useful for 3rd-party crates which wish to use the `Signature`
//! type for interoperability purposes (particularly in conjunction with the
//! [`signature::Signer`] trait. Example use cases for this include other
//! software implementations of ECDSA/P-256 and wrappers for cloud KMS
//! services or hardware devices (HSM or crypto hardware wallet).
//! - `ecdsa`: provides `ecdsa-core` features plus the [`SigningKey`] and
//! [`VerifyingKey`] types which natively implement ECDSA/P-256 signing and
//! verification.
//!
//! ## Signing/Verification Example
//!
//! This example requires the `ecdsa` Cargo feature is enabled:
//!
//! ```
//! # #[cfg(feature = "ecdsa")]
//! # {
//! use p256::{
//! ecdsa::{SigningKey, Signature, signature::Signer},
//! };
//! use rand_core::OsRng; // requires 'getrandom' feature
//!
//! // Signing
//! let signing_key = SigningKey::random(&mut OsRng); // Serialize with `::to_bytes()`
//! let message = b"ECDSA proves knowledge of a secret number in the context of a single message";
//! let signature: Signature = signing_key.sign(message);
//!
//! // Verification
//! use p256::ecdsa::{VerifyingKey, signature::Verifier};
//!
//! let verifying_key = VerifyingKey::from(&signing_key); // Serialize with `::to_encoded_point()`
//! assert!(verifying_key.verify(message, &signature).is_ok());
//! # }
//! ```
pub use ecdsa_core::signature::{self, Error};
use super::NistP256;
#[cfg(feature = "ecdsa")]
use {
crate::{AffinePoint, Scalar},
ecdsa_core::hazmat::{SignPrimitive, VerifyPrimitive},
};
/// ECDSA/P-256 signature (fixed-size)
pub type Signature = ecdsa_core::Signature<NistP256>;
/// ECDSA/P-256 signature (ASN.1 DER encoded)
pub type DerSignature = ecdsa_core::der::Signature<NistP256>;
/// ECDSA/P-256 signing key
#[cfg(feature = "ecdsa")]
pub type SigningKey = ecdsa_core::SigningKey<NistP256>;
/// ECDSA/P-256 verification key (i.e. public key)
#[cfg(feature = "ecdsa")]
pub type VerifyingKey = ecdsa_core::VerifyingKey<NistP256>;
#[cfg(feature = "sha256")]
impl ecdsa_core::hazmat::DigestPrimitive for NistP256 {
type Digest = sha2::Sha256;
}
#[cfg(feature = "ecdsa")]
impl SignPrimitive<NistP256> for Scalar {}
#[cfg(feature = "ecdsa")]
impl VerifyPrimitive<NistP256> for AffinePoint {}
#[cfg(all(test, feature = "ecdsa"))]
mod tests {
use crate::{
ecdsa::{
signature::hazmat::{PrehashSigner, PrehashVerifier},
signature::Signer,
Signature, SigningKey, VerifyingKey,
},
test_vectors::ecdsa::ECDSA_TEST_VECTORS,
AffinePoint, BlindedScalar, EncodedPoint, Scalar,
};
use ecdsa_core::hazmat::SignPrimitive;
use elliptic_curve::{
generic_array::GenericArray, group::ff::PrimeField, rand_core::OsRng,
sec1::FromEncodedPoint,
};
use hex_literal::hex;
use sha2::Digest;
// Test vector from RFC 6979 Appendix 2.5 (NIST P-256 + SHA-256)
// <https://tools.ietf.org/html/rfc6979#appendix-A.2.5>
#[test]
fn rfc6979() {
let x = hex!("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
let signer = SigningKey::from_bytes(&x.into()).unwrap();
let signature: Signature = signer.sign(b"sample");
assert_eq!(
signature.to_bytes().as_slice(),
&hex!(
"efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716
f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8"
)
);
let signature: Signature = signer.sign(b"test");
assert_eq!(
signature.to_bytes().as_slice(),
&hex!(
"f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d38367
019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083"
)
);
}
// Test signing with PrehashSigner using SHA-384 which output is larger than P-256 field size.
#[test]
fn prehash_signer_signing_with_sha384() {
let x = hex!("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
let signer = SigningKey::from_bytes(&x.into()).unwrap();
let digest = sha2::Sha384::digest(b"test");
let signature: Signature = signer.sign_prehash(&digest).unwrap();
assert_eq!(
signature.to_bytes().as_slice(),
&hex!(
"ebde85f1539af67e70dd7a8a6afeeb332aa7f08f01ebb6ab6e04e2a62d2fef75
871af45800daddf55619b005a601a7a84f544260f1d2625b2ef5aa7a4f4dd76f"
)
);
}
// Test verifying with PrehashVerifier using SHA-256 which output is larger than P-256 field size.
#[test]
fn prehash_signer_verification_with_sha384() {
// The following test vector adapted from the FIPS 186-4 ECDSA test vectors
// (P-256, SHA-384, from `SigGen.txt` in `186-4ecdsatestvectors.zip`)
// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/digital-signatures>
let verifier = VerifyingKey::from_affine(
AffinePoint::from_encoded_point(&EncodedPoint::from_affine_coordinates(
GenericArray::from_slice(&hex!(
"e0e7b99bc62d8dd67883e39ed9fa0657789c5ff556cc1fd8dd1e2a55e9e3f243"
)),
GenericArray::from_slice(&hex!(
"63fbfd0232b95578075c903a4dbf85ad58f8350516e1ec89b0ee1f5e1362da69"
)),
false,
))
.unwrap(),
)
.unwrap();
let signature = Signature::from_scalars(
GenericArray::clone_from_slice(&hex!(
"f5087878e212b703578f5c66f434883f3ef414dc23e2e8d8ab6a8d159ed5ad83"
)),
GenericArray::clone_from_slice(&hex!(
"306b4c6c20213707982dffbb30fba99b96e792163dd59dbe606e734328dd7c8a"
)),
)
.unwrap();
let result = verifier.verify_prehash(
&hex!("d9c83b92fa0979f4a5ddbd8dd22ab9377801c3c31bf50f932ace0d2146e2574da0d5552dbed4b18836280e9f94558ea6"),
&signature,
);
assert!(result.is_ok());
}
#[test]
fn scalar_blinding() {
let vector = &ECDSA_TEST_VECTORS[0];
let d = Scalar::from_repr(GenericArray::clone_from_slice(vector.d)).unwrap();
let k = Scalar::from_repr(GenericArray::clone_from_slice(vector.k)).unwrap();
let k_blinded = BlindedScalar::new(k, &mut OsRng);
let z = GenericArray::clone_from_slice(vector.m);
let sig = d.try_sign_prehashed(k_blinded, &z).unwrap().0;
assert_eq!(vector.r, sig.r().to_bytes().as_slice());
assert_eq!(vector.s, sig.s().to_bytes().as_slice());
}
mod sign {
use crate::{test_vectors::ecdsa::ECDSA_TEST_VECTORS, NistP256};
ecdsa_core::new_signing_test!(NistP256, ECDSA_TEST_VECTORS);
}
mod verify {
use crate::{test_vectors::ecdsa::ECDSA_TEST_VECTORS, NistP256};
ecdsa_core::new_verification_test!(NistP256, ECDSA_TEST_VECTORS);
}
mod wycheproof {
use crate::NistP256;
ecdsa_core::new_wycheproof_test!(wycheproof, "wycheproof", NistP256);
}
}

183
vendor/p256/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,183 @@
#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
)]
#![forbid(unsafe_code)]
#![warn(
clippy::mod_module_files,
clippy::unwrap_used,
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
//! ## `serde` support
//!
//! When the `serde` feature of this crate is enabled, `Serialize` and
//! `Deserialize` are impl'd for the following types:
//!
//! - [`AffinePoint`]
//! - [`Scalar`]
//! - [`ecdsa::VerifyingKey`]
//!
//! Please see type-specific documentation for more information.
#[cfg(feature = "arithmetic")]
mod arithmetic;
#[cfg(feature = "ecdh")]
pub mod ecdh;
#[cfg(feature = "ecdsa-core")]
pub mod ecdsa;
#[cfg(any(feature = "test-vectors", test))]
pub mod test_vectors;
pub use elliptic_curve::{self, bigint::U256, consts::U32};
#[cfg(feature = "arithmetic")]
pub use arithmetic::{scalar::Scalar, AffinePoint, ProjectivePoint};
#[cfg(feature = "expose-field")]
pub use arithmetic::field::FieldElement;
#[cfg(feature = "pkcs8")]
pub use elliptic_curve::pkcs8;
use elliptic_curve::{
bigint::ArrayEncoding, consts::U33, generic_array::GenericArray, FieldBytesEncoding,
};
/// Order of NIST P-256's elliptic curve group (i.e. scalar modulus) serialized
/// as hexadecimal.
///
/// ```text
/// n = FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551
/// ```
///
/// # Calculating the order
/// One way to calculate the order is with `GP/PARI`:
///
/// ```text
/// p = (2^224) * (2^32 - 1) + 2^192 + 2^96 - 1
/// b = 41058363725152142129326129780047268409114441015993725554835256314039467401291
/// E = ellinit([Mod(-3, p), Mod(b, p)])
/// default(parisize, 120000000)
/// n = ellsea(E)
/// isprime(n)
/// ```
const ORDER_HEX: &str = "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551";
/// NIST P-256 elliptic curve.
///
/// This curve is also known as prime256v1 (ANSI X9.62) and secp256r1 (SECG)
/// and is specified in [NIST SP 800-186]:
/// Recommendations for Discrete Logarithm-based Cryptography:
/// Elliptic Curve Domain Parameters.
///
/// It's included in the US National Security Agency's "Suite B" and is widely
/// used in protocols like TLS and the associated X.509 PKI.
///
/// Its equation is `y² = x³ - 3x + b` over a ~256-bit prime field where `b` is
/// the "verifiably random"† constant:
///
/// ```text
/// b = 41058363725152142129326129780047268409114441015993725554835256314039467401291
/// ```
///
/// † *NOTE: the specific origins of this constant have never been fully disclosed
/// (it is the SHA-1 digest of an unknown NSA-selected constant)*
///
/// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
pub struct NistP256;
impl elliptic_curve::Curve for NistP256 {
/// 32-byte serialized field elements.
type FieldBytesSize = U32;
/// 256-bit integer type used for internally representing field elements.
type Uint = U256;
/// Order of NIST P-256's elliptic curve group (i.e. scalar modulus).
const ORDER: U256 = U256::from_be_hex(ORDER_HEX);
}
impl elliptic_curve::PrimeCurve for NistP256 {}
impl elliptic_curve::point::PointCompression for NistP256 {
/// NIST P-256 points are typically uncompressed.
const COMPRESS_POINTS: bool = false;
}
impl elliptic_curve::point::PointCompaction for NistP256 {
/// NIST P-256 points are typically uncompressed.
const COMPACT_POINTS: bool = false;
}
#[cfg(feature = "jwk")]
impl elliptic_curve::JwkParameters for NistP256 {
const CRV: &'static str = "P-256";
}
#[cfg(feature = "pkcs8")]
impl pkcs8::AssociatedOid for NistP256 {
const OID: pkcs8::ObjectIdentifier = pkcs8::ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7");
}
/// Blinded scalar.
#[cfg(feature = "arithmetic")]
pub type BlindedScalar = elliptic_curve::scalar::BlindedScalar<NistP256>;
/// Compressed SEC1-encoded NIST P-256 curve point.
pub type CompressedPoint = GenericArray<u8, U33>;
/// NIST P-256 SEC1 encoded point.
pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint<NistP256>;
/// NIST P-256 field element serialized as bytes.
///
/// Byte array containing a serialized field element value (base field or scalar).
pub type FieldBytes = elliptic_curve::FieldBytes<NistP256>;
impl FieldBytesEncoding<NistP256> for U256 {
fn decode_field_bytes(field_bytes: &FieldBytes) -> Self {
U256::from_be_byte_array(*field_bytes)
}
fn encode_field_bytes(&self) -> FieldBytes {
self.to_be_byte_array()
}
}
/// Non-zero NIST P-256 scalar field element.
#[cfg(feature = "arithmetic")]
pub type NonZeroScalar = elliptic_curve::NonZeroScalar<NistP256>;
/// NIST P-256 public key.
#[cfg(feature = "arithmetic")]
pub type PublicKey = elliptic_curve::PublicKey<NistP256>;
/// NIST P-256 secret key.
pub type SecretKey = elliptic_curve::SecretKey<NistP256>;
#[cfg(not(feature = "arithmetic"))]
impl elliptic_curve::sec1::ValidatePublicKey for NistP256 {}
/// Bit representation of a NIST P-256 scalar field element.
#[cfg(feature = "bits")]
pub type ScalarBits = elliptic_curve::scalar::ScalarBits<NistP256>;
#[cfg(feature = "voprf")]
impl elliptic_curve::VoprfParameters for NistP256 {
/// See <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-19.html#section-4.3>.
const ID: &'static str = "P256-SHA256";
/// See <https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-08.html#section-4.3-1.2>.
type Hash = sha2::Sha256;
}

6
vendor/p256/src/test_vectors.rs vendored Normal file
View File

@@ -0,0 +1,6 @@
//! secp256r1 test vectors.
#[cfg(test)]
pub mod ecdsa;
pub mod field;
pub mod group;

Binary file not shown.

150
vendor/p256/src/test_vectors/ecdsa.rs vendored Normal file
View File

@@ -0,0 +1,150 @@
//! ECDSA/secp256r1 test vectors
use ecdsa_core::dev::TestVector;
use hex_literal::hex;
/// ECDSA/P-256 test vectors.
///
/// Adapted from the FIPS 186-4 ECDSA test vectors
/// (P-256, SHA-256, from `SigGen.txt` in `186-4ecdsatestvectors.zip`)
/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/digital-signatures>
///
/// The `m` field contains a SHA-256 prehash of the `Msg` field in the
/// original `SigTen.txt`.
pub const ECDSA_TEST_VECTORS: &[TestVector] = &[
TestVector {
d: &hex!("519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464"),
q_x: &hex!("1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83"),
q_y: &hex!("ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9"),
k: &hex!("94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de"),
m: &hex!("44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56"),
r: &hex!("f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac"),
s: &hex!("8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903"),
},
TestVector {
d: &hex!("0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813"),
q_x: &hex!("e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8a"),
q_y: &hex!("bfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39"),
k: &hex!("6d3e71882c3b83b156bb14e0ab184aa9fb728068d3ae9fac421187ae0b2f34c6"),
m: &hex!("9b2db89cb0e8fa3cc7608b4d6cc1dec0114e0b9ff4080bea12b134f489ab2bbc"),
r: &hex!("976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db"),
s: &hex!("1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932"),
},
TestVector {
d: &hex!("e283871239837e13b95f789e6e1af63bf61c918c992e62bca040d64cad1fc2ef"),
q_x: &hex!("74ccd8a62fba0e667c50929a53f78c21b8ff0c3c737b0b40b1750b2302b0bde8"),
q_y: &hex!("29074e21f3a0ef88b9efdf10d06aa4c295cc1671f758ca0e4cd108803d0f2614"),
k: &hex!("ad5e887eb2b380b8d8280ad6e5ff8a60f4d26243e0124c2f31a297b5d0835de2"),
m: &hex!("b804cf88af0c2eff8bbbfb3660ebb3294138e9d3ebd458884e19818061dacff0"),
r: &hex!("35fb60f5ca0f3ca08542fb3cc641c8263a2cab7a90ee6a5e1583fac2bb6f6bd1"),
s: &hex!("ee59d81bc9db1055cc0ed97b159d8784af04e98511d0a9a407b99bb292572e96"),
},
TestVector {
d: &hex!("a3d2d3b7596f6592ce98b4bfe10d41837f10027a90d7bb75349490018cf72d07"),
q_x: &hex!("322f80371bf6e044bc49391d97c1714ab87f990b949bc178cb7c43b7c22d89e1"),
q_y: &hex!("3c15d54a5cc6b9f09de8457e873eb3deb1fceb54b0b295da6050294fae7fd999"),
k: &hex!("24fc90e1da13f17ef9fe84cc96b9471ed1aaac17e3a4bae33a115df4e5834f18"),
m: &hex!("85b957d92766235e7c880ac5447cfbe97f3cb499f486d1e43bcb5c2ff9608a1a"),
r: &hex!("d7c562370af617b581c84a2468cc8bd50bb1cbf322de41b7887ce07c0e5884ca"),
s: &hex!("b46d9f2d8c4bf83546ff178f1d78937c008d64e8ecc5cbb825cb21d94d670d89"),
},
TestVector {
d: &hex!("53a0e8a8fe93db01e7ae94e1a9882a102ebd079b3a535827d583626c272d280d"),
q_x: &hex!("1bcec4570e1ec2436596b8ded58f60c3b1ebc6a403bc5543040ba82963057244"),
q_y: &hex!("8af62a4c683f096b28558320737bf83b9959a46ad2521004ef74cf85e67494e1"),
k: &hex!("5d833e8d24cc7a402d7ee7ec852a3587cddeb48358cea71b0bedb8fabe84e0c4"),
m: &hex!("3360d699222f21840827cf698d7cb635bee57dc80cd7733b682d41b55b666e22"),
r: &hex!("18caaf7b663507a8bcd992b836dec9dc5703c080af5e51dfa3a9a7c387182604"),
s: &hex!("77c68928ac3b88d985fb43fb615fb7ff45c18ba5c81af796c613dfa98352d29c"),
},
TestVector {
d: &hex!("4af107e8e2194c830ffb712a65511bc9186a133007855b49ab4b3833aefc4a1d"),
q_x: &hex!("a32e50be3dae2c8ba3f5e4bdae14cf7645420d425ead94036c22dd6c4fc59e00"),
q_y: &hex!("d623bf641160c289d6742c6257ae6ba574446dd1d0e74db3aaa80900b78d4ae9"),
k: &hex!("e18f96f84dfa2fd3cdfaec9159d4c338cd54ad314134f0b31e20591fc238d0ab"),
m: &hex!("c413c4908cd0bc6d8e32001aa103043b2cf5be7fcbd61a5cec9488c3a577ca57"),
r: &hex!("8524c5024e2d9a73bde8c72d9129f57873bbad0ed05215a372a84fdbc78f2e68"),
s: &hex!("d18c2caf3b1072f87064ec5e8953f51301cada03469c640244760328eb5a05cb"),
},
TestVector {
d: &hex!("78dfaa09f1076850b3e206e477494cddcfb822aaa0128475053592c48ebaf4ab"),
q_x: &hex!("8bcfe2a721ca6d753968f564ec4315be4857e28bef1908f61a366b1f03c97479"),
q_y: &hex!("0f67576a30b8e20d4232d8530b52fb4c89cbc589ede291e499ddd15fe870ab96"),
k: &hex!("295544dbb2da3da170741c9b2c6551d40af7ed4e891445f11a02b66a5c258a77"),
m: &hex!("88fc1e7d849794fc51b135fa135deec0db02b86c3cd8cebdaa79e8689e5b2898"),
r: &hex!("c5a186d72df452015480f7f338970bfe825087f05c0088d95305f87aacc9b254"),
s: &hex!("84a58f9e9d9e735344b316b1aa1ab5185665b85147dc82d92e969d7bee31ca30"),
},
TestVector {
d: &hex!("80e692e3eb9fcd8c7d44e7de9f7a5952686407f90025a1d87e52c7096a62618a"),
q_x: &hex!("a88bc8430279c8c0400a77d751f26c0abc93e5de4ad9a4166357952fe041e767"),
q_y: &hex!("2d365a1eef25ead579cc9a069b6abc1b16b81c35f18785ce26a10ba6d1381185"),
k: &hex!("7c80fd66d62cc076cef2d030c17c0a69c99611549cb32c4ff662475adbe84b22"),
m: &hex!("41fa8d8b4cd0a5fdf021f4e4829d6d1e996bab6b4a19dcb85585fe76c582d2bc"),
r: &hex!("9d0c6afb6df3bced455b459cc21387e14929392664bb8741a3693a1795ca6902"),
s: &hex!("d7f9ddd191f1f412869429209ee3814c75c72fa46a9cccf804a2f5cc0b7e739f"),
},
TestVector {
d: &hex!("5e666c0db0214c3b627a8e48541cc84a8b6fd15f300da4dff5d18aec6c55b881"),
q_x: &hex!("1bc487570f040dc94196c9befe8ab2b6de77208b1f38bdaae28f9645c4d2bc3a"),
q_y: &hex!("ec81602abd8345e71867c8210313737865b8aa186851e1b48eaca140320f5d8f"),
k: &hex!("2e7625a48874d86c9e467f890aaa7cd6ebdf71c0102bfdcfa24565d6af3fdce9"),
m: &hex!("2d72947c1731543b3d62490866a893952736757746d9bae13e719079299ae192"),
r: &hex!("2f9e2b4e9f747c657f705bffd124ee178bbc5391c86d056717b140c153570fd9"),
s: &hex!("f5413bfd85949da8d83de83ab0d19b2986613e224d1901d76919de23ccd03199"),
},
TestVector {
d: &hex!("f73f455271c877c4d5334627e37c278f68d143014b0a05aa62f308b2101c5308"),
q_x: &hex!("b8188bd68701fc396dab53125d4d28ea33a91daf6d21485f4770f6ea8c565dde"),
q_y: &hex!("423f058810f277f8fe076f6db56e9285a1bf2c2a1dae145095edd9c04970bc4a"),
k: &hex!("62f8665fd6e26b3fa069e85281777a9b1f0dfd2c0b9f54a086d0c109ff9fd615"),
m: &hex!("e138bd577c3729d0e24a98a82478bcc7482499c4cdf734a874f7208ddbc3c116"),
r: &hex!("1cc628533d0004b2b20e7f4baad0b8bb5e0673db159bbccf92491aef61fc9620"),
s: &hex!("880e0bbf82a8cf818ed46ba03cf0fc6c898e36fca36cc7fdb1d2db7503634430"),
},
TestVector {
d: &hex!("b20d705d9bd7c2b8dc60393a5357f632990e599a0975573ac67fd89b49187906"),
q_x: &hex!("51f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce"),
q_y: &hex!("4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1"),
k: &hex!("72b656f6b35b9ccbc712c9f1f3b1a14cbbebaec41c4bca8da18f492a062d6f6f"),
m: &hex!("17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8"),
r: &hex!("9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c42"),
s: &hex!("2bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c"),
},
TestVector {
d: &hex!("d4234bebfbc821050341a37e1240efe5e33763cbbb2ef76a1c79e24724e5a5e7"),
q_x: &hex!("8fb287f0202ad57ae841aea35f29b2e1d53e196d0ddd9aec24813d64c0922fb7"),
q_y: &hex!("1f6daff1aa2dd2d6d3741623eecb5e7b612997a1039aab2e5cf2de969cfea573"),
k: &hex!("d926fe10f1bfd9855610f4f5a3d666b1a149344057e35537373372ead8b1a778"),
m: &hex!("c25beae638ff8dcd370e03a6f89c594c55bed1277ee14d83bbb0ef783a0517c7"),
r: &hex!("490efd106be11fc365c7467eb89b8d39e15d65175356775deab211163c2504cb"),
s: &hex!("644300fc0da4d40fb8c6ead510d14f0bd4e1321a469e9c0a581464c7186b7aa7"),
},
TestVector {
d: &hex!("b58f5211dff440626bb56d0ad483193d606cf21f36d9830543327292f4d25d8c"),
q_x: &hex!("68229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76"),
q_y: &hex!("303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c"),
k: &hex!("e158bf4a2d19a99149d9cdb879294ccb7aaeae03d75ddd616ef8ae51a6dc1071"),
m: &hex!("5eb28029ebf3c7025ff2fc2f6de6f62aecf6a72139e1cba5f20d11bbef036a7f"),
r: &hex!("e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb"),
s: &hex!("9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333"),
},
TestVector {
d: &hex!("54c066711cdb061eda07e5275f7e95a9962c6764b84f6f1f3ab5a588e0a2afb1"),
q_x: &hex!("0a7dbb8bf50cb605eb2268b081f26d6b08e012f952c4b70a5a1e6e7d46af98bb"),
q_y: &hex!("f26dd7d799930062480849962ccf5004edcfd307c044f4e8f667c9baa834eeae"),
k: &hex!("646fe933e96c3b8f9f507498e907fdd201f08478d0202c752a7c2cfebf4d061a"),
m: &hex!("12135386c09e0bf6fd5c454a95bcfe9b3edb25c71e455c73a212405694b29002"),
r: &hex!("b53ce4da1aa7c0dc77a1896ab716b921499aed78df725b1504aba1597ba0c64b"),
s: &hex!("d7c246dc7ad0e67700c373edcfdd1c0a0495fc954549ad579df6ed1438840851"),
},
TestVector {
d: &hex!("34fa4682bf6cb5b16783adcd18f0e6879b92185f76d7c920409f904f522db4b1"),
q_x: &hex!("105d22d9c626520faca13e7ced382dcbe93498315f00cc0ac39c4821d0d73737"),
q_y: &hex!("6c47f3cbbfa97dfcebe16270b8c7d5d3a5900b888c42520d751e8faf3b401ef4"),
k: &hex!("a6f463ee72c9492bc792fe98163112837aebd07bab7a84aaed05be64db3086f4"),
m: &hex!("aea3e069e03c0ff4d6b3fa2235e0053bbedc4c7e40efbc686d4dfb5efba4cfed"),
r: &hex!("542c40a18140a6266d6f0286e24e9a7bad7650e72ef0e2131e629c076d962663"),
s: &hex!("4f7f65305e24a6bbb5cff714ba8f5a2cee5bdc89ba8d75dcbf21966ce38eb66f"),
},
];

257
vendor/p256/src/test_vectors/field.rs vendored Normal file
View File

@@ -0,0 +1,257 @@
//! Test vectors for the secp256r1 base field.
use hex_literal::hex;
/// Repeated doubling of the multiplicative identity.
pub const DBL_TEST_VECTORS: &[[u8; 32]] = &[
hex!("0000000000000000000000000000000000000000000000000000000000000001"),
hex!("0000000000000000000000000000000000000000000000000000000000000002"),
hex!("0000000000000000000000000000000000000000000000000000000000000004"),
hex!("0000000000000000000000000000000000000000000000000000000000000008"),
hex!("0000000000000000000000000000000000000000000000000000000000000010"),
hex!("0000000000000000000000000000000000000000000000000000000000000020"),
hex!("0000000000000000000000000000000000000000000000000000000000000040"),
hex!("0000000000000000000000000000000000000000000000000000000000000080"),
hex!("0000000000000000000000000000000000000000000000000000000000000100"),
hex!("0000000000000000000000000000000000000000000000000000000000000200"),
hex!("0000000000000000000000000000000000000000000000000000000000000400"),
hex!("0000000000000000000000000000000000000000000000000000000000000800"),
hex!("0000000000000000000000000000000000000000000000000000000000001000"),
hex!("0000000000000000000000000000000000000000000000000000000000002000"),
hex!("0000000000000000000000000000000000000000000000000000000000004000"),
hex!("0000000000000000000000000000000000000000000000000000000000008000"),
hex!("0000000000000000000000000000000000000000000000000000000000010000"),
hex!("0000000000000000000000000000000000000000000000000000000000020000"),
hex!("0000000000000000000000000000000000000000000000000000000000040000"),
hex!("0000000000000000000000000000000000000000000000000000000000080000"),
hex!("0000000000000000000000000000000000000000000000000000000000100000"),
hex!("0000000000000000000000000000000000000000000000000000000000200000"),
hex!("0000000000000000000000000000000000000000000000000000000000400000"),
hex!("0000000000000000000000000000000000000000000000000000000000800000"),
hex!("0000000000000000000000000000000000000000000000000000000001000000"),
hex!("0000000000000000000000000000000000000000000000000000000002000000"),
hex!("0000000000000000000000000000000000000000000000000000000004000000"),
hex!("0000000000000000000000000000000000000000000000000000000008000000"),
hex!("0000000000000000000000000000000000000000000000000000000010000000"),
hex!("0000000000000000000000000000000000000000000000000000000020000000"),
hex!("0000000000000000000000000000000000000000000000000000000040000000"),
hex!("0000000000000000000000000000000000000000000000000000000080000000"),
hex!("0000000000000000000000000000000000000000000000000000000100000000"),
hex!("0000000000000000000000000000000000000000000000000000000200000000"),
hex!("0000000000000000000000000000000000000000000000000000000400000000"),
hex!("0000000000000000000000000000000000000000000000000000000800000000"),
hex!("0000000000000000000000000000000000000000000000000000001000000000"),
hex!("0000000000000000000000000000000000000000000000000000002000000000"),
hex!("0000000000000000000000000000000000000000000000000000004000000000"),
hex!("0000000000000000000000000000000000000000000000000000008000000000"),
hex!("0000000000000000000000000000000000000000000000000000010000000000"),
hex!("0000000000000000000000000000000000000000000000000000020000000000"),
hex!("0000000000000000000000000000000000000000000000000000040000000000"),
hex!("0000000000000000000000000000000000000000000000000000080000000000"),
hex!("0000000000000000000000000000000000000000000000000000100000000000"),
hex!("0000000000000000000000000000000000000000000000000000200000000000"),
hex!("0000000000000000000000000000000000000000000000000000400000000000"),
hex!("0000000000000000000000000000000000000000000000000000800000000000"),
hex!("0000000000000000000000000000000000000000000000000001000000000000"),
hex!("0000000000000000000000000000000000000000000000000002000000000000"),
hex!("0000000000000000000000000000000000000000000000000004000000000000"),
hex!("0000000000000000000000000000000000000000000000000008000000000000"),
hex!("0000000000000000000000000000000000000000000000000010000000000000"),
hex!("0000000000000000000000000000000000000000000000000020000000000000"),
hex!("0000000000000000000000000000000000000000000000000040000000000000"),
hex!("0000000000000000000000000000000000000000000000000080000000000000"),
hex!("0000000000000000000000000000000000000000000000000100000000000000"),
hex!("0000000000000000000000000000000000000000000000000200000000000000"),
hex!("0000000000000000000000000000000000000000000000000400000000000000"),
hex!("0000000000000000000000000000000000000000000000000800000000000000"),
hex!("0000000000000000000000000000000000000000000000001000000000000000"),
hex!("0000000000000000000000000000000000000000000000002000000000000000"),
hex!("0000000000000000000000000000000000000000000000004000000000000000"),
hex!("0000000000000000000000000000000000000000000000008000000000000000"),
hex!("0000000000000000000000000000000000000000000000010000000000000000"),
hex!("0000000000000000000000000000000000000000000000020000000000000000"),
hex!("0000000000000000000000000000000000000000000000040000000000000000"),
hex!("0000000000000000000000000000000000000000000000080000000000000000"),
hex!("0000000000000000000000000000000000000000000000100000000000000000"),
hex!("0000000000000000000000000000000000000000000000200000000000000000"),
hex!("0000000000000000000000000000000000000000000000400000000000000000"),
hex!("0000000000000000000000000000000000000000000000800000000000000000"),
hex!("0000000000000000000000000000000000000000000001000000000000000000"),
hex!("0000000000000000000000000000000000000000000002000000000000000000"),
hex!("0000000000000000000000000000000000000000000004000000000000000000"),
hex!("0000000000000000000000000000000000000000000008000000000000000000"),
hex!("0000000000000000000000000000000000000000000010000000000000000000"),
hex!("0000000000000000000000000000000000000000000020000000000000000000"),
hex!("0000000000000000000000000000000000000000000040000000000000000000"),
hex!("0000000000000000000000000000000000000000000080000000000000000000"),
hex!("0000000000000000000000000000000000000000000100000000000000000000"),
hex!("0000000000000000000000000000000000000000000200000000000000000000"),
hex!("0000000000000000000000000000000000000000000400000000000000000000"),
hex!("0000000000000000000000000000000000000000000800000000000000000000"),
hex!("0000000000000000000000000000000000000000001000000000000000000000"),
hex!("0000000000000000000000000000000000000000002000000000000000000000"),
hex!("0000000000000000000000000000000000000000004000000000000000000000"),
hex!("0000000000000000000000000000000000000000008000000000000000000000"),
hex!("0000000000000000000000000000000000000000010000000000000000000000"),
hex!("0000000000000000000000000000000000000000020000000000000000000000"),
hex!("0000000000000000000000000000000000000000040000000000000000000000"),
hex!("0000000000000000000000000000000000000000080000000000000000000000"),
hex!("0000000000000000000000000000000000000000100000000000000000000000"),
hex!("0000000000000000000000000000000000000000200000000000000000000000"),
hex!("0000000000000000000000000000000000000000400000000000000000000000"),
hex!("0000000000000000000000000000000000000000800000000000000000000000"),
hex!("0000000000000000000000000000000000000001000000000000000000000000"),
hex!("0000000000000000000000000000000000000002000000000000000000000000"),
hex!("0000000000000000000000000000000000000004000000000000000000000000"),
hex!("0000000000000000000000000000000000000008000000000000000000000000"),
hex!("0000000000000000000000000000000000000010000000000000000000000000"),
hex!("0000000000000000000000000000000000000020000000000000000000000000"),
hex!("0000000000000000000000000000000000000040000000000000000000000000"),
hex!("0000000000000000000000000000000000000080000000000000000000000000"),
hex!("0000000000000000000000000000000000000100000000000000000000000000"),
hex!("0000000000000000000000000000000000000200000000000000000000000000"),
hex!("0000000000000000000000000000000000000400000000000000000000000000"),
hex!("0000000000000000000000000000000000000800000000000000000000000000"),
hex!("0000000000000000000000000000000000001000000000000000000000000000"),
hex!("0000000000000000000000000000000000002000000000000000000000000000"),
hex!("0000000000000000000000000000000000004000000000000000000000000000"),
hex!("0000000000000000000000000000000000008000000000000000000000000000"),
hex!("0000000000000000000000000000000000010000000000000000000000000000"),
hex!("0000000000000000000000000000000000020000000000000000000000000000"),
hex!("0000000000000000000000000000000000040000000000000000000000000000"),
hex!("0000000000000000000000000000000000080000000000000000000000000000"),
hex!("0000000000000000000000000000000000100000000000000000000000000000"),
hex!("0000000000000000000000000000000000200000000000000000000000000000"),
hex!("0000000000000000000000000000000000400000000000000000000000000000"),
hex!("0000000000000000000000000000000000800000000000000000000000000000"),
hex!("0000000000000000000000000000000001000000000000000000000000000000"),
hex!("0000000000000000000000000000000002000000000000000000000000000000"),
hex!("0000000000000000000000000000000004000000000000000000000000000000"),
hex!("0000000000000000000000000000000008000000000000000000000000000000"),
hex!("0000000000000000000000000000000010000000000000000000000000000000"),
hex!("0000000000000000000000000000000020000000000000000000000000000000"),
hex!("0000000000000000000000000000000040000000000000000000000000000000"),
hex!("0000000000000000000000000000000080000000000000000000000000000000"),
hex!("0000000000000000000000000000000100000000000000000000000000000000"),
hex!("0000000000000000000000000000000200000000000000000000000000000000"),
hex!("0000000000000000000000000000000400000000000000000000000000000000"),
hex!("0000000000000000000000000000000800000000000000000000000000000000"),
hex!("0000000000000000000000000000001000000000000000000000000000000000"),
hex!("0000000000000000000000000000002000000000000000000000000000000000"),
hex!("0000000000000000000000000000004000000000000000000000000000000000"),
hex!("0000000000000000000000000000008000000000000000000000000000000000"),
hex!("0000000000000000000000000000010000000000000000000000000000000000"),
hex!("0000000000000000000000000000020000000000000000000000000000000000"),
hex!("0000000000000000000000000000040000000000000000000000000000000000"),
hex!("0000000000000000000000000000080000000000000000000000000000000000"),
hex!("0000000000000000000000000000100000000000000000000000000000000000"),
hex!("0000000000000000000000000000200000000000000000000000000000000000"),
hex!("0000000000000000000000000000400000000000000000000000000000000000"),
hex!("0000000000000000000000000000800000000000000000000000000000000000"),
hex!("0000000000000000000000000001000000000000000000000000000000000000"),
hex!("0000000000000000000000000002000000000000000000000000000000000000"),
hex!("0000000000000000000000000004000000000000000000000000000000000000"),
hex!("0000000000000000000000000008000000000000000000000000000000000000"),
hex!("0000000000000000000000000010000000000000000000000000000000000000"),
hex!("0000000000000000000000000020000000000000000000000000000000000000"),
hex!("0000000000000000000000000040000000000000000000000000000000000000"),
hex!("0000000000000000000000000080000000000000000000000000000000000000"),
hex!("0000000000000000000000000100000000000000000000000000000000000000"),
hex!("0000000000000000000000000200000000000000000000000000000000000000"),
hex!("0000000000000000000000000400000000000000000000000000000000000000"),
hex!("0000000000000000000000000800000000000000000000000000000000000000"),
hex!("0000000000000000000000001000000000000000000000000000000000000000"),
hex!("0000000000000000000000002000000000000000000000000000000000000000"),
hex!("0000000000000000000000004000000000000000000000000000000000000000"),
hex!("0000000000000000000000008000000000000000000000000000000000000000"),
hex!("0000000000000000000000010000000000000000000000000000000000000000"),
hex!("0000000000000000000000020000000000000000000000000000000000000000"),
hex!("0000000000000000000000040000000000000000000000000000000000000000"),
hex!("0000000000000000000000080000000000000000000000000000000000000000"),
hex!("0000000000000000000000100000000000000000000000000000000000000000"),
hex!("0000000000000000000000200000000000000000000000000000000000000000"),
hex!("0000000000000000000000400000000000000000000000000000000000000000"),
hex!("0000000000000000000000800000000000000000000000000000000000000000"),
hex!("0000000000000000000001000000000000000000000000000000000000000000"),
hex!("0000000000000000000002000000000000000000000000000000000000000000"),
hex!("0000000000000000000004000000000000000000000000000000000000000000"),
hex!("0000000000000000000008000000000000000000000000000000000000000000"),
hex!("0000000000000000000010000000000000000000000000000000000000000000"),
hex!("0000000000000000000020000000000000000000000000000000000000000000"),
hex!("0000000000000000000040000000000000000000000000000000000000000000"),
hex!("0000000000000000000080000000000000000000000000000000000000000000"),
hex!("0000000000000000000100000000000000000000000000000000000000000000"),
hex!("0000000000000000000200000000000000000000000000000000000000000000"),
hex!("0000000000000000000400000000000000000000000000000000000000000000"),
hex!("0000000000000000000800000000000000000000000000000000000000000000"),
hex!("0000000000000000001000000000000000000000000000000000000000000000"),
hex!("0000000000000000002000000000000000000000000000000000000000000000"),
hex!("0000000000000000004000000000000000000000000000000000000000000000"),
hex!("0000000000000000008000000000000000000000000000000000000000000000"),
hex!("0000000000000000010000000000000000000000000000000000000000000000"),
hex!("0000000000000000020000000000000000000000000000000000000000000000"),
hex!("0000000000000000040000000000000000000000000000000000000000000000"),
hex!("0000000000000000080000000000000000000000000000000000000000000000"),
hex!("0000000000000000100000000000000000000000000000000000000000000000"),
hex!("0000000000000000200000000000000000000000000000000000000000000000"),
hex!("0000000000000000400000000000000000000000000000000000000000000000"),
hex!("0000000000000000800000000000000000000000000000000000000000000000"),
hex!("0000000000000001000000000000000000000000000000000000000000000000"),
hex!("0000000000000002000000000000000000000000000000000000000000000000"),
hex!("0000000000000004000000000000000000000000000000000000000000000000"),
hex!("0000000000000008000000000000000000000000000000000000000000000000"),
hex!("0000000000000010000000000000000000000000000000000000000000000000"),
hex!("0000000000000020000000000000000000000000000000000000000000000000"),
hex!("0000000000000040000000000000000000000000000000000000000000000000"),
hex!("0000000000000080000000000000000000000000000000000000000000000000"),
hex!("0000000000000100000000000000000000000000000000000000000000000000"),
hex!("0000000000000200000000000000000000000000000000000000000000000000"),
hex!("0000000000000400000000000000000000000000000000000000000000000000"),
hex!("0000000000000800000000000000000000000000000000000000000000000000"),
hex!("0000000000001000000000000000000000000000000000000000000000000000"),
hex!("0000000000002000000000000000000000000000000000000000000000000000"),
hex!("0000000000004000000000000000000000000000000000000000000000000000"),
hex!("0000000000008000000000000000000000000000000000000000000000000000"),
hex!("0000000000010000000000000000000000000000000000000000000000000000"),
hex!("0000000000020000000000000000000000000000000000000000000000000000"),
hex!("0000000000040000000000000000000000000000000000000000000000000000"),
hex!("0000000000080000000000000000000000000000000000000000000000000000"),
hex!("0000000000100000000000000000000000000000000000000000000000000000"),
hex!("0000000000200000000000000000000000000000000000000000000000000000"),
hex!("0000000000400000000000000000000000000000000000000000000000000000"),
hex!("0000000000800000000000000000000000000000000000000000000000000000"),
hex!("0000000001000000000000000000000000000000000000000000000000000000"),
hex!("0000000002000000000000000000000000000000000000000000000000000000"),
hex!("0000000004000000000000000000000000000000000000000000000000000000"),
hex!("0000000008000000000000000000000000000000000000000000000000000000"),
hex!("0000000010000000000000000000000000000000000000000000000000000000"),
hex!("0000000020000000000000000000000000000000000000000000000000000000"),
hex!("0000000040000000000000000000000000000000000000000000000000000000"),
hex!("0000000080000000000000000000000000000000000000000000000000000000"),
hex!("0000000100000000000000000000000000000000000000000000000000000000"),
hex!("0000000200000000000000000000000000000000000000000000000000000000"),
hex!("0000000400000000000000000000000000000000000000000000000000000000"),
hex!("0000000800000000000000000000000000000000000000000000000000000000"),
hex!("0000001000000000000000000000000000000000000000000000000000000000"),
hex!("0000002000000000000000000000000000000000000000000000000000000000"),
hex!("0000004000000000000000000000000000000000000000000000000000000000"),
hex!("0000008000000000000000000000000000000000000000000000000000000000"),
hex!("0000010000000000000000000000000000000000000000000000000000000000"),
hex!("0000020000000000000000000000000000000000000000000000000000000000"),
hex!("0000040000000000000000000000000000000000000000000000000000000000"),
hex!("0000080000000000000000000000000000000000000000000000000000000000"),
hex!("0000100000000000000000000000000000000000000000000000000000000000"),
hex!("0000200000000000000000000000000000000000000000000000000000000000"),
hex!("0000400000000000000000000000000000000000000000000000000000000000"),
hex!("0000800000000000000000000000000000000000000000000000000000000000"),
hex!("0001000000000000000000000000000000000000000000000000000000000000"),
hex!("0002000000000000000000000000000000000000000000000000000000000000"),
hex!("0004000000000000000000000000000000000000000000000000000000000000"),
hex!("0008000000000000000000000000000000000000000000000000000000000000"),
hex!("0010000000000000000000000000000000000000000000000000000000000000"),
hex!("0020000000000000000000000000000000000000000000000000000000000000"),
hex!("0040000000000000000000000000000000000000000000000000000000000000"),
hex!("0080000000000000000000000000000000000000000000000000000000000000"),
hex!("0100000000000000000000000000000000000000000000000000000000000000"),
hex!("0200000000000000000000000000000000000000000000000000000000000000"),
];

256
vendor/p256/src/test_vectors/group.rs vendored Normal file
View File

@@ -0,0 +1,256 @@
//! Test vectors for the secp256r1 group.
use hex_literal::hex;
/// Repeated addition of the generator.
///
/// These are the first 20 test vectors from <http://point-at-infinity.org/ecc/nisttv>
pub const ADD_TEST_VECTORS: &[([u8; 32], [u8; 32])] = &[
(
hex!("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"),
hex!("4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"),
),
(
hex!("7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978"),
hex!("07775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1"),
),
(
hex!("5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C"),
hex!("8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032"),
),
(
hex!("E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852"),
hex!("E0F1575A4C633CC719DFEE5FDA862D764EFC96C3F30EE0055C42C23F184ED8C6"),
),
(
hex!("51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED"),
hex!("E0C17DA8904A727D8AE1BF36BF8A79260D012F00D4D80888D1D0BB44FDA16DA4"),
),
(
hex!("B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9"),
hex!("E85C10743237DAD56FEC0E2DFBA703791C00F7701C7E16BDFD7C48538FC77FE2"),
),
(
hex!("8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3"),
hex!("73EB1DBDE03318366D069F83A6F5900053C73633CB041B21C55E1A86C1F400B4"),
),
(
hex!("62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393"),
hex!("AD5ACCBD91E9D8244FF15D771167CEE0A2ED51F6BBE76A78DA540A6A0F09957E"),
),
(
hex!("EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0"),
hex!("2A2744C972C9FCE787014A964A8EA0C84D714FEAA4DE823FE85A224A4DD048FA"),
),
(
hex!("CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F"),
hex!("878662A229AAAE906E123CDD9D3B4C10590DED29FE751EEECA34BBAA44AF0773"),
),
(
hex!("3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1"),
hex!("9099209ACCC4C8A224C843AFA4F4C68A090D04DA5E9889DAE2F8EEFCE82A3740"),
),
(
hex!("741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4"),
hex!("0770B46A9C385FDC567383554887B1548EEB912C35BA5CA71995FF22CD4481D3"),
),
(
hex!("177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01"),
hex!("63BB58CD4EBEA558A24091ADB40F4E7226EE14C3A1FB4DF39C43BBE2EFC7BFD8"),
),
(
hex!("54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B"),
hex!("F599F1BB29F4317542121F8C05A2E7C37171EA77735090081BA7C82F60D0B375"),
),
(
hex!("F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F"),
hex!("B5B93EE3592E2D1F4E6594E51F9643E62A3B21CE75B5FA3F47E59CDE0D034F36"),
),
(
hex!("76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E"),
hex!("A985FE61341F260E6CB0A1B5E11E87208599A0040FC78BAA0E9DDD724B8C5110"),
),
(
hex!("47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E"),
hex!("AA005EE6B5B957286231856577648E8381B2804428D5733F32F787FF71F1FCDC"),
),
(
hex!("1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA"),
hex!("F6F1645A15CBE5DC9FA9B7DFD96EE5A7DCC11B5C5EF4F1F78D83B3393C6A45A2"),
),
(
hex!("CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83"),
hex!("58D7614B24D9EF515C35E7100D6D6CE4A496716E30FA3E03E39150752BCECDAA"),
),
(
hex!("83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A"),
hex!("76E49B6DE2F73234AE6A5EB9D612B75C9F2202BB6923F54FF8240AAA86F640B8"),
),
];
/// Scalar multiplication with the generator.
///
/// These are the test vectors from <http://point-at-infinity.org/ecc/nisttv> that are not
/// part of [`ADD_TEST_VECTORS`].
pub const MUL_TEST_VECTORS: &[([u8; 32], [u8; 32], [u8; 32])] = &[
(
hex!("000000000000000000000000000000000000000000000000018EBBB95EED0E13"),
hex!("339150844EC15234807FE862A86BE77977DBFB3AE3D96F4C22795513AEAAB82F"),
hex!("B1C14DDFDC8EC1B2583F51E85A5EB3A155840F2034730E9B5ADA38B674336A21"),
),
(
hex!("0000000000000000000000000000000000159D893D4CDD747246CDCA43590E13"),
hex!("1B7E046A076CC25E6D7FA5003F6729F665CC3241B5ADAB12B498CD32F2803264"),
hex!("BFEA79BE2B666B073DB69A2A241ADAB0738FE9D2DD28B5604EB8C8CF097C457B"),
),
(
hex!("41FFC1FFFFFE01FFFC0003FFFE0007C001FFF00003FFF07FFE0007C000000003"),
hex!("9EACE8F4B071E677C5350B02F2BB2B384AAE89D58AA72CA97A170572E0FB222F"),
hex!("1BBDAEC2430B09B93F7CB08678636CE12EAAFD58390699B5FD2F6E1188FC2A78"),
),
(
hex!("7FFFFFC03FFFC003FFFFFC007FFF00000000070000100000000E00FFFFFFF3FF"),
hex!("878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D"),
hex!("714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E"),
),
(
hex!("0000FFFFF01FFFF8FFFFC00FFFFFFFFFC000000FFFFFC007FFFFFC000FFFE3FF"),
hex!("659A379625AB122F2512B8DADA02C6348D53B54452DFF67AC7ACE4E8856295CA"),
hex!("49D81AB97B648464D0B4A288BD7818FAB41A16426E943527C4FED8736C53D0F6"),
),
(
hex!("4000008000FFFFFC000003F00000FFFFFFFF800003800F8000E0000E000000FF"),
hex!("CBCEAAA8A4DD44BBCE58E8DB7740A5510EC2CB7EA8DA8D8F036B3FB04CDA4DE4"),
hex!("4BD7AA301A80D7F59FD983FEDBE59BB7B2863FE46494935E3745B360E32332FA"),
),
(
hex!("003FFFFFF0001F80000003F80003FFFFC0000000000FFE0000007FF818000F80"),
hex!("F0C4A0576154FF3A33A3460D42EAED806E854DFA37125221D37935124BA462A4"),
hex!("5B392FA964434D29EEC6C9DBC261CF116796864AA2FAADB984A2DF38D1AEF7A3"),
),
(
hex!("000001C000000000001001F803FFFFFF80000000000007FF0000000000000000"),
hex!("5E6C8524B6369530B12C62D31EC53E0288173BD662BDF680B53A41ECBCAD00CC"),
hex!("447FE742C2BFEF4D0DB14B5B83A2682309B5618E0064A94804E9282179FE089F"),
),
(
hex!("7FC0007FFFFFFC0003FFFFFFFFFFFFFE00003FFFFF07FFFFFFFFFFFFC007FFFF"),
hex!("03792E541BC209076A3D7920A915021ECD396A6EB5C3960024BE5575F3223484"),
hex!("FC774AE092403101563B712F68170312304F20C80B40C06282063DB25F268DE4"),
),
(
hex!("7FFFFC03FF807FFFE0001FFFFF800FFF800001FFFF0001FFFFFE001FFFC00000"),
hex!("2379FF85AB693CDF901D6CE6F2473F39C04A2FE3DCD842CE7AAB0E002095BCF8"),
hex!("F8B476530A634589D5129E46F322B02FBC610A703D80875EE70D7CE1877436A1"),
),
(
hex!("00FFFFFFFE03FFFC07FFFC800070000FC0007FFC00000000000FFFE1FBFF81FF"),
hex!("C1E4072C529BF2F44DA769EFC934472848003B3AF2C0F5AA8F8DDBD53E12ED7C"),
hex!("39A6EE77812BB37E8079CD01ED649D3830FCA46F718C1D3993E4A591824ABCDB"),
),
(
hex!("01FFF81FC000000000FF801FFFC0F81F01FFF8001FC005FFFFFF800000FFFFFC"),
hex!("34DFBC09404C21E250A9B40FA8772897AC63A094877DB65862B61BD1507B34F3"),
hex!("CF6F8A876C6F99CEAEC87148F18C7E1E0DA6E165FFC8ED82ABB65955215F77D3"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63253D"),
hex!("83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A"),
hex!("891B64911D08CDCC5195A14629ED48A360DDFD4596DC0AB007DBF5557909BF47"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63253E"),
hex!("CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83"),
hex!("A7289EB3DB2610AFA3CA18EFF292931B5B698E92CF05C1FC1C6EAF8AD4313255"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63253F"),
hex!("1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA"),
hex!("090E9BA4EA341A246056482026911A58233EE4A4A10B0E08727C4CC6C395BA5D"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632540"),
hex!("47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E"),
hex!("55FFA1184A46A8D89DCE7A9A889B717C7E4D7FBCD72A8CC0CD0878008E0E0323"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632541"),
hex!("76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E"),
hex!("567A019DCBE0D9F2934F5E4A1EE178DF7A665FFCF0387455F162228DB473AEEF"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632542"),
hex!("F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F"),
hex!("4A46C11BA6D1D2E1B19A6B1AE069BC19D5C4DE328A4A05C0B81A6321F2FCB0C9"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632543"),
hex!("54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B"),
hex!("0A660E43D60BCE8BBDEDE073FA5D183C8E8E15898CAF6FF7E45837D09F2F4C8A"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632544"),
hex!("177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01"),
hex!("9C44A731B1415AA85DBF6E524BF0B18DD911EB3D5E04B20C63BC441D10384027"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632545"),
hex!("741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4"),
hex!("F88F4B9463C7A024A98C7CAAB7784EAB71146ED4CA45A358E66A00DD32BB7E2C"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632546"),
hex!("3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1"),
hex!("6F66DF64333B375EDB37BC505B0B3975F6F2FB26A16776251D07110317D5C8BF"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632547"),
hex!("CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F"),
hex!("78799D5CD655517091EDC32262C4B3EFA6F212D7018AE11135CB4455BB50F88C"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632548"),
hex!("EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0"),
hex!("D5D8BB358D36031978FEB569B5715F37B28EB0165B217DC017A5DDB5B22FB705"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632549"),
hex!("62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393"),
hex!("52A533416E1627DCB00EA288EE98311F5D12AE0A4418958725ABF595F0F66A81"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254A"),
hex!("8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3"),
hex!("8C14E2411FCCE7CA92F9607C590A6FFFAC38C9CD34FBE4DE3AA1E5793E0BFF4B"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254B"),
hex!("B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9"),
hex!("17A3EF8ACDC8252B9013F1D20458FC86E3FF0890E381E9420283B7AC7038801D"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254C"),
hex!("51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED"),
hex!("1F3E82566FB58D83751E40C9407586D9F2FED1002B27F7772E2F44BB025E925B"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254D"),
hex!("E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852"),
hex!("1F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E"),
hex!("5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C"),
hex!("78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F"),
hex!("7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978"),
hex!("F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E"),
),
(
hex!("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550"),
hex!("6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"),
hex!("B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A"),
),
];