1
1
use super :: { field_extension:: BLS12381PrimeField , twist:: BLS12381TwistCurve } ;
2
2
use crate :: {
3
- elliptic_curve:: {
4
- short_weierstrass:: {
5
- curves:: bls12_381:: {
6
- curve:: BLS12381Curve , field_extension:: Degree2ExtensionField , sqrt,
7
- } ,
8
- point:: ShortWeierstrassProjectivePoint ,
9
- traits:: Compress ,
10
- } ,
11
- traits:: IsEllipticCurve ,
3
+ elliptic_curve:: short_weierstrass:: {
4
+ curves:: bls12_381:: { curve:: BLS12381Curve , field_extension:: Degree2ExtensionField , sqrt} ,
5
+ point:: ShortWeierstrassProjectivePoint ,
6
+ traits:: Compress ,
12
7
} ,
13
8
field:: element:: FieldElement ,
14
9
} ;
@@ -20,20 +15,25 @@ use crate::{
20
15
} ;
21
16
22
17
type G1Point = ShortWeierstrassProjectivePoint < BLS12381Curve > ;
18
+ type G2Point = ShortWeierstrassProjectivePoint < BLS12381TwistCurve > ;
23
19
type BLS12381FieldElement = FieldElement < BLS12381PrimeField > ;
24
20
25
21
impl Compress for BLS12381Curve {
26
22
type G1Point = G1Point ;
27
23
28
- type G2Point = <BLS12381TwistCurve as IsEllipticCurve >:: PointRepresentation ;
24
+ type G2Point = G2Point ;
25
+
26
+ type G1Compressed = [ u8 ; 48 ] ;
27
+
28
+ type G2Compressed = [ u8 ; 96 ] ;
29
29
30
30
type Error = ByteConversionError ;
31
31
32
32
#[ cfg( feature = "alloc" ) ]
33
- fn compress_g1_point ( point : & Self :: G1Point ) -> alloc :: vec :: Vec < u8 > {
33
+ fn compress_g1_point ( point : & Self :: G1Point ) -> Self :: G1Compressed {
34
34
if * point == G1Point :: neutral_element ( ) {
35
35
// point is at infinity
36
- let mut x_bytes = alloc :: vec! [ 0_u8 ; 48 ] ;
36
+ let mut x_bytes = [ 0_u8 ; 48 ] ;
37
37
x_bytes[ 0 ] |= 1 << 7 ;
38
38
x_bytes[ 0 ] |= 1 << 6 ;
39
39
x_bytes
@@ -42,8 +42,9 @@ impl Compress for BLS12381Curve {
42
42
let point_affine = point. to_affine ( ) ;
43
43
let x = point_affine. x ( ) ;
44
44
let y = point_affine. y ( ) ;
45
-
46
- let mut x_bytes = x. to_bytes_be ( ) ;
45
+ let mut x_bytes = [ 0u8 ; 48 ] ;
46
+ let bytes = x. to_bytes_be ( ) ;
47
+ x_bytes. copy_from_slice ( & bytes) ;
47
48
48
49
// Set first bit to to 1 indicate this is compressed element.
49
50
x_bytes[ 0 ] |= 1 << 7 ;
@@ -106,7 +107,49 @@ impl Compress for BLS12381Curve {
106
107
. ok_or ( ByteConversionError :: PointNotInSubgroup )
107
108
}
108
109
109
- #[ allow( unused) ]
110
+ #[ cfg( feature = "alloc" ) ]
111
+ fn compress_g2_point ( point : & Self :: G2Point ) -> Self :: G2Compressed {
112
+ if * point == G2Point :: neutral_element ( ) {
113
+ // point is at infinity
114
+ let mut x_bytes = [ 0_u8 ; 96 ] ;
115
+ x_bytes[ 0 ] |= 1 << 7 ;
116
+ x_bytes[ 0 ] |= 1 << 6 ;
117
+ x_bytes
118
+ } else {
119
+ // point is not at infinity
120
+ let point_affine = point. to_affine ( ) ;
121
+ let x = point_affine. x ( ) ;
122
+ let y = point_affine. y ( ) ;
123
+
124
+ let x_rev: FieldElement < Degree2ExtensionField > =
125
+ FieldElement :: new ( [ x. value ( ) [ 1 ] . clone ( ) , x. value ( ) [ 0 ] . clone ( ) ] ) ;
126
+ let mut x_bytes = [ 0u8 ; 96 ] ;
127
+ let bytes = x_rev. to_bytes_be ( ) ;
128
+ x_bytes. copy_from_slice ( & bytes) ;
129
+
130
+ // Set first bit to to 1 indicate this is compressed element.
131
+ x_bytes[ 0 ] |= 1 << 7 ;
132
+
133
+ // Set the 3rd bit based on y value.
134
+ let y_neg = -y;
135
+
136
+ match (
137
+ y. value ( ) [ 0 ]
138
+ . representative ( )
139
+ . cmp ( & y_neg. value ( ) [ 0 ] . representative ( ) ) ,
140
+ y. value ( ) [ 1 ]
141
+ . representative ( )
142
+ . cmp ( & y_neg. value ( ) [ 1 ] . representative ( ) ) ,
143
+ ) {
144
+ ( Ordering :: Greater , _) | ( Ordering :: Equal , Ordering :: Greater ) => {
145
+ x_bytes[ 0 ] |= 1 << 5 ;
146
+ }
147
+ ( _, _) => ( ) ,
148
+ }
149
+ x_bytes
150
+ }
151
+ }
152
+
110
153
fn decompress_g2_point ( input_bytes : & mut [ u8 ; 96 ] ) -> Result < Self :: G2Point , Self :: Error > {
111
154
let first_byte = input_bytes. first ( ) . unwrap ( ) ;
112
155
@@ -124,6 +167,8 @@ impl Compress for BLS12381Curve {
124
167
return Ok ( Self :: G2Point :: neutral_element ( ) ) ;
125
168
}
126
169
170
+ let third_bit = prefix_bits & 1_u8 ;
171
+
127
172
let first_byte_without_control_bits = ( first_byte << 3 ) >> 3 ;
128
173
input_bytes[ 0 ] = first_byte_without_control_bits;
129
174
@@ -136,7 +181,7 @@ impl Compress for BLS12381Curve {
136
181
const VALUE : BLS12381FieldElement = BLS12381FieldElement :: from_hex_unchecked ( "4" ) ;
137
182
let b_param_qfe = FieldElement :: < Degree2ExtensionField > :: new ( [ VALUE , VALUE ] ) ;
138
183
139
- let y = sqrt:: sqrt_qfe ( & ( x. pow ( 3_u64 ) + b_param_qfe) , 0 )
184
+ let y = sqrt:: sqrt_qfe ( & ( x. pow ( 3_u64 ) + b_param_qfe) , third_bit )
140
185
. ok_or ( ByteConversionError :: InvalidValue ) ?;
141
186
142
187
Self :: G2Point :: from_affine ( x, y) . map_err ( |_| ByteConversionError :: InvalidValue )
@@ -204,8 +249,7 @@ mod tests {
204
249
use crate :: elliptic_curve:: short_weierstrass:: traits:: Compress ;
205
250
206
251
let g = BLS12381Curve :: generator ( ) ;
207
- let compressed_g = BLS12381Curve :: compress_g1_point ( & g) ;
208
- let mut compressed_g_slice: [ u8 ; 48 ] = compressed_g. try_into ( ) . unwrap ( ) ;
252
+ let mut compressed_g_slice = BLS12381Curve :: compress_g1_point ( & g) ;
209
253
210
254
let decompressed_g = BLS12381Curve :: decompress_g1_point ( & mut compressed_g_slice) . unwrap ( ) ;
211
255
@@ -219,11 +263,106 @@ mod tests {
219
263
// calculate g point operate with itself
220
264
let g_2 = g. operate_with_self ( UnsignedInteger :: < 4 > :: from ( "2" ) ) ;
221
265
222
- let compressed_g2 = BLS12381Curve :: compress_g1_point ( & g_2) ;
223
- let mut compressed_g2_slice: [ u8 ; 48 ] = compressed_g2. try_into ( ) . unwrap ( ) ;
266
+ let mut compressed_g2_slice: [ u8 ; 48 ] = BLS12381Curve :: compress_g1_point ( & g_2) ;
224
267
225
268
let decompressed_g2 = BLS12381Curve :: decompress_g1_point ( & mut compressed_g2_slice) . unwrap ( ) ;
226
269
227
270
assert_eq ! ( g_2, decompressed_g2) ;
228
271
}
272
+
273
+ #[ cfg( feature = "alloc" ) ]
274
+ #[ test]
275
+ fn test_compress_decompress_generator_g2 ( ) {
276
+ use crate :: elliptic_curve:: short_weierstrass:: {
277
+ curves:: bls12_381:: twist:: BLS12381TwistCurve , traits:: Compress ,
278
+ } ;
279
+
280
+ let g = BLS12381TwistCurve :: generator ( ) ;
281
+ let mut compressed_g_slice = BLS12381Curve :: compress_g2_point ( & g) ;
282
+
283
+ let decompressed_g = BLS12381Curve :: decompress_g2_point ( & mut compressed_g_slice) . unwrap ( ) ;
284
+
285
+ assert_eq ! ( g, decompressed_g) ;
286
+ }
287
+
288
+ #[ cfg( feature = "alloc" ) ]
289
+ #[ test]
290
+ fn test_compress_decompress_generator_g2_neg ( ) {
291
+ use crate :: elliptic_curve:: short_weierstrass:: {
292
+ curves:: bls12_381:: twist:: BLS12381TwistCurve , traits:: Compress ,
293
+ } ;
294
+
295
+ let g = BLS12381TwistCurve :: generator ( ) ;
296
+ let g_neg = g. neg ( ) ;
297
+
298
+ let mut compressed_g_neg_slice = BLS12381Curve :: compress_g2_point ( & g_neg) ;
299
+
300
+ let decompressed_g_neg =
301
+ BLS12381Curve :: decompress_g2_point ( & mut compressed_g_neg_slice) . unwrap ( ) ;
302
+
303
+ assert_eq ! ( g_neg, decompressed_g_neg) ;
304
+ }
305
+
306
+ #[ cfg( feature = "alloc" ) ]
307
+ #[ test]
308
+ fn test_decompress_g2 ( ) {
309
+ use crate :: {
310
+ elliptic_curve:: short_weierstrass:: curves:: bls12_381:: {
311
+ field_extension:: Degree2ExtensionField , twist:: BLS12381TwistCurve ,
312
+ } ,
313
+ field:: element:: FieldElement ,
314
+ } ;
315
+
316
+ let mut compressed_point = [ 0_u8 ; 96 ] ;
317
+ compressed_point[ 0 ] |= 1 << 7 ;
318
+ compressed_point[ 95 ] |= 1 << 1 ;
319
+
320
+ // Valig G2 point coordinates:
321
+ let x_0 = BLS12381FieldElement :: from_hex_unchecked ( "02" ) ;
322
+ let x_1 = BLS12381FieldElement :: from_hex_unchecked ( "0" ) ;
323
+ let y_0 = BLS12381FieldElement :: from_hex_unchecked ( "013a59858b6809fca4d9a3b6539246a70051a3c88899964a42bc9a69cf9acdd9dd387cfa9086b894185b9a46a402be73" ) ;
324
+ let y_1 = BLS12381FieldElement :: from_hex_unchecked ( "02d27e0ec3356299a346a09ad7dc4ef68a483c3aed53f9139d2f929a3eecebf72082e5e58c6da24ee32e03040c406d4f" ) ;
325
+
326
+ let x: FieldElement < Degree2ExtensionField > = FieldElement :: new ( [ x_0, x_1] ) ;
327
+ let y: FieldElement < Degree2ExtensionField > = FieldElement :: new ( [ y_0, y_1] ) ;
328
+
329
+ let valid_g2_point = BLS12381TwistCurve :: create_point_from_affine ( x, y) . unwrap ( ) ;
330
+
331
+ let decompressed_point = BLS12381Curve :: decompress_g2_point ( & mut compressed_point) . unwrap ( ) ;
332
+
333
+ assert_eq ! ( valid_g2_point, decompressed_point) ;
334
+ }
335
+
336
+ #[ cfg( feature = "alloc" ) ]
337
+ #[ test]
338
+ fn test_compress_g2 ( ) {
339
+ use crate :: {
340
+ elliptic_curve:: short_weierstrass:: {
341
+ curves:: bls12_381:: {
342
+ field_extension:: Degree2ExtensionField , twist:: BLS12381TwistCurve ,
343
+ } ,
344
+ traits:: Compress ,
345
+ } ,
346
+ field:: element:: FieldElement ,
347
+ } ;
348
+
349
+ // Valig G2 point coordinates:
350
+ let x_0 = BLS12381FieldElement :: from_hex_unchecked ( "02" ) ;
351
+ let x_1 = BLS12381FieldElement :: from_hex_unchecked ( "0" ) ;
352
+ let y_0 = BLS12381FieldElement :: from_hex_unchecked ( "013a59858b6809fca4d9a3b6539246a70051a3c88899964a42bc9a69cf9acdd9dd387cfa9086b894185b9a46a402be73" ) ;
353
+ let y_1 = BLS12381FieldElement :: from_hex_unchecked ( "02d27e0ec3356299a346a09ad7dc4ef68a483c3aed53f9139d2f929a3eecebf72082e5e58c6da24ee32e03040c406d4f" ) ;
354
+
355
+ let x: FieldElement < Degree2ExtensionField > = FieldElement :: new ( [ x_0, x_1] ) ;
356
+ let y: FieldElement < Degree2ExtensionField > = FieldElement :: new ( [ y_0, y_1] ) ;
357
+
358
+ let point = BLS12381TwistCurve :: create_point_from_affine ( x, y) . unwrap ( ) ;
359
+
360
+ let compress_point = BLS12381Curve :: compress_g2_point ( & point) ;
361
+
362
+ let mut valid_compressed_point = [ 0_u8 ; 96 ] ;
363
+ valid_compressed_point[ 0 ] |= 1 << 7 ;
364
+ valid_compressed_point[ 95 ] |= 1 << 1 ;
365
+
366
+ assert_eq ! ( compress_point, valid_compressed_point) ;
367
+ }
229
368
}
0 commit comments