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 }