@@ -63,69 +63,127 @@ void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
63
63
}
64
64
65
65
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 );
96
124
}
97
125
98
126
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 );
129
187
}
130
188
131
189
void static secp256k1_fe_inv_var (secp256k1_fe_t * r , const secp256k1_fe_t * a ) {
0 commit comments