github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/comm/crypto.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package comm
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"crypto/elliptic"
    22  	"crypto/rand"
    23  	"crypto/tls"
    24  	"crypto/x509"
    25  	"encoding/pem"
    26  	"errors"
    27  	"fmt"
    28  	"math/big"
    29  	"os"
    30  
    31  	"github.com/hyperledger/fabric/common/util"
    32  	gutil "github.com/hyperledger/fabric/gossip/util"
    33  	"golang.org/x/net/context"
    34  	"google.golang.org/grpc/credentials"
    35  	"google.golang.org/grpc/peer"
    36  )
    37  
    38  func writeFile(filename string, keyType string, data []byte) error {
    39  	f, err := os.Create(filename)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	defer f.Close()
    44  	return pem.Encode(f, &pem.Block{Type: keyType, Bytes: data})
    45  }
    46  
    47  func GenerateCertificatesOrPanic() tls.Certificate {
    48  	privKeyFile := fmt.Sprintf("key.%d.priv", gutil.RandomUInt64())
    49  	certKeyFile := fmt.Sprintf("cert.%d.pub", gutil.RandomUInt64())
    50  
    51  	defer os.Remove(privKeyFile)
    52  	defer os.Remove(certKeyFile)
    53  	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    54  	if err != nil {
    55  		panic(err)
    56  	}
    57  
    58  	sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
    59  	if err != nil {
    60  		panic(err)
    61  	}
    62  	template := x509.Certificate{
    63  		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    64  		SerialNumber: sn,
    65  		ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    66  	}
    67  	rawBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
    68  	if err != nil {
    69  		panic(err)
    70  	}
    71  	err = writeFile(certKeyFile, "CERTIFICATE", rawBytes)
    72  	if err != nil {
    73  		panic(err)
    74  	}
    75  	privBytes, err := x509.MarshalECPrivateKey(privateKey)
    76  	if err != nil {
    77  		panic(err)
    78  	}
    79  	err = writeFile(privKeyFile, "EC PRIVATE KEY", privBytes)
    80  	if err != nil {
    81  		panic(err)
    82  	}
    83  	cert, err := tls.LoadX509KeyPair(certKeyFile, privKeyFile)
    84  	if err != nil {
    85  		panic(err)
    86  	}
    87  	if len(cert.Certificate) == 0 {
    88  		panic(errors.New("Certificate chain is empty"))
    89  	}
    90  	return cert
    91  }
    92  
    93  func certHashFromRawCert(rawCert []byte) []byte {
    94  	if len(rawCert) == 0 {
    95  		return nil
    96  	}
    97  	return util.ComputeSHA256(rawCert)
    98  }
    99  
   100  // ExtractCertificateHash extracts the hash of the certificate from the stream
   101  func extractCertificateHashFromContext(ctx context.Context) []byte {
   102  	pr, extracted := peer.FromContext(ctx)
   103  	if !extracted {
   104  		return nil
   105  	}
   106  
   107  	authInfo := pr.AuthInfo
   108  	if authInfo == nil {
   109  		return nil
   110  	}
   111  
   112  	tlsInfo, isTLSConn := authInfo.(credentials.TLSInfo)
   113  	if !isTLSConn {
   114  		return nil
   115  	}
   116  	certs := tlsInfo.State.PeerCertificates
   117  	if len(certs) == 0 {
   118  		return nil
   119  	}
   120  	raw := certs[0].Raw
   121  	return certHashFromRawCert(raw)
   122  }