github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/cmd/common/signer/signer.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package signer
     8  
     9  import (
    10  	"crypto"
    11  	"crypto/ecdsa"
    12  	"crypto/rand"
    13  	"crypto/x509"
    14  	"encoding/asn1"
    15  	"encoding/pem"
    16  	"io/ioutil"
    17  	"math/big"
    18  	"strings"
    19  
    20  	"github.com/hechain20/hechain/bccsp/utils"
    21  	"github.com/hechain20/hechain/common/util"
    22  	"github.com/hechain20/hechain/protoutil"
    23  	"github.com/hyperledger/fabric-protos-go/msp"
    24  	"github.com/pkg/errors"
    25  )
    26  
    27  // Config holds the configuration for
    28  // creation of a Signer
    29  type Config struct {
    30  	MSPID        string
    31  	IdentityPath string
    32  	KeyPath      string
    33  }
    34  
    35  // Signer signs messages.
    36  // TODO: Ideally we'd use an MSP to be agnostic, but since it's impossible to
    37  // initialize an MSP without a CA cert that signs the signing identity,
    38  // this will do for now.
    39  type Signer struct {
    40  	key     *ecdsa.PrivateKey
    41  	Creator []byte
    42  }
    43  
    44  func (si *Signer) Serialize() ([]byte, error) {
    45  	return si.Creator, nil
    46  }
    47  
    48  // NewSigner creates a new Signer out of the given configuration
    49  func NewSigner(conf Config) (*Signer, error) {
    50  	sId, err := serializeIdentity(conf.IdentityPath, conf.MSPID)
    51  	if err != nil {
    52  		return nil, errors.WithStack(err)
    53  	}
    54  	key, err := loadPrivateKey(conf.KeyPath)
    55  	if err != nil {
    56  		return nil, errors.WithStack(err)
    57  	}
    58  	return &Signer{
    59  		Creator: sId,
    60  		key:     key,
    61  	}, nil
    62  }
    63  
    64  func serializeIdentity(clientCert string, mspID string) ([]byte, error) {
    65  	b, err := ioutil.ReadFile(clientCert)
    66  	if err != nil {
    67  		return nil, errors.WithStack(err)
    68  	}
    69  	if err := validateEnrollmentCertificate(b); err != nil {
    70  		return nil, err
    71  	}
    72  	sId := &msp.SerializedIdentity{
    73  		Mspid:   mspID,
    74  		IdBytes: b,
    75  	}
    76  	return protoutil.MarshalOrPanic(sId), nil
    77  }
    78  
    79  func validateEnrollmentCertificate(b []byte) error {
    80  	bl, _ := pem.Decode(b)
    81  	if bl == nil {
    82  		return errors.Errorf("enrollment certificate isn't a valid PEM block")
    83  	}
    84  
    85  	if bl.Type != "CERTIFICATE" {
    86  		return errors.Errorf("enrollment certificate should be a certificate, got a %s instead", strings.ToLower(bl.Type))
    87  	}
    88  
    89  	if _, err := x509.ParseCertificate(bl.Bytes); err != nil {
    90  		return errors.Errorf("enrollment certificate is not a valid x509 certificate: %v", err)
    91  	}
    92  	return nil
    93  }
    94  
    95  func (si *Signer) Sign(msg []byte) ([]byte, error) {
    96  	digest := util.ComputeSHA256(msg)
    97  	return signECDSA(si.key, digest)
    98  }
    99  
   100  func loadPrivateKey(file string) (*ecdsa.PrivateKey, error) {
   101  	b, err := ioutil.ReadFile(file)
   102  	if err != nil {
   103  		return nil, errors.WithStack(err)
   104  	}
   105  	bl, _ := pem.Decode(b)
   106  	if bl == nil {
   107  		return nil, errors.Errorf("failed to decode PEM block from %s", file)
   108  	}
   109  	key, err := parsePrivateKey(bl.Bytes)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	return key.(*ecdsa.PrivateKey), nil
   114  }
   115  
   116  // Based on crypto/tls/tls.go but modified for Fabric:
   117  func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
   118  	// OpenSSL 1.0.0 generates PKCS#8 keys.
   119  	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
   120  		switch key := key.(type) {
   121  		// Fabric only supports ECDSA at the moment.
   122  		case *ecdsa.PrivateKey:
   123  			return key, nil
   124  		default:
   125  			return nil, errors.Errorf("found unknown private key type (%T) in PKCS#8 wrapping", key)
   126  		}
   127  	}
   128  
   129  	// OpenSSL ecparam generates SEC1 EC private keys for ECDSA.
   130  	key, err := x509.ParseECPrivateKey(der)
   131  	if err != nil {
   132  		return nil, errors.Errorf("failed to parse private key: %v", err)
   133  	}
   134  
   135  	return key, nil
   136  }
   137  
   138  func signECDSA(k *ecdsa.PrivateKey, digest []byte) (signature []byte, err error) {
   139  	r, s, err := ecdsa.Sign(rand.Reader, k, digest)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	s, err = utils.ToLowS(&k.PublicKey, s)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	return marshalECDSASignature(r, s)
   150  }
   151  
   152  func marshalECDSASignature(r, s *big.Int) ([]byte, error) {
   153  	return asn1.Marshal(ECDSASignature{r, s})
   154  }
   155  
   156  type ECDSASignature struct {
   157  	R, S *big.Int
   158  }