github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/comm/crypto.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package comm
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"crypto/tls"
    14  	"crypto/x509"
    15  	"encoding/pem"
    16  	"errors"
    17  	"fmt"
    18  	"math/big"
    19  	"os"
    20  
    21  	"github.com/hyperledger/fabric/common/util"
    22  	gutil "github.com/hyperledger/fabric/gossip/util"
    23  	"golang.org/x/net/context"
    24  	"google.golang.org/grpc/credentials"
    25  	"google.golang.org/grpc/peer"
    26  )
    27  
    28  func writeFile(filename string, keyType string, data []byte) error {
    29  	f, err := os.Create(filename)
    30  	if err != nil {
    31  		return err
    32  	}
    33  	defer f.Close()
    34  	return pem.Encode(f, &pem.Block{Type: keyType, Bytes: data})
    35  }
    36  
    37  func GenerateCertificatesOrPanic() tls.Certificate {
    38  	privKeyFile := fmt.Sprintf("key.%d.priv", gutil.RandomUInt64())
    39  	certKeyFile := fmt.Sprintf("cert.%d.pub", gutil.RandomUInt64())
    40  
    41  	defer os.Remove(privKeyFile)
    42  	defer os.Remove(certKeyFile)
    43  	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  
    48  	sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
    49  	if err != nil {
    50  		panic(err)
    51  	}
    52  	template := x509.Certificate{
    53  		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    54  		SerialNumber: sn,
    55  		ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    56  	}
    57  	rawBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
    58  	if err != nil {
    59  		panic(err)
    60  	}
    61  	err = writeFile(certKeyFile, "CERTIFICATE", rawBytes)
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  	privBytes, err := x509.MarshalECPrivateKey(privateKey)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  	err = writeFile(privKeyFile, "EC PRIVATE KEY", privBytes)
    70  	if err != nil {
    71  		panic(err)
    72  	}
    73  	cert, err := tls.LoadX509KeyPair(certKeyFile, privKeyFile)
    74  	if err != nil {
    75  		panic(err)
    76  	}
    77  	if len(cert.Certificate) == 0 {
    78  		panic(errors.New("Certificate chain is empty"))
    79  	}
    80  	return cert
    81  }
    82  
    83  func certHashFromRawCert(rawCert []byte) []byte {
    84  	if len(rawCert) == 0 {
    85  		return nil
    86  	}
    87  	return util.ComputeSHA256(rawCert)
    88  }
    89  
    90  // ExtractCertificateHash extracts the hash of the certificate from the stream
    91  func extractCertificateHashFromContext(ctx context.Context) []byte {
    92  	pr, extracted := peer.FromContext(ctx)
    93  	if !extracted {
    94  		return nil
    95  	}
    96  
    97  	authInfo := pr.AuthInfo
    98  	if authInfo == nil {
    99  		return nil
   100  	}
   101  
   102  	tlsInfo, isTLSConn := authInfo.(credentials.TLSInfo)
   103  	if !isTLSConn {
   104  		return nil
   105  	}
   106  	certs := tlsInfo.State.PeerCertificates
   107  	if len(certs) == 0 {
   108  		return nil
   109  	}
   110  	raw := certs[0].Raw
   111  	return certHashFromRawCert(raw)
   112  }