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  }