@@ -52,11 +52,8 @@ func (curve *CurveParams) Params() *CurveParams {
52
52
return curve
53
53
}
54
54
55
- func (curve * CurveParams ) IsOnCurve (x , y * big.Int ) bool {
56
- // y² = x³ - 3x + b
57
- y2 := new (big.Int ).Mul (y , y )
58
- y2 .Mod (y2 , curve .P )
59
-
55
+ // polynomial returns x³ - 3x + b
56
+ func (curve * CurveParams ) polynomial (x * big.Int ) * big.Int {
60
57
x3 := new (big.Int ).Mul (x , x )
61
58
x3 .Mul (x3 , x )
62
59
@@ -67,7 +64,15 @@ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
67
64
x3 .Add (x3 , curve .B )
68
65
x3 .Mod (x3 , curve .P )
69
66
70
- return x3 .Cmp (y2 ) == 0
67
+ return x3
68
+ }
69
+
70
+ func (curve * CurveParams ) IsOnCurve (x , y * big.Int ) bool {
71
+ // y² = x³ - 3x + b
72
+ y2 := new (big.Int ).Mul (y , y )
73
+ y2 .Mod (y2 , curve .P )
74
+
75
+ return curve .polynomial (x ).Cmp (y2 ) == 0
71
76
}
72
77
73
78
// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
@@ -321,21 +326,39 @@ func Marshal(curve Curve, x, y *big.Int) []byte {
321
326
// On error, x = nil.
322
327
func Unmarshal (curve Curve , data []byte ) (x , y * big.Int ) {
323
328
byteLen := (curve .Params ().BitSize + 7 ) >> 3
324
- if len (data ) != 1 + 2 * byteLen {
325
- return
326
- }
327
- if data [0 ] != 4 { // uncompressed form
328
- return
329
- }
330
- p := curve .Params ().P
331
- x = new (big.Int ).SetBytes (data [1 : 1 + byteLen ])
332
- y = new (big.Int ).SetBytes (data [1 + byteLen :])
333
- if x .Cmp (p ) >= 0 || y .Cmp (p ) >= 0 {
334
- return nil , nil
335
- }
336
- if ! curve .IsOnCurve (x , y ) {
337
- return nil , nil
329
+
330
+ switch data [0 ] {
331
+ case 2 , 3 : // compressed form
332
+ if len (data ) != 1 + byteLen {
333
+ return
334
+ }
335
+
336
+ x = new (big.Int ).SetBytes (data [1 :])
337
+ x3 := curve .Params ().polynomial (x )
338
+ y = new (big.Int ).ModSqrt (x3 , curve .Params ().P )
339
+
340
+ // Jacobi(x, p) == -1
341
+ if y == nil {
342
+ return nil , nil
343
+ } else if y .Bit (0 ) != uint (data [0 ]& 0x1 ) {
344
+ y .Neg (y )
345
+ y .Mod (y , curve .Params ().P )
346
+ }
347
+ case 4 : // uncompressed form
348
+ if len (data ) != 1 + 2 * byteLen {
349
+ return
350
+ }
351
+ p := curve .Params ().P
352
+ x = new (big.Int ).SetBytes (data [1 : 1 + byteLen ])
353
+ y = new (big.Int ).SetBytes (data [1 + byteLen :])
354
+ if x .Cmp (p ) >= 0 || y .Cmp (p ) >= 0 {
355
+ return nil , nil
356
+ }
357
+ if ! curve .IsOnCurve (x , y ) {
358
+ return nil , nil
359
+ }
338
360
}
361
+
339
362
return
340
363
}
341
364
0 commit comments