lambdaworks_math/elliptic_curve/short_weierstrass/curves/secq256k1/
curve.rs1use crate::elliptic_curve::short_weierstrass::point::ShortWeierstrassProjectivePoint;
2use crate::elliptic_curve::traits::IsEllipticCurve;
3use crate::field::fields::secp256k1_scalarfield::Secp256k1ScalarField;
4use crate::{
5 elliptic_curve::short_weierstrass::traits::IsShortWeierstrass, field::element::FieldElement,
6};
7
8#[derive(Clone, Debug)]
9pub struct Secq256k1Curve;
10
11impl IsEllipticCurve for Secq256k1Curve {
12 type BaseField = Secp256k1ScalarField;
13 type PointRepresentation = ShortWeierstrassProjectivePoint<Self>;
14
15 fn generator() -> Self::PointRepresentation {
16 let point = Self::PointRepresentation::new([
20 FieldElement::<Self::BaseField>::from_hex_unchecked(
21 "76C39F5585CB160EB6B06C87A2CE32E23134E45A097781A6A24288E37702EDA6",
22 ),
23 FieldElement::<Self::BaseField>::from_hex_unchecked(
24 "3FFC646C7B2918B5DC2D265A8E82A7F7D18983D26E8DC055A4120DDAD952677F",
25 ),
26 FieldElement::one(),
27 ]);
28 point.unwrap()
29 }
30}
31
32impl IsShortWeierstrass for Secq256k1Curve {
33 fn a() -> FieldElement<Self::BaseField> {
34 FieldElement::from(0)
35 }
36
37 fn b() -> FieldElement<Self::BaseField> {
38 FieldElement::from(7)
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::{
46 cyclic_group::IsGroup, elliptic_curve::traits::EllipticCurveError,
47 field::element::FieldElement, unsigned_integer::element::U256,
48 };
49
50 use super::Secq256k1Curve;
51
52 #[allow(clippy::upper_case_acronyms)]
53 type FE = FieldElement<Secp256k1ScalarField>;
54
55 fn point_1() -> ShortWeierstrassProjectivePoint<Secq256k1Curve> {
56 let x = FE::from_hex_unchecked(
57 "76C39F5585CB160EB6B06C87A2CE32E23134E45A097781A6A24288E37702EDA6",
58 );
59 let y = FE::from_hex_unchecked(
60 "3FFC646C7B2918B5DC2D265A8E82A7F7D18983D26E8DC055A4120DDAD952677F",
61 );
62 Secq256k1Curve::create_point_from_affine(x, y).unwrap()
63 }
64
65 fn point_1_times_5() -> ShortWeierstrassProjectivePoint<Secq256k1Curve> {
66 let x = FE::from_hex_unchecked(
67 "8656a2c13dd0a3bfa362d2ff8c00281341ff3a79cbbe8857f2d20b398041a21a",
68 );
69 let y = FE::from_hex_unchecked(
70 "468ed8bcfcd4ed2b3bf154414b9e48d8c5ce54f6616846a7cf6a725f70d34a63",
71 );
72 let z = FE::from_hex_unchecked(
73 "bb26eae3d2b9603d98dff86d87175f442e539c07bbe4ef5712e47c4d72c89734",
74 );
75 ShortWeierstrassProjectivePoint::<Secq256k1Curve>::new([x, y, z]).unwrap()
76 }
77
78 #[test]
79 fn adding_five_times_point_1_works() {
80 let point_1 = point_1();
81 let point_1_times_5 = point_1_times_5();
82 assert_eq!(point_1.operate_with_self(5_u16), point_1_times_5);
83 }
84
85 #[test]
86 fn create_valid_point_works() {
87 let p = point_1();
88 assert_eq!(
89 *p.x(),
90 FE::from_hex_unchecked(
91 "76C39F5585CB160EB6B06C87A2CE32E23134E45A097781A6A24288E37702EDA6"
92 )
93 );
94 assert_eq!(
95 *p.y(),
96 FE::from_hex_unchecked(
97 "3FFC646C7B2918B5DC2D265A8E82A7F7D18983D26E8DC055A4120DDAD952677F"
98 )
99 );
100 assert_eq!(*p.z(), FE::from_hex_unchecked("1"));
101 }
102
103 #[test]
104 fn create_invalid_points_returns_an_error() {
105 assert_eq!(
106 Secq256k1Curve::create_point_from_affine(FE::from(0), FE::from(1)),
107 Err(EllipticCurveError::InvalidPoint)
108 );
109 }
110
111 #[test]
112 fn equality_works() {
113 let g = Secq256k1Curve::generator();
114 let g2 = g.operate_with_self(2_u16);
115 let g2_other = g.operate_with(&g);
116 assert_ne!(&g2, &g);
117 assert_eq!(&g, &g);
118 assert_eq!(&g2, &g2_other);
119 }
120
121 #[test]
122 fn g_operated_with_g_satifies_ec_equation() {
123 let g = Secq256k1Curve::generator();
124 let g2 = g.operate_with_self(2_u16);
125
126 let g2_affine = g2.to_affine();
128 let x = g2_affine.x();
129 let y = g2_affine.y();
130
131 let seven = Secq256k1Curve::b();
133 let y_sq_0 = x.pow(3_u16) + seven;
134 let y_sq_1 = y.pow(2_u16);
135
136 assert_eq!(y_sq_0, y_sq_1);
137 }
138
139 #[test]
140 fn operate_with_self_works() {
141 let g = Secq256k1Curve::generator();
142 assert_eq!(
143 g.operate_with(&g).operate_with(&g),
144 g.operate_with_self(3_u16)
145 );
146 }
147
148 #[test]
149 fn generator_has_right_order() {
150 let g = Secq256k1Curve::generator();
151 assert_eq!(
152 g.operate_with_self(U256::from_hex_unchecked(
153 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"
154 ))
155 .to_affine(),
156 ShortWeierstrassProjectivePoint::neutral_element()
157 );
158 }
159
160 #[test]
161 fn inverse_works() {
163 let g = Secq256k1Curve::generator();
164 assert_eq!(
165 g.operate_with_self(U256::from_hex_unchecked(
166 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2A"
167 ))
168 .to_affine(),
169 g.operate_with_self(5u64).neg().to_affine()
170 );
171 }
172}