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  }