@@ -4,9 +4,8 @@ use elliptic_curve::bigint::{ArrayEncoding, U256};
4
4
use elliptic_curve:: consts:: { U4 , U16 , U48 } ;
5
5
use elliptic_curve:: ops:: Reduce ;
6
6
use elliptic_curve:: subtle:: { Choice , ConditionallySelectable , ConstantTimeEq } ;
7
- use hash2curve:: {
8
- GroupDigest , Isogeny , IsogenyCoefficients , MapToCurve , OsswuMap , OsswuMapParams , Sgn0 ,
9
- } ;
7
+ use hash2curve:: { GroupDigest , MapToCurve } ;
8
+ use primeorder:: osswu:: { OsswuMap , OsswuMapParams , Sgn0 } ;
10
9
11
10
use crate :: { AffinePoint , ProjectivePoint , Scalar , Secp256k1 } ;
12
11
@@ -134,7 +133,7 @@ impl MapToCurve for Secp256k1 {
134
133
135
134
fn map_to_curve ( element : FieldElement ) -> ProjectivePoint {
136
135
let ( rx, ry) = element. osswu ( ) ;
137
- let ( qx, qy) = FieldElement :: isogeny ( rx, ry) ;
136
+ let ( qx, qy) = isogeny ( rx, ry) ;
138
137
139
138
AffinePoint {
140
139
x : qx,
@@ -163,96 +162,114 @@ impl Reduce<Array<u8, U48>> for Scalar {
163
162
}
164
163
}
165
164
166
- impl Isogeny for FieldElement {
167
- type Degree = U4 ;
168
-
169
- // See section E.1 in
170
- // <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/>
171
- const COEFFICIENTS : IsogenyCoefficients < Self > = IsogenyCoefficients {
172
- xnum : & [
173
- FieldElement :: from_bytes_unchecked ( & [
174
- 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 ,
175
- 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8d ,
176
- 0xaa , 0xaa , 0xa8 , 0xc7 ,
177
- ] ) ,
178
- FieldElement :: from_bytes_unchecked ( & [
179
- 0x07 , 0xd3 , 0xd4 , 0xc8 , 0x0b , 0xc3 , 0x21 , 0xd5 , 0xb9 , 0xf3 , 0x15 , 0xce , 0xa7 , 0xfd ,
180
- 0x44 , 0xc5 , 0xd5 , 0x95 , 0xd2 , 0xfc , 0x0b , 0xf6 , 0x3b , 0x92 , 0xdf , 0xff , 0x10 , 0x44 ,
181
- 0xf1 , 0x7c , 0x65 , 0x81 ,
182
- ] ) ,
183
- FieldElement :: from_bytes_unchecked ( & [
184
- 0x53 , 0x4c , 0x32 , 0x8d , 0x23 , 0xf2 , 0x34 , 0xe6 , 0xe2 , 0xa4 , 0x13 , 0xde , 0xca , 0x25 ,
185
- 0xca , 0xec , 0xe4 , 0x50 , 0x61 , 0x44 , 0x03 , 0x7c , 0x40 , 0x31 , 0x4e , 0xcb , 0xd0 , 0xb5 ,
186
- 0x3d , 0x9d , 0xd2 , 0x62 ,
187
- ] ) ,
188
- FieldElement :: from_bytes_unchecked ( & [
189
- 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 ,
190
- 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8d ,
191
- 0xaa , 0xaa , 0xa8 , 0x8c ,
192
- ] ) ,
193
- ] ,
194
- xden : & [
195
- FieldElement :: from_bytes_unchecked ( & [
196
- 0xd3 , 0x57 , 0x71 , 0x19 , 0x3d , 0x94 , 0x91 , 0x8a , 0x9c , 0xa3 , 0x4c , 0xcb , 0xb7 , 0xb6 ,
197
- 0x40 , 0xdd , 0x86 , 0xcd , 0x40 , 0x95 , 0x42 , 0xf8 , 0x48 , 0x7d , 0x9f , 0xe6 , 0xb7 , 0x45 ,
198
- 0x78 , 0x1e , 0xb4 , 0x9b ,
199
- ] ) ,
200
- FieldElement :: from_bytes_unchecked ( & [
201
- 0xed , 0xad , 0xc6 , 0xf6 , 0x43 , 0x83 , 0xdc , 0x1d , 0xf7 , 0xc4 , 0xb2 , 0xd5 , 0x1b , 0x54 ,
202
- 0x22 , 0x54 , 0x06 , 0xd3 , 0x6b , 0x64 , 0x1f , 0x5e , 0x41 , 0xbb , 0xc5 , 0x2a , 0x56 , 0x61 ,
203
- 0x2a , 0x8c , 0x6d , 0x14 ,
204
- ] ) ,
205
- FieldElement :: from_bytes_unchecked ( & [
206
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
207
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
208
- 0x00 , 0x00 , 0x00 , 0x01 ,
209
- ] ) ,
210
- ] ,
211
- ynum : & [
212
- FieldElement :: from_bytes_unchecked ( & [
213
- 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 ,
214
- 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b ,
215
- 0x8e , 0x38 , 0xe2 , 0x3c ,
216
- ] ) ,
217
- FieldElement :: from_bytes_unchecked ( & [
218
- 0xc7 , 0x5e , 0x0c , 0x32 , 0xd5 , 0xcb , 0x7c , 0x0f , 0xa9 , 0xd0 , 0xa5 , 0x4b , 0x12 , 0xa0 ,
219
- 0xa6 , 0xd5 , 0x64 , 0x7a , 0xb0 , 0x46 , 0xd6 , 0x86 , 0xda , 0x6f , 0xdf , 0xfc , 0x90 , 0xfc ,
220
- 0x20 , 0x1d , 0x71 , 0xa3 ,
221
- ] ) ,
222
- FieldElement :: from_bytes_unchecked ( & [
223
- 0x29 , 0xa6 , 0x19 , 0x46 , 0x91 , 0xf9 , 0x1a , 0x73 , 0x71 , 0x52 , 0x09 , 0xef , 0x65 , 0x12 ,
224
- 0xe5 , 0x76 , 0x72 , 0x28 , 0x30 , 0xa2 , 0x01 , 0xbe , 0x20 , 0x18 , 0xa7 , 0x65 , 0xe8 , 0x5a ,
225
- 0x9e , 0xce , 0xe9 , 0x31 ,
226
- ] ) ,
227
- FieldElement :: from_bytes_unchecked ( & [
228
- 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 ,
229
- 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f ,
230
- 0x38 , 0xe3 , 0x8d , 0x84 ,
231
- ] ) ,
232
- ] ,
233
- yden : & [
234
- FieldElement :: from_bytes_unchecked ( & [
235
- 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
236
- 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xfe ,
237
- 0xff , 0xff , 0xf9 , 0x3b ,
238
- ] ) ,
239
- FieldElement :: from_bytes_unchecked ( & [
240
- 0x7a , 0x06 , 0x53 , 0x4b , 0xb8 , 0xbd , 0xb4 , 0x9f , 0xd5 , 0xe9 , 0xe6 , 0x63 , 0x27 , 0x22 ,
241
- 0xc2 , 0x98 , 0x94 , 0x67 , 0xc1 , 0xbf , 0xc8 , 0xe8 , 0xd9 , 0x78 , 0xdf , 0xb4 , 0x25 , 0xd2 ,
242
- 0x68 , 0x5c , 0x25 , 0x73 ,
243
- ] ) ,
244
- FieldElement :: from_bytes_unchecked ( & [
245
- 0x64 , 0x84 , 0xaa , 0x71 , 0x65 , 0x45 , 0xca , 0x2c , 0xf3 , 0xa7 , 0x0c , 0x3f , 0xa8 , 0xfe ,
246
- 0x33 , 0x7e , 0x0a , 0x3d , 0x21 , 0x16 , 0x2f , 0x0d , 0x62 , 0x99 , 0xa7 , 0xbf , 0x81 , 0x92 ,
247
- 0xbf , 0xd2 , 0xa7 , 0x6f ,
248
- ] ) ,
249
- FieldElement :: from_bytes_unchecked ( & [
250
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
251
- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
252
- 0x00 , 0x00 , 0x00 , 0x01 ,
253
- ] ) ,
254
- ] ,
255
- } ;
165
+ // See section E.1 in
166
+ // <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/>
167
+ fn isogeny ( x : FieldElement , y : FieldElement ) -> ( FieldElement , FieldElement ) {
168
+ const XNUM : [ FieldElement ; 4 ] = [
169
+ FieldElement :: from_bytes_unchecked ( & [
170
+ 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 ,
171
+ 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8d ,
172
+ 0xaa , 0xaa , 0xa8 , 0xc7 ,
173
+ ] ) ,
174
+ FieldElement :: from_bytes_unchecked ( & [
175
+ 0x07 , 0xd3 , 0xd4 , 0xc8 , 0x0b , 0xc3 , 0x21 , 0xd5 , 0xb9 , 0xf3 , 0x15 , 0xce , 0xa7 , 0xfd ,
176
+ 0x44 , 0xc5 , 0xd5 , 0x95 , 0xd2 , 0xfc , 0x0b , 0xf6 , 0x3b , 0x92 , 0xdf , 0xff , 0x10 , 0x44 ,
177
+ 0xf1 , 0x7c , 0x65 , 0x81 ,
178
+ ] ) ,
179
+ FieldElement :: from_bytes_unchecked ( & [
180
+ 0x53 , 0x4c , 0x32 , 0x8d , 0x23 , 0xf2 , 0x34 , 0xe6 , 0xe2 , 0xa4 , 0x13 , 0xde , 0xca , 0x25 ,
181
+ 0xca , 0xec , 0xe4 , 0x50 , 0x61 , 0x44 , 0x03 , 0x7c , 0x40 , 0x31 , 0x4e , 0xcb , 0xd0 , 0xb5 ,
182
+ 0x3d , 0x9d , 0xd2 , 0x62 ,
183
+ ] ) ,
184
+ FieldElement :: from_bytes_unchecked ( & [
185
+ 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 ,
186
+ 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8e , 0x38 , 0xe3 , 0x8d ,
187
+ 0xaa , 0xaa , 0xa8 , 0x8c ,
188
+ ] ) ,
189
+ ] ;
190
+ const XDEN : [ FieldElement ; 3 ] = [
191
+ FieldElement :: from_bytes_unchecked ( & [
192
+ 0xd3 , 0x57 , 0x71 , 0x19 , 0x3d , 0x94 , 0x91 , 0x8a , 0x9c , 0xa3 , 0x4c , 0xcb , 0xb7 , 0xb6 ,
193
+ 0x40 , 0xdd , 0x86 , 0xcd , 0x40 , 0x95 , 0x42 , 0xf8 , 0x48 , 0x7d , 0x9f , 0xe6 , 0xb7 , 0x45 ,
194
+ 0x78 , 0x1e , 0xb4 , 0x9b ,
195
+ ] ) ,
196
+ FieldElement :: from_bytes_unchecked ( & [
197
+ 0xed , 0xad , 0xc6 , 0xf6 , 0x43 , 0x83 , 0xdc , 0x1d , 0xf7 , 0xc4 , 0xb2 , 0xd5 , 0x1b , 0x54 ,
198
+ 0x22 , 0x54 , 0x06 , 0xd3 , 0x6b , 0x64 , 0x1f , 0x5e , 0x41 , 0xbb , 0xc5 , 0x2a , 0x56 , 0x61 ,
199
+ 0x2a , 0x8c , 0x6d , 0x14 ,
200
+ ] ) ,
201
+ FieldElement :: from_bytes_unchecked ( & [
202
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
203
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
204
+ 0x00 , 0x00 , 0x00 , 0x01 ,
205
+ ] ) ,
206
+ ] ;
207
+ const YNUM : [ FieldElement ; 4 ] = [
208
+ FieldElement :: from_bytes_unchecked ( & [
209
+ 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 ,
210
+ 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b ,
211
+ 0x8e , 0x38 , 0xe2 , 0x3c ,
212
+ ] ) ,
213
+ FieldElement :: from_bytes_unchecked ( & [
214
+ 0xc7 , 0x5e , 0x0c , 0x32 , 0xd5 , 0xcb , 0x7c , 0x0f , 0xa9 , 0xd0 , 0xa5 , 0x4b , 0x12 , 0xa0 ,
215
+ 0xa6 , 0xd5 , 0x64 , 0x7a , 0xb0 , 0x46 , 0xd6 , 0x86 , 0xda , 0x6f , 0xdf , 0xfc , 0x90 , 0xfc ,
216
+ 0x20 , 0x1d , 0x71 , 0xa3 ,
217
+ ] ) ,
218
+ FieldElement :: from_bytes_unchecked ( & [
219
+ 0x29 , 0xa6 , 0x19 , 0x46 , 0x91 , 0xf9 , 0x1a , 0x73 , 0x71 , 0x52 , 0x09 , 0xef , 0x65 , 0x12 ,
220
+ 0xe5 , 0x76 , 0x72 , 0x28 , 0x30 , 0xa2 , 0x01 , 0xbe , 0x20 , 0x18 , 0xa7 , 0x65 , 0xe8 , 0x5a ,
221
+ 0x9e , 0xce , 0xe9 , 0x31 ,
222
+ ] ) ,
223
+ FieldElement :: from_bytes_unchecked ( & [
224
+ 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 ,
225
+ 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f , 0x68 , 0x4b , 0xda , 0x12 , 0xf6 , 0x84 , 0xbd , 0xa1 , 0x2f ,
226
+ 0x38 , 0xe3 , 0x8d , 0x84 ,
227
+ ] ) ,
228
+ ] ;
229
+ const YDEN : [ FieldElement ; 4 ] = [
230
+ FieldElement :: from_bytes_unchecked ( & [
231
+ 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
232
+ 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xfe ,
233
+ 0xff , 0xff , 0xf9 , 0x3b ,
234
+ ] ) ,
235
+ FieldElement :: from_bytes_unchecked ( & [
236
+ 0x7a , 0x06 , 0x53 , 0x4b , 0xb8 , 0xbd , 0xb4 , 0x9f , 0xd5 , 0xe9 , 0xe6 , 0x63 , 0x27 , 0x22 ,
237
+ 0xc2 , 0x98 , 0x94 , 0x67 , 0xc1 , 0xbf , 0xc8 , 0xe8 , 0xd9 , 0x78 , 0xdf , 0xb4 , 0x25 , 0xd2 ,
238
+ 0x68 , 0x5c , 0x25 , 0x73 ,
239
+ ] ) ,
240
+ FieldElement :: from_bytes_unchecked ( & [
241
+ 0x64 , 0x84 , 0xaa , 0x71 , 0x65 , 0x45 , 0xca , 0x2c , 0xf3 , 0xa7 , 0x0c , 0x3f , 0xa8 , 0xfe ,
242
+ 0x33 , 0x7e , 0x0a , 0x3d , 0x21 , 0x16 , 0x2f , 0x0d , 0x62 , 0x99 , 0xa7 , 0xbf , 0x81 , 0x92 ,
243
+ 0xbf , 0xd2 , 0xa7 , 0x6f ,
244
+ ] ) ,
245
+ FieldElement :: from_bytes_unchecked ( & [
246
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
247
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
248
+ 0x00 , 0x00 , 0x00 , 0x01 ,
249
+ ] ) ,
250
+ ] ;
251
+
252
+ let mut xs = Array :: < FieldElement , U4 > :: default ( ) ;
253
+ xs[ 0 ] = FieldElement :: ONE ;
254
+ xs[ 1 ] = x;
255
+ xs[ 2 ] = x. square ( ) ;
256
+ for i in 3 ..4 {
257
+ xs[ i] = xs[ i - 1 ] * x;
258
+ }
259
+ let x_num = compute_iso ( & xs, & XNUM ) ;
260
+ let x_den = compute_iso ( & xs, & XDEN ) . invert ( ) . unwrap ( ) ;
261
+ let y_num = compute_iso ( & xs, & YNUM ) * y;
262
+ let y_den = compute_iso ( & xs, & YDEN ) . invert ( ) . unwrap ( ) ;
263
+
264
+ ( x_num * x_den, y_num * y_den)
265
+ }
266
+
267
+ fn compute_iso ( xxs : & [ FieldElement ] , k : & [ FieldElement ] ) -> FieldElement {
268
+ let mut xx = FieldElement :: ZERO ;
269
+ for ( xi, ki) in xxs. iter ( ) . zip ( k. iter ( ) ) {
270
+ xx += * xi * ki;
271
+ }
272
+ xx
256
273
}
257
274
258
275
#[ cfg( test) ]
0 commit comments