1use core::{
2 cmp,
3 fmt::Debug,
4 iter::Sum,
5 ops::{Add, Mul, Neg, Sub},
6};
7
8use rand::RngCore;
9use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
10
11use crate::{
12 ff::{Field, PrimeField, WithSmallOrderMulGroup},
13 group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding},
14 secp256r1::{Fp, Fq},
15 Coordinates, CurveAffine, CurveExt,
16};
17
18impl group::cofactor::CofactorGroup for Secp256r1 {
19 type Subgroup = Secp256r1;
20
21 fn clear_cofactor(&self) -> Self {
22 *self
23 }
24
25 fn into_subgroup(self) -> CtOption<Self::Subgroup> {
26 CtOption::new(self, 1.into())
27 }
28
29 fn is_torsion_free(&self) -> Choice {
30 1.into()
31 }
32}
33
34const SECP_GENERATOR_X: Fp = Fp::from_raw([
36 0xF4A13945D898C296,
37 0x77037D812DEB33A0,
38 0xF8BCE6E563A440F2,
39 0x6B17D1F2E12C4247,
40]);
41
42const SECP_GENERATOR_Y: Fp = Fp::from_raw([
43 0xCBB6406837BF51F5,
44 0x2BCE33576B315ECE,
45 0x8EE7EB4A7C0F9E16,
46 0x4FE342E2FE1A7F9B,
47]);
48
49const SECP_A: Fp = Fp::from_raw([
50 0xFFFFFFFFFFFFFFFC,
51 0x00000000FFFFFFFF,
52 0x0000000000000000,
53 0xFFFFFFFF00000001,
54]);
55const SECP_B: Fp = Fp::from_raw([
56 0x3BCE3C3E27D2604B,
57 0x651D06B0CC53B0F6,
58 0xB3EBBD55769886BC,
59 0x5AC635D8AA3A93E7,
60]);
61
62use crate::{
63 impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative,
64 impl_binops_multiplicative_mixed, new_curve_impl,
65};
66
67new_curve_impl!(
68 (pub),
69 Secp256r1,
70 Secp256r1Affine,
71 Fp,
72 Fq,
73 (SECP_GENERATOR_X,SECP_GENERATOR_Y),
74 SECP_A,
75 SECP_B,
76 "secp256r1",
77 |domain_prefix| hash_to_curve(domain_prefix, hash_to_curve_suite(b"P256_XMD:SHA-256_SSWU_RO_")),
78 crate::serde::CompressedFlagConfig::Extra,
79 standard_sign
80);
81
82fn hash_to_curve_suite(domain: &[u8]) -> crate::hash_to_curve::Suite<Secp256r1, sha2::Sha256, 48> {
83 const SSWU_Z: Fp = Fp::from_raw([
87 0xfffffffffffffff5,
88 0x00000000ffffffff,
89 0x0000000000000000,
90 0xffffffff00000001,
91 ]);
92
93 let iso_map = crate::hash_to_curve::Iso {
94 a: Secp256r1::a(),
95 b: Secp256r1::b(),
96 map: Box::new(move |x, y, z| Secp256r1 { x, y, z }),
97 };
98
99 crate::hash_to_curve::Suite::new(domain, SSWU_Z, crate::hash_to_curve::Method::SSWU(iso_map))
100}
101
102#[allow(clippy::type_complexity)]
103pub(crate) fn hash_to_curve<'a>(
104 domain_prefix: &'a str,
105 suite: crate::hash_to_curve::Suite<Secp256r1, sha2::Sha256, 48>,
106) -> Box<dyn Fn(&[u8]) -> Secp256r1 + 'a> {
107 Box::new(move |message| suite.hash_to_curve(domain_prefix, message))
108}
109
110#[cfg(test)]
111mod test {
112 use group::UncompressedEncoding;
113 use rand_core::OsRng;
114
115 use super::*;
116 use crate::{serde::SerdeObject, tests::curve::TestH2C};
117 crate::curve_testing_suite!(Secp256r1);
118 crate::curve_testing_suite!(Secp256r1, "ecdsa_example");
119 crate::curve_testing_suite!(
120 Secp256r1,
121 "constants",
122 Fp::MODULUS,
123 SECP_A,
124 SECP_B,
125 SECP_GENERATOR_X,
126 SECP_GENERATOR_Y,
127 Fq::MODULUS
128 );
129
130 #[test]
131 fn test_hash_to_curve() {
132 [
135 TestH2C::<Secp256r1Affine>::new(
136 b"",
137 crate::tests::point_from_hex(
138 "2c15230b26dbc6fc9a37051158c95b79656e17a1a920b11394ca91c44247d3e4",
139 "8a7a74985cc5c776cdfe4b1f19884970453912e9d31528c060be9ab5c43e8415",
140 ),
141 ),
142 TestH2C::<Secp256r1Affine>::new(
143 b"abc",
144 crate::tests::point_from_hex(
145 "0bb8b87485551aa43ed54f009230450b492fead5f1cc91658775dac4a3388a0f",
146 "5c41b3d0731a27a7b14bc0bf0ccded2d8751f83493404c84a88e71ffd424212e",
147 ),
148 ),
149 TestH2C::<Secp256r1Affine>::new(
150 b"abcdef0123456789",
151 crate::tests::point_from_hex(
152 "65038ac8f2b1def042a5df0b33b1f4eca6bff7cb0f9c6c1526811864e544ed80",
153 "cad44d40a656e7aff4002a8de287abc8ae0482b5ae825822bb870d6df9b56ca3",
154 ),
155 ),
156 TestH2C::<Secp256r1Affine>::new(
157 b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
158 crate::tests::point_from_hex(
159 "4be61ee205094282ba8a2042bcb48d88dfbb609301c49aa8b078533dc65a0b5d",
160 "98f8df449a072c4721d241a3b1236d3caccba603f916ca680f4539d2bfb3c29e",
161 ),
162 ), TestH2C::<Secp256r1Affine>::new(
164 b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
165 crate::tests::point_from_hex(
166 "457ae2981f70ca85d8e24c308b14db22f3e3862c5ea0f652ca38b5e49cd64bc5",
167 "ecb9f0eadc9aeed232dabc53235368c1394c78de05dd96893eefa62b0f4757dc",
168 ),
169 ),
170 ].iter().for_each(|test| {
171 test.run("QUUX-V01-CS02-with-");
172 });
173 }
174}