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