github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/common/tools/cryptogen/msp/generator.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 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  package msp
    17  
    18  import (
    19  	"crypto/x509"
    20  	"encoding/pem"
    21  	"os"
    22  	"path/filepath"
    23  
    24  	"encoding/hex"
    25  
    26  	"github.com/hyperledger/fabric/bccsp"
    27  	"github.com/hyperledger/fabric/bccsp/factory"
    28  	"github.com/hyperledger/fabric/common/tools/cryptogen/ca"
    29  	"github.com/hyperledger/fabric/common/tools/cryptogen/csp"
    30  )
    31  
    32  func GenerateLocalMSP(baseDir, name string, sans []string, signCA *ca.CA,
    33  	tlsCA *ca.CA) error {
    34  
    35  	// create folder structure
    36  	mspDir := filepath.Join(baseDir, "msp")
    37  	tlsDir := filepath.Join(baseDir, "tls")
    38  
    39  	err := createFolderStructure(mspDir, true)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	err = os.MkdirAll(tlsDir, 0755)
    45  	if err != nil {
    46  		return err
    47  	}
    48  
    49  	/*
    50  		Create the MSP identity artifacts
    51  	*/
    52  	// get keystore path
    53  	keystore := filepath.Join(mspDir, "keystore")
    54  
    55  	// generate private key
    56  	priv, _, err := csp.GeneratePrivateKey(keystore)
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	// get public key
    62  	ecPubKey, err := csp.GetECPublicKey(priv)
    63  	if err != nil {
    64  		return err
    65  	}
    66  	// generate X509 certificate using signing CA
    67  	cert, err := signCA.SignCertificate(filepath.Join(mspDir, "signcerts"),
    68  		name, []string{}, ecPubKey, x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{})
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	// write artifacts to MSP folders
    74  
    75  	// the signing CA certificate goes into cacerts
    76  	err = x509Export(filepath.Join(mspDir, "cacerts", x509Filename(signCA.Name)), signCA.SignCert)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	// the TLS CA certificate goes into tlscacerts
    81  	err = x509Export(filepath.Join(mspDir, "tlscacerts", x509Filename(tlsCA.Name)), tlsCA.SignCert)
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	// the signing identity goes into admincerts.
    87  	// This means that the signing identity
    88  	// of this MSP is also an admin of this MSP
    89  	// NOTE: the admincerts folder is going to be
    90  	// cleared up anyway by copyAdminCert, but
    91  	// we leave a valid admin for now for the sake
    92  	// of unit tests
    93  	err = x509Export(filepath.Join(mspDir, "admincerts", x509Filename(name)), cert)
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	/*
    99  		Generate the TLS artifacts in the TLS folder
   100  	*/
   101  
   102  	// generate private key
   103  	tlsPrivKey, _, err := csp.GeneratePrivateKey(tlsDir)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	// get public key
   108  	tlsPubKey, err := csp.GetECPublicKey(tlsPrivKey)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	// generate X509 certificate using TLS CA
   113  	_, err = tlsCA.SignCertificate(filepath.Join(tlsDir),
   114  		name, sans, tlsPubKey, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment,
   115  		[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth})
   116  	if err != nil {
   117  		return err
   118  	}
   119  	err = x509Export(filepath.Join(tlsDir, "ca.crt"), tlsCA.SignCert)
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	// rename the generated TLS X509 cert
   125  	err = os.Rename(filepath.Join(tlsDir, x509Filename(name)),
   126  		filepath.Join(tlsDir, "server.crt"))
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	err = keyExport(tlsDir, filepath.Join(tlsDir, "server.key"), tlsPrivKey)
   132  	if err != nil {
   133  		return err
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  func GenerateVerifyingMSP(baseDir string, signCA *ca.CA, tlsCA *ca.CA) error {
   140  
   141  	// create folder structure and write artifacts to proper locations
   142  	err := createFolderStructure(baseDir, false)
   143  	if err == nil {
   144  		// the signing CA certificate goes into cacerts
   145  		err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(signCA.Name)), signCA.SignCert)
   146  		if err != nil {
   147  			return err
   148  		}
   149  		// the TLS CA certificate goes into tlscacerts
   150  		err = x509Export(filepath.Join(baseDir, "tlscacerts", x509Filename(tlsCA.Name)), tlsCA.SignCert)
   151  		if err != nil {
   152  			return err
   153  		}
   154  	}
   155  
   156  	// create a throwaway cert to act as an admin cert
   157  	// NOTE: the admincerts folder is going to be
   158  	// cleared up anyway by copyAdminCert, but
   159  	// we leave a valid admin for now for the sake
   160  	// of unit tests
   161  	factory.InitFactories(nil)
   162  	bcsp := factory.GetDefault()
   163  	priv, err := bcsp.KeyGen(&bccsp.ECDSAP256KeyGenOpts{Temporary: true})
   164  	ecPubKey, err := csp.GetECPublicKey(priv)
   165  	if err != nil {
   166  		return err
   167  	}
   168  	_, err = signCA.SignCertificate(filepath.Join(baseDir, "admincerts"), signCA.Name,
   169  		[]string{""}, ecPubKey, x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{})
   170  	if err != nil {
   171  		return err
   172  	}
   173  
   174  	return nil
   175  }
   176  
   177  func createFolderStructure(rootDir string, local bool) error {
   178  
   179  	var folders []string
   180  	// create admincerts, cacerts, keystore and signcerts folders
   181  	folders = []string{
   182  		filepath.Join(rootDir, "admincerts"),
   183  		filepath.Join(rootDir, "cacerts"),
   184  		filepath.Join(rootDir, "tlscacerts"),
   185  	}
   186  	if local {
   187  		folders = append(folders, filepath.Join(rootDir, "keystore"),
   188  			filepath.Join(rootDir, "signcerts"))
   189  	}
   190  
   191  	for _, folder := range folders {
   192  		err := os.MkdirAll(folder, 0755)
   193  		if err != nil {
   194  			return err
   195  		}
   196  	}
   197  
   198  	return nil
   199  }
   200  
   201  func x509Filename(name string) string {
   202  	return name + "-cert.pem"
   203  }
   204  
   205  func x509Export(path string, cert *x509.Certificate) error {
   206  	return pemExport(path, "CERTIFICATE", cert.Raw)
   207  }
   208  
   209  func keyExport(keystore, output string, key bccsp.Key) error {
   210  	id := hex.EncodeToString(key.SKI())
   211  
   212  	return os.Rename(filepath.Join(keystore, id+"_sk"), output)
   213  }
   214  
   215  func pemExport(path, pemType string, bytes []byte) error {
   216  	//write pem out to file
   217  	file, err := os.Create(path)
   218  	if err != nil {
   219  		return err
   220  	}
   221  	defer file.Close()
   222  
   223  	return pem.Encode(file, &pem.Block{Type: pemType, Bytes: bytes})
   224  }