github.com/Evanesco-Labs/go-evanesco@v1.0.1/zkpminer/keypair/unmarshall.go (about) 1 package keypair 2 3 // This file implements compressed point unmarshaling. Preferably this 4 // functionality would be in a standard library. Code borrowed from: 5 // https://go-review.googlesource.com/#/c/1883/2/src/crypto/elliptic/elliptic.go 6 7 import ( 8 "crypto/elliptic" 9 "math/big" 10 ) 11 12 // Unmarshal a compressed point in the form specified in section 4.3.6 of ANSI X9.62. 13 func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { 14 byteLen := (curve.Params().BitSize + 7) >> 3 15 if (data[0] &^ 1) != 2 { 16 return // unrecognized point encoding 17 } 18 if len(data) != 1+byteLen { 19 return 20 } 21 22 // Based on Routine 2.2.4 in NIST Mathematical routines paper 23 params := curve.Params() 24 tx := new(big.Int).SetBytes(data[1 : 1+byteLen]) 25 y2 := y2(params, tx) 26 sqrt := defaultSqrt 27 ty := sqrt(y2, params.P) 28 if ty == nil { 29 return // "y^2" is not a square: invalid point 30 } 31 var y2c big.Int 32 y2c.Mul(ty, ty).Mod(&y2c, params.P) 33 if y2c.Cmp(y2) != 0 { 34 return // sqrt(y2)^2 != y2: invalid point 35 } 36 if ty.Bit(0) != uint(data[0]&1) { 37 ty.Sub(params.P, ty) 38 } 39 40 x, y = tx, ty 41 return 42 } 43 44 // Use the curve equation to calculate y² given x. 45 // only applies to curves of the form y² = x³ + b. 46 func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int { 47 x3 := new(big.Int).Mul(x, x) 48 x3.Mul(x3, x) 49 50 x3.Add(x3, curve.B) 51 x3.Mod(x3, curve.P) 52 return x3 53 } 54 55 func defaultSqrt(x, p *big.Int) *big.Int { 56 var r big.Int 57 if nil == r.ModSqrt(x, p) { 58 return nil // x is not a square 59 } 60 return &r 61 }