github.com/lzy4123/fabric@v2.1.1+incompatible/bccsp/utils/ecdsa.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package utils 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "encoding/asn1" 13 "errors" 14 "fmt" 15 "math/big" 16 ) 17 18 type ECDSASignature struct { 19 R, S *big.Int 20 } 21 22 var ( 23 // curveHalfOrders contains the precomputed curve group orders halved. 24 // It is used to ensure that signature' S value is lower or equal to the 25 // curve group order halved. We accept only low-S signatures. 26 // They are precomputed for efficiency reasons. 27 curveHalfOrders = map[elliptic.Curve]*big.Int{ 28 elliptic.P224(): new(big.Int).Rsh(elliptic.P224().Params().N, 1), 29 elliptic.P256(): new(big.Int).Rsh(elliptic.P256().Params().N, 1), 30 elliptic.P384(): new(big.Int).Rsh(elliptic.P384().Params().N, 1), 31 elliptic.P521(): new(big.Int).Rsh(elliptic.P521().Params().N, 1), 32 } 33 ) 34 35 func GetCurveHalfOrdersAt(c elliptic.Curve) *big.Int { 36 return big.NewInt(0).Set(curveHalfOrders[c]) 37 } 38 39 func MarshalECDSASignature(r, s *big.Int) ([]byte, error) { 40 return asn1.Marshal(ECDSASignature{r, s}) 41 } 42 43 func UnmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) { 44 // Unmarshal 45 sig := new(ECDSASignature) 46 _, err := asn1.Unmarshal(raw, sig) 47 if err != nil { 48 return nil, nil, fmt.Errorf("failed unmashalling signature [%s]", err) 49 } 50 51 // Validate sig 52 if sig.R == nil { 53 return nil, nil, errors.New("invalid signature, R must be different from nil") 54 } 55 if sig.S == nil { 56 return nil, nil, errors.New("invalid signature, S must be different from nil") 57 } 58 59 if sig.R.Sign() != 1 { 60 return nil, nil, errors.New("invalid signature, R must be larger than zero") 61 } 62 if sig.S.Sign() != 1 { 63 return nil, nil, errors.New("invalid signature, S must be larger than zero") 64 } 65 66 return sig.R, sig.S, nil 67 } 68 69 func SignatureToLowS(k *ecdsa.PublicKey, signature []byte) ([]byte, error) { 70 r, s, err := UnmarshalECDSASignature(signature) 71 if err != nil { 72 return nil, err 73 } 74 75 s, err = ToLowS(k, s) 76 if err != nil { 77 return nil, err 78 } 79 80 return MarshalECDSASignature(r, s) 81 } 82 83 // IsLow checks that s is a low-S 84 func IsLowS(k *ecdsa.PublicKey, s *big.Int) (bool, error) { 85 halfOrder, ok := curveHalfOrders[k.Curve] 86 if !ok { 87 return false, fmt.Errorf("curve not recognized [%s]", k.Curve) 88 } 89 90 return s.Cmp(halfOrder) != 1, nil 91 92 } 93 94 func ToLowS(k *ecdsa.PublicKey, s *big.Int) (*big.Int, error) { 95 lowS, err := IsLowS(k, s) 96 if err != nil { 97 return nil, err 98 } 99 100 if !lowS { 101 // Set s to N - s that will be then in the lower part of signature space 102 // less or equal to half order 103 s.Sub(k.Params().N, s) 104 105 return s, nil 106 } 107 108 return s, nil 109 }