github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 "math/big" 27 "net" 28 "os" 29 "time" 30 31 "github.com/hyperledger/fabric/common/util" 32 "golang.org/x/net/context" 33 "google.golang.org/grpc/credentials" 34 "google.golang.org/grpc/peer" 35 ) 36 37 func writeFile(filename string, keyType string, data []byte) error { 38 f, err := os.Create(filename) 39 if err != nil { 40 return err 41 } 42 defer f.Close() 43 return pem.Encode(f, &pem.Block{Type: keyType, Bytes: data}) 44 } 45 46 func generateCertificates(privKeyFile string, certKeyFile string) error { 47 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 48 if err != nil { 49 return err 50 } 51 52 sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) 53 if err != nil { 54 return err 55 } 56 template := x509.Certificate{ 57 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 58 SerialNumber: sn, 59 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 60 } 61 rawBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) 62 if err != nil { 63 return err 64 } 65 err = writeFile(certKeyFile, "CERTIFICATE", rawBytes) 66 if err != nil { 67 return err 68 } 69 privBytes, err := x509.MarshalECPrivateKey(privateKey) 70 if err != nil { 71 return err 72 } 73 err = writeFile(privKeyFile, "EC PRIVATE KEY", privBytes) 74 return err 75 } 76 77 func certHashFromRawCert(rawCert []byte) []byte { 78 if len(rawCert) == 0 { 79 return nil 80 } 81 return util.ComputeSHA256(rawCert) 82 } 83 84 // ExtractCertificateHash extracts the hash of the certificate from the stream 85 func extractCertificateHashFromContext(ctx context.Context) []byte { 86 pr, extracted := peer.FromContext(ctx) 87 if !extracted { 88 return nil 89 } 90 91 authInfo := pr.AuthInfo 92 if authInfo == nil { 93 return nil 94 } 95 96 tlsInfo, isTLSConn := authInfo.(credentials.TLSInfo) 97 if !isTLSConn { 98 return nil 99 } 100 certs := tlsInfo.State.PeerCertificates 101 if len(certs) == 0 { 102 return nil 103 } 104 raw := certs[0].Raw 105 return certHashFromRawCert(raw) 106 } 107 108 type authCreds struct { 109 tlsCreds credentials.TransportCredentials 110 } 111 112 func (c authCreds) Info() credentials.ProtocolInfo { 113 return c.tlsCreds.Info() 114 } 115 116 func (c *authCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.Duration) (_ net.Conn, _ credentials.AuthInfo, err error) { 117 conn, auth, err := c.tlsCreds.ClientHandshake(addr, rawConn, timeout) 118 if auth == nil && conn != nil { 119 auth = credentials.TLSInfo{State: conn.(*tls.Conn).ConnectionState()} 120 } 121 return conn, auth, err 122 } 123 124 func (c *authCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 125 return c.tlsCreds.ServerHandshake(rawConn) 126 }