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 }