github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/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  }