halo2curves_axiom/secp256k1/
curve.rs
1use crate::ff::WithSmallOrderMulGroup;
2use crate::ff::{Field, PrimeField};
3use crate::group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding};
4use crate::hash_to_curve::svdw_hash_to_curve;
5use crate::secp256k1::Fp;
6use crate::secp256k1::Fq;
7use crate::{Coordinates, CurveAffine, CurveAffineExt, CurveExt};
8use core::cmp;
9use core::fmt::Debug;
10use core::iter::Sum;
11use core::ops::{Add, Mul, Neg, Sub};
12use rand::RngCore;
13use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
14
15#[cfg(feature = "derive_serde")]
16use serde::{Deserialize, Serialize};
17
18impl group::cofactor::CofactorGroup for Secp256k1 {
19 type Subgroup = Secp256k1;
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 0x59F2815B16F81798,
37 0x029BFCDB2DCE28D9,
38 0x55A06295CE870B07,
39 0x79BE667EF9DCBBAC,
40]);
41const SECP_GENERATOR_Y: Fp = Fp::from_raw([
42 0x9C47D08FFB10D4B8,
43 0xFD17B448A6855419,
44 0x5DA4FBFC0E1108A8,
45 0x483ADA7726A3C465,
46]);
47
48const SECP_A: Fp = Fp::from_raw([0, 0, 0, 0]);
49const SECP_B: Fp = Fp::from_raw([7, 0, 0, 0]);
50
51use crate::{
52 impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
53 impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
54 new_curve_impl,
55};
56
57new_curve_impl!(
58 (pub),
59 Secp256k1,
60 Secp256k1Affine,
61 true,
62 Fp,
63 Fq,
64 (SECP_GENERATOR_X,SECP_GENERATOR_Y),
65 SECP_A,
66 SECP_B,
67 "secp256k1",
68 |curve_id, domain_prefix| svdw_hash_to_curve(curve_id, domain_prefix, Secp256k1::SVDW_Z),
69);
70
71impl Secp256k1 {
72 const SVDW_Z: Fp = Fp::ONE;
73}
74
75#[test]
76fn test_curve() {
77 crate::tests::curve::curve_tests::<Secp256k1>();
78}
79
80#[test]
81fn test_hash_to_curve() {
82 crate::tests::curve::hash_to_curve_test::<Secp256k1>();
83}
84
85#[test]
86fn test_serialization() {
87 crate::tests::curve::random_serialization_test::<Secp256k1>();
88 #[cfg(feature = "derive_serde")]
89 crate::tests::curve::random_serde_test::<Secp256k1>();
90}
91
92#[test]
93fn test_endo_consistency() {
94 let g = Secp256k1::generator();
95 assert_eq!(g * Fq::ZETA, g.endo());
96}
97
98#[test]
99fn ecdsa_example() {
100 use crate::group::Curve;
101 use crate::CurveAffine;
102 use ff::FromUniformBytes;
103 use rand_core::OsRng;
104
105 fn mod_n(x: Fp) -> Fq {
106 let mut x_repr = [0u8; 32];
107 x_repr.copy_from_slice(x.to_repr().as_ref());
108 let mut x_bytes = [0u8; 64];
109 x_bytes[..32].copy_from_slice(&x_repr[..]);
110 Fq::from_uniform_bytes(&x_bytes)
111 }
112
113 let g = Secp256k1::generator();
114
115 for _ in 0..1000 {
116 let sk = Fq::random(OsRng);
118 let pk = (g * sk).to_affine();
119
120 let msg_hash = Fq::random(OsRng);
123
124 let (r, s) = {
125 let k = Fq::random(OsRng);
127 let k_inv = k.invert().unwrap();
128
129 let r_point = (g * k).to_affine().coordinates().unwrap();
131 let x = r_point.x();
132 let r = mod_n(*x);
133
134 let s = k_inv * (msg_hash + (r * sk));
136
137 (r, s)
138 };
139
140 {
141 let s_inv = s.invert().unwrap();
143 let u_1 = msg_hash * s_inv;
144 let u_2 = r * s_inv;
145
146 let v_1 = g * u_1;
147 let v_2 = pk * u_2;
148
149 let r_point = (v_1 + v_2).to_affine().coordinates().unwrap();
150 let x_candidate = r_point.x();
151 let r_candidate = mod_n(*x_candidate);
152
153 assert_eq!(r, r_candidate);
154 }
155 }
156}