diff --git a/common/tools/cryptogen/ca/ca_test.go b/common/tools/cryptogen/ca/ca_test.go index 3cc0529aa07..a56cf368042 100644 --- a/common/tools/cryptogen/ca/ca_test.go +++ b/common/tools/cryptogen/ca/ca_test.go @@ -71,7 +71,7 @@ func TestGenerateSignCertificate(t *testing.T) { rootCA, err := ca.NewCA(caDir, testCA2Name) assert.NoError(t, err, "Error generating CA") - err = rootCA.SignCertificate(certDir, testName, ecPubKey) + _, err = rootCA.SignCertificate(certDir, testName, ecPubKey) assert.NoError(t, err, "Failed to generate signed certificate") // check to make sure the signed public key was stored @@ -79,7 +79,7 @@ func TestGenerateSignCertificate(t *testing.T) { assert.Equal(t, true, checkForFile(pemFile), "Expected to find file "+pemFile) - err = rootCA.SignCertificate(certDir, "empty/CA", ecPubKey) + _, err = rootCA.SignCertificate(certDir, "empty/CA", ecPubKey) assert.Error(t, err, "Bad name should fail") // use an empty CA to test error path @@ -87,7 +87,7 @@ func TestGenerateSignCertificate(t *testing.T) { Name: "badCA", SignCert: &x509.Certificate{}, } - err = badCA.SignCertificate(certDir, testName, &ecdsa.PublicKey{}) + _, err = badCA.SignCertificate(certDir, testName, &ecdsa.PublicKey{}) assert.Error(t, err, "Empty CA should not be able to sign") cleanup(testDir) diff --git a/common/tools/cryptogen/ca/generator.go b/common/tools/cryptogen/ca/generator.go index 5bdfcb96e48..95eb012a8f3 100644 --- a/common/tools/cryptogen/ca/generator.go +++ b/common/tools/cryptogen/ca/generator.go @@ -86,7 +86,7 @@ func NewCA(baseDir, name string) (*CA, error) { // SignCertificate creates a signed certificate based on a built-in template // and saves it in baseDir/name -func (ca *CA) SignCertificate(baseDir, name string, pub *ecdsa.PublicKey) error { +func (ca *CA) SignCertificate(baseDir, name string, pub *ecdsa.PublicKey) (*x509.Certificate, error) { template := x509Template() template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} @@ -97,14 +97,14 @@ func (ca *CA) SignCertificate(baseDir, name string, pub *ecdsa.PublicKey) error template.Subject = subject - _, err := genCertificateECDSA(baseDir, name, &template, ca.SignCert, + cert, err := genCertificateECDSA(baseDir, name, &template, ca.SignCert, pub, ca.Signer) if err != nil { - return err + return nil, err } - return nil + return cert, nil } // default template for X509 subject diff --git a/common/tools/cryptogen/main.go b/common/tools/cryptogen/main.go index 229202a8435..d403888f073 100644 --- a/common/tools/cryptogen/main.go +++ b/common/tools/cryptogen/main.go @@ -351,8 +351,9 @@ func generatePeerOrg(baseDir string, orgSpec OrgSpec) { // copy the admin cert to each of the org's peer's MSP admincerts for _, peerName := range peerNames { - err = copyAdminCert(usersDir, filepath.Join(peersDir, peerName, - "admincerts"), adminUserName) + err = copyAdminCert(usersDir, + filepath.Join(peersDir, peerName, "msp", "admincerts"), + adminUserName) if err != nil { fmt.Printf("Error copying admin cert for org %s peer %s:\n%v\n", orgName, peerName, err) @@ -372,7 +373,7 @@ func copyAdminCert(usersDir, adminCertsDir, adminUserName string) error { if err != nil { return err } - err = copyFile(filepath.Join(usersDir, adminUserName, "signcerts", + err = copyFile(filepath.Join(usersDir, adminUserName, "msp", "signcerts", adminUserName+"-cert.pem"), filepath.Join(adminCertsDir, adminUserName+"-cert.pem")) if err != nil { @@ -444,8 +445,8 @@ func generateOrdererOrg(baseDir string, orgSpec OrgSpec) { // copy the admin cert to each of the org's orderers's MSP admincerts for _, ordererName := range ordererNames { - err = copyAdminCert(usersDir, filepath.Join(orderersDir, ordererName, - "admincerts"), adminUserName) + err = copyAdminCert(usersDir, + filepath.Join(orderersDir, ordererName, "msp", "admincerts"), adminUserName) if err != nil { fmt.Printf("Error copying admin cert for org %s orderer %s:\n%v\n", orgName, ordererName, err) diff --git a/common/tools/cryptogen/msp/generator.go b/common/tools/cryptogen/msp/generator.go index 27d54bd63de..d956bbe138f 100644 --- a/common/tools/cryptogen/msp/generator.go +++ b/common/tools/cryptogen/msp/generator.go @@ -21,42 +21,76 @@ import ( "os" "path/filepath" + "encoding/hex" + "io" + + "github.com/hyperledger/fabric/bccsp" "github.com/hyperledger/fabric/common/tools/cryptogen/ca" "github.com/hyperledger/fabric/common/tools/cryptogen/csp" ) func GenerateLocalMSP(baseDir, name string, rootCA *ca.CA) error { - var response error // create folder structure - err := createFolderStructure(baseDir) - response = err - if err == nil { - // generate private key - priv, _, err := csp.GeneratePrivateKey(filepath.Join(baseDir, "keystore")) - response = err - if err == nil { - // get public signing certificate - ecPubKey, err := csp.GetECPublicKey(priv) - response = err - if err == nil { - err = rootCA.SignCertificate(filepath.Join(baseDir, "signcerts"), - name, ecPubKey) - response = err - if err == nil { - // write root cert to folders - folders := []string{"admincerts", "cacerts"} - for _, folder := range folders { - err = x509ToFile(filepath.Join(baseDir, folder), rootCA.Name, rootCA.SignCert) - if err != nil { - return err - } - } - } - } + mspDir := filepath.Join(baseDir, "msp") + tlsDir := filepath.Join(baseDir, "tls") + + err := createFolderStructure(mspDir) + if err != nil { + return err + } + + err = os.MkdirAll(tlsDir, 0755) + if err != nil { + return err + } + + // get keystore path + keystore := filepath.Join(mspDir, "keystore") + + // generate private key + priv, _, err := csp.GeneratePrivateKey(keystore) + if err != nil { + return err + } + + // get public signing certificate + ecPubKey, err := csp.GetECPublicKey(priv) + if err != nil { + return err + } + + cert, err := rootCA.SignCertificate(filepath.Join(mspDir, "signcerts"), name, ecPubKey) + if err != nil { + return err + } + + // write artifacts to MSP folders + folders := []string{"admincerts", "cacerts"} + for _, folder := range folders { + err = x509Export(filepath.Join(mspDir, folder, x509Filename(rootCA.Name)), rootCA.SignCert) + if err != nil { + return err } } - return response + + // write artifacts to TLS folder + err = x509Export(filepath.Join(tlsDir, "ca.crt"), rootCA.SignCert) + if err != nil { + return err + } + + err = x509Export(filepath.Join(tlsDir, "server.crt"), cert) + if err != nil { + return err + } + + err = keyExport(keystore, filepath.Join(tlsDir, "server.key"), priv) + if err != nil { + return err + } + + return nil } func GenerateVerifyingMSP(baseDir string, rootCA *ca.CA) error { @@ -64,16 +98,17 @@ func GenerateVerifyingMSP(baseDir string, rootCA *ca.CA) error { // create folder structure err := createFolderStructure(baseDir) if err == nil { - // write public cert to appropriate folders + // write MSP cert to appropriate folders folders := []string{"admincerts", "cacerts", "signcerts"} for _, folder := range folders { - err = x509ToFile(filepath.Join(baseDir, folder), rootCA.Name, rootCA.SignCert) + err = x509Export(filepath.Join(baseDir, folder, x509Filename(rootCA.Name)), rootCA.SignCert) if err != nil { return err } } } - return err + + return nil } func createFolderStructure(rootDir string) error { @@ -92,21 +127,50 @@ func createFolderStructure(rootDir string) error { return err } } + return nil } -func x509ToFile(baseDir, name string, cert *x509.Certificate) error { +func x509Filename(name string) string { + return name + "-cert.pem" +} - //write cert out to file - fileName := filepath.Join(baseDir, name+"-cert.pem") - certFile, err := os.Create(fileName) +func x509Export(path string, cert *x509.Certificate) error { + return pemExport(path, "CERTIFICATE", cert.Raw) +} + +func copyFile(src, dst string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + _, err = io.Copy(out, in) + cerr := out.Close() if err != nil { return err } - //pem encode the cert - err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) - certFile.Close() + return cerr +} + +func keyExport(keystore, output string, key bccsp.Key) error { + id := hex.EncodeToString(key.SKI()) + + return copyFile(filepath.Join(keystore, id+"_sk"), output) +} - return err +func pemExport(path, pemType string, bytes []byte) error { + //write pem out to file + file, err := os.Create(path) + if err != nil { + return err + } + defer file.Close() + return pem.Encode(file, &pem.Block{Type: pemType, Bytes: bytes}) } diff --git a/common/tools/cryptogen/msp/msp_test.go b/common/tools/cryptogen/msp/msp_test.go index 594600eda3c..389db2b35c0 100644 --- a/common/tools/cryptogen/msp/msp_test.go +++ b/common/tools/cryptogen/msp/msp_test.go @@ -44,7 +44,7 @@ func TestGenerateLocalMSP(t *testing.T) { mspDir := filepath.Join(testDir, "msp") rootCA, err := ca.NewCA(caDir, testCAName) assert.NoError(t, err, "Error generating CA") - err = msp.GenerateLocalMSP(mspDir, testName, rootCA) + err = msp.GenerateLocalMSP(testDir, testName, rootCA) assert.NoError(t, err, "Failed to generate local MSP") // check to see that the right files were generated/saved diff --git a/sampleconfig/core.yaml b/sampleconfig/core.yaml index b0353a7c0ae..9478e2b34b2 100644 --- a/sampleconfig/core.yaml +++ b/sampleconfig/core.yaml @@ -193,15 +193,11 @@ peer: tls: enabled: false cert: - file: peer/tls.crt + file: tls/server.crt key: - file: peer/tls.key - # Root cert file for selfsigned certificates - # This represents a self-signed x509 cert that was used to sign the cert.file, - # this is sent to client to validate the recived certificate from server when - # establishing TLS connection + file: tls/server.key rootcert: - file: peer/tls.crt + file: tls/ca.crt # The server name use to verify the hostname returned by TLS handshake serverhostoverride: diff --git a/sampleconfig/orderer.yaml b/sampleconfig/orderer.yaml index 56e8aa0771e..0c332248a16 100644 --- a/sampleconfig/orderer.yaml +++ b/sampleconfig/orderer.yaml @@ -25,9 +25,10 @@ General: # TLS: TLS settings for the GRPC server. TLS: Enabled: false - PrivateKey: - Certificate: + PrivateKey: tls/server.key + Certificate: tls/server.crt RootCAs: + - tls/ca.crt ClientAuthEnabled: false ClientRootCAs: