github.com/turingchain2020/turingchain@v1.1.21/system/crypto/secp256r1/utils.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  package ecdsa
     6  
     7  import (
     8  	"crypto/ecdsa"
     9  	"crypto/elliptic"
    10  	"encoding/asn1"
    11  	"errors"
    12  	"fmt"
    13  	"math/big"
    14  )
    15  
    16  const (
    17  	pubkeyUncompressed byte = 0x4 // x coord + y coord
    18  )
    19  
    20  // MarshalECDSASignature marshal ECDSA signature
    21  func MarshalECDSASignature(r, s *big.Int) ([]byte, error) {
    22  	return asn1.Marshal(signatureECDSA{r, s})
    23  }
    24  
    25  // UnmarshalECDSASignature unmarshal ECDSA signature
    26  func UnmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
    27  	sig := new(signatureECDSA)
    28  	_, err := asn1.Unmarshal(raw, sig)
    29  	if err != nil {
    30  		return nil, nil, fmt.Errorf("failed unmashalling signature [%s]", err)
    31  	}
    32  
    33  	if sig.R == nil || sig.S == nil {
    34  		return nil, nil, errors.New("invalid signature, R/S must be different from nil")
    35  	}
    36  
    37  	if sig.R.Sign() != 1 || sig.S.Sign() != 1 {
    38  		return nil, nil, errors.New("invalid signature, R/S must be larger than zero")
    39  	}
    40  
    41  	return sig.R, sig.S, nil
    42  }
    43  
    44  // ToLowS convert to low int
    45  func ToLowS(k *ecdsa.PublicKey, s *big.Int) *big.Int {
    46  	lowS := IsLowS(s)
    47  	if !lowS {
    48  		s.Sub(k.Params().N, s)
    49  
    50  		return s
    51  	}
    52  
    53  	return s
    54  }
    55  
    56  // IsLowS check is low int
    57  func IsLowS(s *big.Int) bool {
    58  	return s.Cmp(new(big.Int).Rsh(elliptic.P256().Params().N, 1)) != 1
    59  }
    60  
    61  // SerializePublicKeyCompressed serialize compressed publicKey
    62  func SerializePublicKeyCompressed(p *ecdsa.PublicKey) []byte {
    63  	byteLen := (elliptic.P256().Params().BitSize + 7) >> 3
    64  	compressed := make([]byte, 1+byteLen)
    65  	compressed[0] = byte(p.Y.Bit(0)) | 2
    66  
    67  	xBytes := p.X.Bytes()
    68  	copy(compressed[1:], xBytes)
    69  	return compressed
    70  }
    71  
    72  // y² = x³ - 3x + b
    73  func polynomial(B, P, x *big.Int) *big.Int {
    74  	x3 := new(big.Int).Mul(x, x)
    75  	x3.Mul(x3, x)
    76  
    77  	threeX := new(big.Int).Lsh(x, 1)
    78  	threeX.Add(threeX, x)
    79  
    80  	x3.Sub(x3, threeX)
    81  	x3.Add(x3, B)
    82  	x3.Mod(x3, P)
    83  
    84  	return x3
    85  }
    86  
    87  func parsePubKeyCompressed(data []byte) (*ecdsa.PublicKey, error) {
    88  	curve := elliptic.P256()
    89  	byteLen := (curve.Params().BitSize + 7) / 8
    90  	if len(data) != 1+byteLen {
    91  		return nil, errors.New("parsePubKeyCompressed byteLen error")
    92  	}
    93  	if data[0] != 2 && data[0] != 3 { // compressed form
    94  		return nil, errors.New("parsePubKeyCompressed compressed form error")
    95  	}
    96  	p := curve.Params().P
    97  	x := new(big.Int).SetBytes(data[1:])
    98  	if x.Cmp(p) >= 0 {
    99  		return nil, errors.New("parsePubKeyCompressed x data error")
   100  	}
   101  
   102  	y := polynomial(curve.Params().B, curve.Params().P, x)
   103  	y = y.ModSqrt(y, p)
   104  	if y == nil {
   105  		return nil, errors.New("parsePubKeyCompressed y data error")
   106  	}
   107  	if byte(y.Bit(0)) != data[0]&1 {
   108  		y.Neg(y).Mod(y, p)
   109  	}
   110  	if !curve.IsOnCurve(x, y) {
   111  		return nil, errors.New("parsePubKeyCompressed IsOnCurve error")
   112  	}
   113  
   114  	pubkey := ecdsa.PublicKey{}
   115  	pubkey.Curve = curve
   116  	pubkey.X = x
   117  	pubkey.Y = y
   118  	return &pubkey, nil
   119  }
   120  
   121  // SerializePrivateKey serialize private key
   122  func SerializePrivateKey(p *ecdsa.PrivateKey) []byte {
   123  	b := make([]byte, 0, privateKeyECDSALength)
   124  	return paddedAppend(privateKeyECDSALength, b, p.D.Bytes())
   125  }
   126  
   127  func paddedAppend(size uint, dst, src []byte) []byte {
   128  	for i := 0; i < int(size)-len(src); i++ {
   129  		dst = append(dst, 0)
   130  	}
   131  	return append(dst, src...)
   132  }