1use std::str::FromStr;
5
6use elliptic_curve::{sec1::ToEncodedPoint, subtle::Choice};
7use generic_array::GenericArray;
8use num::{
9 traits::{FromBytes, ToBytes},
10 BigUint,
11};
12use p256::{elliptic_curve::point::DecompressPoint, FieldElement};
13use serde::{Deserialize, Serialize};
14use typenum::{U32, U62};
15
16use super::{SwCurve, WeierstrassParameters};
17use crate::{
18 params::{FieldParameters, NumLimbs},
19 AffinePoint, CurveType, EllipticCurve, EllipticCurveParameters,
20};
21
22#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
23pub struct Secp256r1Parameters;
25
26pub type Secp256r1 = SwCurve<Secp256r1Parameters>;
27
28#[derive(Debug, Default, Clone, Copy, PartialEq, Serialize, Deserialize)]
29pub struct Secp256r1BaseField;
31
32impl FieldParameters for Secp256r1BaseField {
33 const MODULUS: &'static [u8] = &[
34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff,
36 0xff, 0xff,
37 ];
38 const WITNESS_OFFSET: usize = 1usize << 14;
40
41 fn modulus() -> BigUint {
42 BigUint::from_bytes_le(Self::MODULUS)
43 }
44}
45
46impl NumLimbs for Secp256r1BaseField {
47 type Limbs = U32;
48 type Witness = U62;
49}
50
51impl EllipticCurveParameters for Secp256r1Parameters {
52 type BaseField = Secp256r1BaseField;
53 const CURVE_TYPE: CurveType = CurveType::Secp256r1;
54}
55
56impl WeierstrassParameters for Secp256r1Parameters {
57 const A: GenericArray<u8, U32> = GenericArray::from_array([
58 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 1, 0, 0, 0, 255, 255, 255, 255,
60 ]);
61
62 const B: GenericArray<u8, U32> = GenericArray::from_array([
63 75, 96, 210, 39, 62, 60, 206, 59, 246, 176, 83, 204, 176, 6, 29, 101, 188, 134, 152, 118,
64 85, 189, 235, 179, 231, 147, 58, 170, 216, 53, 198, 90,
65 ]);
66
67 fn generator() -> (BigUint, BigUint) {
68 let x = BigUint::from_str(
69 "48439561293906451759052585252797914202762949526041747995844080717082404635286",
70 )
71 .unwrap();
72 let y = BigUint::from_str(
73 "36134250956749795798585127919587881956611106672985015071877198253568414405109",
74 )
75 .unwrap();
76 (x, y)
77 }
78
79 fn prime_group_order() -> num::BigUint {
80 BigUint::from_slice(&[
81 0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
82 0xFFFFFFFF,
83 ])
84 }
85
86 fn a_int() -> BigUint {
87 BigUint::from_slice(&[
88 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
89 0xFFFFFFFF,
90 ])
91 }
92
93 fn b_int() -> BigUint {
94 BigUint::from_slice(&[
95 0x27D2604B, 0x3BCE3C3E, 0xCC53B0F6, 0x651D06B0, 0x769886BC, 0xB3EBBD55, 0xAA3A93E7,
96 0x5AC635D8,
97 ])
98 }
99}
100
101pub fn secp256r1_decompress<E: EllipticCurve>(bytes_be: &[u8], sign: u32) -> AffinePoint<E> {
102 let computed_point =
103 p256::AffinePoint::decompress(bytes_be.into(), Choice::from(sign as u8)).unwrap();
104 let point = computed_point.to_encoded_point(false);
105
106 let x = BigUint::from_bytes_be(point.x().unwrap());
107 let y = BigUint::from_bytes_be(point.y().unwrap());
108 AffinePoint::<E>::new(x, y)
109}
110
111pub fn secp256r1_sqrt(n: &BigUint) -> BigUint {
112 let be_bytes = n.to_be_bytes();
113 let mut bytes = [0_u8; 32];
114 bytes[32 - be_bytes.len()..].copy_from_slice(&be_bytes);
115 let fe = FieldElement::from_bytes(&bytes.into()).unwrap();
116 let result_bytes = fe.sqrt().unwrap().to_bytes();
117 BigUint::from_be_bytes(&result_bytes as &[u8])
118}
119
120#[cfg(test)]
121mod tests {
122
123 use super::*;
124 use crate::utils::biguint_from_limbs;
125 use num::bigint::RandBigInt;
126 use rand::thread_rng;
127
128 #[test]
129 fn test_weierstrass_biguint_scalar_mul() {
130 assert_eq!(biguint_from_limbs(Secp256r1BaseField::MODULUS), Secp256r1BaseField::modulus());
131 }
132
133 #[test]
134 fn test_secp256r_sqrt() {
135 let mut rng = thread_rng();
136 for _ in 0..10 {
137 let x = rng.gen_biguint(256) % Secp256r1BaseField::modulus();
140 let x_2 = (&x * &x) % Secp256r1BaseField::modulus(); let sqrt = secp256r1_sqrt(&x_2); let sqrt_2 = (&sqrt * &sqrt) % Secp256r1BaseField::modulus();
143
144 assert_eq!(sqrt_2, x_2);
145 }
146 }
147}