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