Skip to content

Commit f8ccd9b

Browse files
committed
Re-write secp256k1_fe_sqrt and secp256k1_fe_inv to use a sliding window over blocks of 1s
1 parent ea0fe5a commit f8ccd9b

File tree

1 file changed

+118
-60
lines changed

1 file changed

+118
-60
lines changed

src/impl/field.h

Lines changed: 118 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -63,69 +63,127 @@ void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
6363
}
6464

6565
void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
66-
// calculate a^p, with p={15,780,1022,1023}
67-
secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a);
68-
secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a);
69-
secp256k1_fe_t a6; secp256k1_fe_sqr(&a6, &a3);
70-
secp256k1_fe_t a12; secp256k1_fe_sqr(&a12, &a6);
71-
secp256k1_fe_t a15; secp256k1_fe_mul(&a15, &a12, &a3);
72-
secp256k1_fe_t a30; secp256k1_fe_sqr(&a30, &a15);
73-
secp256k1_fe_t a60; secp256k1_fe_sqr(&a60, &a30);
74-
secp256k1_fe_t a120; secp256k1_fe_sqr(&a120, &a60);
75-
secp256k1_fe_t a240; secp256k1_fe_sqr(&a240, &a120);
76-
secp256k1_fe_t a255; secp256k1_fe_mul(&a255, &a240, &a15);
77-
secp256k1_fe_t a510; secp256k1_fe_sqr(&a510, &a255);
78-
secp256k1_fe_t a750; secp256k1_fe_mul(&a750, &a510, &a240);
79-
secp256k1_fe_t a780; secp256k1_fe_mul(&a780, &a750, &a30);
80-
secp256k1_fe_t a1020; secp256k1_fe_sqr(&a1020, &a510);
81-
secp256k1_fe_t a1022; secp256k1_fe_mul(&a1022, &a1020, &a2);
82-
secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1022, a);
83-
secp256k1_fe_t x = a15;
84-
for (int i=0; i<21; i++) {
85-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
86-
secp256k1_fe_mul(&x, &x, &a1023);
87-
}
88-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
89-
secp256k1_fe_mul(&x, &x, &a1022);
90-
for (int i=0; i<2; i++) {
91-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
92-
secp256k1_fe_mul(&x, &x, &a1023);
93-
}
94-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
95-
secp256k1_fe_mul(r, &x, &a780);
66+
67+
// The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
68+
// { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
69+
// 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 222, [223]
70+
71+
secp256k1_fe_t x2;
72+
secp256k1_fe_sqr(&x2, a);
73+
secp256k1_fe_mul(&x2, &x2, a);
74+
75+
secp256k1_fe_t x3;
76+
secp256k1_fe_sqr(&x3, &x2);
77+
secp256k1_fe_mul(&x3, &x3, a);
78+
79+
secp256k1_fe_t x6 = x3;
80+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6);
81+
secp256k1_fe_mul(&x6, &x6, &x3);
82+
83+
secp256k1_fe_t x9 = x6;
84+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9);
85+
secp256k1_fe_mul(&x9, &x9, &x3);
86+
87+
secp256k1_fe_t x11 = x9;
88+
for (int j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11);
89+
secp256k1_fe_mul(&x11, &x11, &x2);
90+
91+
secp256k1_fe_t x22 = x11;
92+
for (int j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22);
93+
secp256k1_fe_mul(&x22, &x22, &x11);
94+
95+
secp256k1_fe_t x44 = x22;
96+
for (int j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44);
97+
secp256k1_fe_mul(&x44, &x44, &x22);
98+
99+
secp256k1_fe_t x88 = x44;
100+
for (int j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88);
101+
secp256k1_fe_mul(&x88, &x88, &x44);
102+
103+
secp256k1_fe_t x176 = x88;
104+
for (int j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176);
105+
secp256k1_fe_mul(&x176, &x176, &x88);
106+
107+
secp256k1_fe_t x220 = x176;
108+
for (int j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220);
109+
secp256k1_fe_mul(&x220, &x220, &x44);
110+
111+
secp256k1_fe_t x223 = x220;
112+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223);
113+
secp256k1_fe_mul(&x223, &x223, &x3);
114+
115+
// The final result is then assembled using a sliding window over the blocks.
116+
117+
secp256k1_fe_t t1 = x223;
118+
for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
119+
secp256k1_fe_mul(&t1, &t1, &x22);
120+
for (int j=0; j<6; j++) secp256k1_fe_sqr(&t1, &t1);
121+
secp256k1_fe_mul(&t1, &t1, &x2);
122+
secp256k1_fe_sqr(&t1, &t1);
123+
secp256k1_fe_sqr(r, &t1);
96124
}
97125

98126
void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
99-
// calculate a^p, with p={45,63,1019,1023}
100-
secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a);
101-
secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a);
102-
secp256k1_fe_t a4; secp256k1_fe_sqr(&a4, &a2);
103-
secp256k1_fe_t a5; secp256k1_fe_mul(&a5, &a4, a);
104-
secp256k1_fe_t a10; secp256k1_fe_sqr(&a10, &a5);
105-
secp256k1_fe_t a11; secp256k1_fe_mul(&a11, &a10, a);
106-
secp256k1_fe_t a21; secp256k1_fe_mul(&a21, &a11, &a10);
107-
secp256k1_fe_t a42; secp256k1_fe_sqr(&a42, &a21);
108-
secp256k1_fe_t a45; secp256k1_fe_mul(&a45, &a42, &a3);
109-
secp256k1_fe_t a63; secp256k1_fe_mul(&a63, &a42, &a21);
110-
secp256k1_fe_t a126; secp256k1_fe_sqr(&a126, &a63);
111-
secp256k1_fe_t a252; secp256k1_fe_sqr(&a252, &a126);
112-
secp256k1_fe_t a504; secp256k1_fe_sqr(&a504, &a252);
113-
secp256k1_fe_t a1008; secp256k1_fe_sqr(&a1008, &a504);
114-
secp256k1_fe_t a1019; secp256k1_fe_mul(&a1019, &a1008, &a11);
115-
secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1019, &a4);
116-
secp256k1_fe_t x = a63;
117-
for (int i=0; i<21; i++) {
118-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
119-
secp256k1_fe_mul(&x, &x, &a1023);
120-
}
121-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
122-
secp256k1_fe_mul(&x, &x, &a1019);
123-
for (int i=0; i<2; i++) {
124-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
125-
secp256k1_fe_mul(&x, &x, &a1023);
126-
}
127-
for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
128-
secp256k1_fe_mul(r, &x, &a45);
127+
128+
// The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
129+
// { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
130+
// [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 222, [223]
131+
132+
secp256k1_fe_t x2;
133+
secp256k1_fe_sqr(&x2, a);
134+
secp256k1_fe_mul(&x2, &x2, a);
135+
136+
secp256k1_fe_t x3;
137+
secp256k1_fe_sqr(&x3, &x2);
138+
secp256k1_fe_mul(&x3, &x3, a);
139+
140+
secp256k1_fe_t x6 = x3;
141+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6);
142+
secp256k1_fe_mul(&x6, &x6, &x3);
143+
144+
secp256k1_fe_t x9 = x6;
145+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9);
146+
secp256k1_fe_mul(&x9, &x9, &x3);
147+
148+
secp256k1_fe_t x11 = x9;
149+
for (int j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11);
150+
secp256k1_fe_mul(&x11, &x11, &x2);
151+
152+
secp256k1_fe_t x22 = x11;
153+
for (int j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22);
154+
secp256k1_fe_mul(&x22, &x22, &x11);
155+
156+
secp256k1_fe_t x44 = x22;
157+
for (int j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44);
158+
secp256k1_fe_mul(&x44, &x44, &x22);
159+
160+
secp256k1_fe_t x88 = x44;
161+
for (int j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88);
162+
secp256k1_fe_mul(&x88, &x88, &x44);
163+
164+
secp256k1_fe_t x176 = x88;
165+
for (int j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176);
166+
secp256k1_fe_mul(&x176, &x176, &x88);
167+
168+
secp256k1_fe_t x220 = x176;
169+
for (int j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220);
170+
secp256k1_fe_mul(&x220, &x220, &x44);
171+
172+
secp256k1_fe_t x223 = x220;
173+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223);
174+
secp256k1_fe_mul(&x223, &x223, &x3);
175+
176+
// The final result is then assembled using a sliding window over the blocks.
177+
178+
secp256k1_fe_t t1 = x223;
179+
for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1);
180+
secp256k1_fe_mul(&t1, &t1, &x22);
181+
for (int j=0; j<5; j++) secp256k1_fe_sqr(&t1, &t1);
182+
secp256k1_fe_mul(&t1, &t1, a);
183+
for (int j=0; j<3; j++) secp256k1_fe_sqr(&t1, &t1);
184+
secp256k1_fe_mul(&t1, &t1, &x2);
185+
for (int j=0; j<2; j++) secp256k1_fe_sqr(&t1, &t1);
186+
secp256k1_fe_mul(r, &t1, a);
129187
}
130188

131189
void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {

0 commit comments

Comments
 (0)