openzeppelin_crypto/curve/sw/instance/
secp256k1.rs1use crate::{
5 arithmetic::uint::U256,
6 curve::{
7 sw::{Affine, SWCurveConfig},
8 CurveConfig,
9 },
10 field::fp::{Fp256, FpParams, LIMBS_256},
11 fp_from_num, from_num,
12};
13
14const G_GENERATOR_X: Fq =
15 fp_from_num!("55066263022277343669578718895168534326250603453777594175500187360389116729240");
16
17const G_GENERATOR_Y: Fq =
18 fp_from_num!("32670510020758816978083085130507043184471273380659243275938904335757337482424");
19
20pub type Fq = Fp256<Secp256k1FqParam>;
22pub struct Secp256k1FqParam;
24
25impl FpParams<LIMBS_256> for Secp256k1FqParam {
26 const GENERATOR: Fp256<Self> = fp_from_num!("3");
27 const MODULUS: U256 = from_num!("115792089237316195423570985008687907853269984665640564039457584007908834671663");
28}
29
30pub type Fr = Fp256<Secp256k1FrParam>;
32pub struct Secp256k1FrParam;
34
35impl FpParams<LIMBS_256> for Secp256k1FrParam {
36 const GENERATOR: Fp256<Self> = fp_from_num!("7");
37 const MODULUS: U256 = from_num!("115792089237316195423570985008687907852837564279074904382605163141518161494337");
38}
39
40#[derive(Clone, Default, PartialEq, Eq)]
42pub struct Secp256k1Config;
43
44impl CurveConfig for Secp256k1Config {
45 type BaseField = Fq;
46 type ScalarField = Fr;
47
48 const COFACTOR: &'static [u64] = &[0x1, 0x0];
49 const COFACTOR_INV: Fr = Fr::ONE;
50}
51
52impl SWCurveConfig for Secp256k1Config {
53 const COEFF_A: Fq = Fq::ZERO;
54 const COEFF_B: Fq = fp_from_num!("7");
55 const GENERATOR: Affine<Self> =
56 Affine::new_unchecked(G_GENERATOR_X, G_GENERATOR_Y);
57}
58
59#[cfg(test)]
60mod test {
61 use alloc::vec::Vec;
62
63 use num_traits::Zero;
64 use proptest::{arbitrary::any, prelude::prop, proptest};
65
66 use crate::{
67 curve::{
68 sw::{
69 instance::secp256k1::{Fq, Fr, Secp256k1Config},
70 Affine, Projective,
71 },
72 AffineRepr, CurveConfig, CurveGroup,
73 },
74 field::group::AdditiveGroup,
75 fp_from_hex,
76 };
77
78 #[test]
82 fn scalar_mul() {
83 assert!(
84 Affine::<Secp256k1Config>::generator()
85 .mul_bigint(0u32)
86 .into_affine()
87 .infinity
88 );
89
90 let result: Vec<_> = (1u32..25)
91 .map(|k| {
92 Affine::<Secp256k1Config>::generator()
93 .mul_bigint(k)
94 .into_affine()
95 })
96 .collect();
97
98 let expected =
99 [
100 (fp_from_hex!("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"), fp_from_hex!("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")),
101 (fp_from_hex!("C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5"), fp_from_hex!("1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A")),
102 (fp_from_hex!("F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9"), fp_from_hex!("388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672")),
103 (fp_from_hex!("E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13"), fp_from_hex!("51ED993EA0D455B75642E2098EA51448D967AE33BFBDFE40CFE97BDC47739922")),
104 (fp_from_hex!("2F8BDE4D1A07209355B4A7250A5C5128E88B84BDDC619AB7CBA8D569B240EFE4"), fp_from_hex!("D8AC222636E5E3D6D4DBA9DDA6C9C426F788271BAB0D6840DCA87D3AA6AC62D6")),
105 (fp_from_hex!("FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A1460297556"), fp_from_hex!("AE12777AACFBB620F3BE96017F45C560DE80F0F6518FE4A03C870C36B075F297")),
106 (fp_from_hex!("5CBDF0646E5DB4EAA398F365F2EA7A0E3D419B7E0330E39CE92BDDEDCAC4F9BC"), fp_from_hex!("6AEBCA40BA255960A3178D6D861A54DBA813D0B813FDE7B5A5082628087264DA")),
107 (fp_from_hex!("2F01E5E15CCA351DAFF3843FB70F3C2F0A1BDD05E5AF888A67784EF3E10A2A01"), fp_from_hex!("5C4DA8A741539949293D082A132D13B4C2E213D6BA5B7617B5DA2CB76CBDE904")),
108 (fp_from_hex!("ACD484E2F0C7F65309AD178A9F559ABDE09796974C57E714C35F110DFC27CCBE"), fp_from_hex!("CC338921B0A7D9FD64380971763B61E9ADD888A4375F8E0F05CC262AC64F9C37")),
109 (fp_from_hex!("A0434D9E47F3C86235477C7B1AE6AE5D3442D49B1943C2B752A68E2A47E247C7"), fp_from_hex!("893ABA425419BC27A3B6C7E693A24C696F794C2ED877A1593CBEE53B037368D7")),
110 (fp_from_hex!("774AE7F858A9411E5EF4246B70C65AAC5649980BE5C17891BBEC17895DA008CB"), fp_from_hex!("D984A032EB6B5E190243DD56D7B7B365372DB1E2DFF9D6A8301D74C9C953C61B")),
111 (fp_from_hex!("D01115D548E7561B15C38F004D734633687CF4419620095BC5B0F47070AFE85A"), fp_from_hex!("A9F34FFDC815E0D7A8B64537E17BD81579238C5DD9A86D526B051B13F4062327")),
112 (fp_from_hex!("F28773C2D975288BC7D1D205C3748651B075FBC6610E58CDDEEDDF8F19405AA8"), fp_from_hex!("AB0902E8D880A89758212EB65CDAF473A1A06DA521FA91F29B5CB52DB03ED81")),
113 (fp_from_hex!("499FDF9E895E719CFD64E67F07D38E3226AA7B63678949E6E49B241A60E823E4"), fp_from_hex!("CAC2F6C4B54E855190F044E4A7B3D464464279C27A3F95BCC65F40D403A13F5B")),
114 (fp_from_hex!("D7924D4F7D43EA965A465AE3095FF41131E5946F3C85F79E44ADBCF8E27E080E"), fp_from_hex!("581E2872A86C72A683842EC228CC6DEFEA40AF2BD896D3A5C504DC9FF6A26B58")),
115 (fp_from_hex!("E60FCE93B59E9EC53011AABC21C23E97B2A31369B87A5AE9C44EE89E2A6DEC0A"), fp_from_hex!("F7E3507399E595929DB99F34F57937101296891E44D23F0BE1F32CCE69616821")),
116 (fp_from_hex!("DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34"), fp_from_hex!("4211AB0694635168E997B0EAD2A93DAECED1F4A04A95C0F6CFB199F69E56EB77")),
117 (fp_from_hex!("5601570CB47F238D2B0286DB4A990FA0F3BA28D1A319F5E7CF55C2A2444DA7CC"), fp_from_hex!("C136C1DC0CBEB930E9E298043589351D81D8E0BC736AE2A1F5192E5E8B061D58")),
118 (fp_from_hex!("2B4EA0A797A443D293EF5CFF444F4979F06ACFEBD7E86D277475656138385B6C"), fp_from_hex!("85E89BC037945D93B343083B5A1C86131A01F60C50269763B570C854E5C09B7A")),
119 (fp_from_hex!("4CE119C96E2FA357200B559B2F7DD5A5F02D5290AFF74B03F3E471B273211C97"), fp_from_hex!("12BA26DCB10EC1625DA61FA10A844C676162948271D96967450288EE9233DC3A")),
120 (fp_from_hex!("352BBF4A4CDD12564F93FA332CE333301D9AD40271F8107181340AEF25BE59D5"), fp_from_hex!("321EB4075348F534D59C18259DDA3E1F4A1B3B2E71B1039C67BD3D8BCF81998C")),
121 (fp_from_hex!("421F5FC9A21065445C96FDB91C0C1E2F2431741C72713B4B99DDCB316F31E9FC"), fp_from_hex!("2B90F16D11DABDB616F6DB7E225D1E14743034B37B223115DB20717AD1CD6781")),
122 (fp_from_hex!("2FA2104D6B38D11B0230010559879124E42AB8DFEFF5FF29DC9CDADD4ECACC3F"), fp_from_hex!("2DE1068295DD865B64569335BD5DD80181D70ECFC882648423BA76B532B7D67")),
123 (fp_from_hex!("FE72C435413D33D48AC09C9161BA8B09683215439D62B7940502BDA8B202E6CE"), fp_from_hex!("6851DE067FF24A68D3AB47E09D72998101DC88E36B4A9D22978ED2FBCF58C5BF")),
124 ];
125
126 for (result, (expected_x, expected_y)) in result.iter().zip(expected) {
127 assert!(result.is_on_curve());
128 assert_eq!(result.x, expected_x);
129 assert_eq!(result.y, expected_y);
130 }
131 }
132
133 #[test]
134 fn point_add() {
135 let g = Affine::<Secp256k1Config>::generator();
136 let g_proj: Projective<Secp256k1Config> = g.into();
137
138 let expected_g2 = Affine::new_unchecked(
140 fp_from_hex!("C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5"),
141 fp_from_hex!("1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A"),
142 );
143 let g2 = g_proj + g;
144 let g2_affine = g2.into_affine();
145 assert_eq!(g2_affine, expected_g2);
146 let g2_affine = g_proj.double().into_affine();
147 assert_eq!(g2_affine, expected_g2);
148
149 let neg_g = -g_proj;
151 let zero = g_proj + neg_g;
152 assert!(zero.is_zero());
153 }
154
155 #[test]
156 fn point_sub() {
157 let g = Affine::<Secp256k1Config>::generator();
158 let g_proj: Projective<Secp256k1Config> = g.into();
159
160 let zero = g_proj - g_proj;
162 assert!(zero.is_zero());
163
164 let g2: Projective<Secp256k1Config> = Affine::new_unchecked(
166 fp_from_hex!("C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5"),
167 fp_from_hex!("1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A"),
168 ).into();
169 assert_eq!(g2 - g_proj, g_proj);
170 }
171
172 #[test]
173 fn cofactor_is_one() {
174 #[derive(Clone, Default, PartialEq, Eq)]
175 struct NotOneCofactorConfig;
176
177 impl CurveConfig for NotOneCofactorConfig {
178 type BaseField = Fq;
179 type ScalarField = Fr;
180
181 const COFACTOR: &'static [u64] = &[0x0, 0x0, 0x0, 0x1, 0x0];
182 const COFACTOR_INV: Fr = Fr::ONE;
183 }
184
185 assert!(Secp256k1Config::cofactor_is_one());
186 assert!(!NotOneCofactorConfig::cofactor_is_one());
187 }
188
189 #[test]
190 fn normalize_batch() {
191 proptest!(|(scalars in prop::collection::vec(any::<u32>(), 1..10))|{
193 let prj_points: Vec<_> = scalars.iter()
194 .map(|&k| Affine::<Secp256k1Config>::generator().mul_bigint(k))
195 .collect();
196
197 let expected_aff_points: Vec<_> =
198 prj_points.iter().map(|prj| prj.into_affine()).collect();
199
200 let aff_points =
201 Projective::<Secp256k1Config>::normalize_batch(&prj_points);
202
203 assert_eq!(aff_points, expected_aff_points);
204 });
205 }
206}