github.com/turingchain2020/turingchain@v1.1.21/common/vrf/secp256k1/unmarshal.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Copyright 2016 Google Inc. All Rights Reserved. 6 // 7 // Licensed under the Apache License, Version 2.0 (the "License"); 8 // you may not use this file except in compliance with the License. 9 // You may obtain a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an "AS IS" BASIS, 15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 // See the License for the specific language governing permissions and 17 // limitations under the License. 18 19 package secp256k1 20 21 import ( 22 "crypto/elliptic" 23 "math/big" 24 ) 25 26 // Unmarshal a compressed point in the form specified in section 4.3.6 of ANSI X9.62. 27 func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { 28 byteLen := (curve.Params().BitSize + 7) >> 3 29 if (data[0] &^ 1) != 2 { 30 return // unrecognized point encoding 31 } 32 if len(data) != 1+byteLen { 33 return 34 } 35 36 // Based on Routine 2.2.4 in NIST Mathematical routines paper 37 params := curve.Params() 38 tx := new(big.Int).SetBytes(data[1 : 1+byteLen]) 39 y2 := y2(params, tx) 40 sqrt := defaultSqrt 41 ty := sqrt(y2, params.P) 42 if ty == nil { 43 return // "y^2" is not a square: invalid point 44 } 45 var y2c big.Int 46 y2c.Mul(ty, ty).Mod(&y2c, params.P) 47 if y2c.Cmp(y2) != 0 { 48 return // sqrt(y2)^2 != y2: invalid point 49 } 50 if ty.Bit(0) != uint(data[0]&1) { 51 ty.Sub(params.P, ty) 52 } 53 54 x, y = tx, ty // valid point: return it 55 return 56 } 57 58 // Use the curve equation to calculate y² given x. 59 // only applies to curves of the form y² = x³ + b. 60 func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int { 61 62 // y² = x³ + b 63 x3 := new(big.Int).Mul(x, x) 64 x3.Mul(x3, x) 65 66 //threeX := new(big.Int).Lsh(x, 1) 67 //threeX.Add(threeX, x) 68 // 69 //x3.Sub(x3, threeX) 70 x3.Add(x3, curve.B) 71 x3.Mod(x3, curve.P) 72 return x3 73 } 74 75 func defaultSqrt(x, p *big.Int) *big.Int { 76 var r big.Int 77 if nil == r.ModSqrt(x, p) { 78 return nil // x is not a square 79 } 80 return &r 81 }