(MSP)是一個(gè)提供虛擬成員操作的管理框架的組件。
MSP抽取出簽發(fā)和驗(yàn)證證書以及用戶認(rèn)證背后的所有加密機(jī)制和協(xié)議。 MSP可以定義自己的身份概念,以及這些身份管理的規(guī)則(身份驗(yàn)證)和身份驗(yàn)證(簽名生成和驗(yàn)證)。
1、MSP接口定義
// MSP is the minimal Membership Service Provider Interface to be implemented
// to accommodate peer functionality
//最基本成員服務(wù)接口 其實(shí)現(xiàn)在mspimp.go文件中
type MSP interface {
// IdentityDeserializer interface needs to be implemented by MSP
IdentityDeserializer
// Setup the MSP instance according to configuration information
Setup(config *msp.MSPConfig) error
// GetVersion returns the version of this MSP
GetVersion() MSPVersion
// GetType returns the provider type
GetType() ProviderType
// GetIdentifier returns the provider identifier
GetIdentifier() (string, error)
// GetSigningIdentity returns a signing identity corresponding to the provided identifier
GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error)
// GetDefaultSigningIdentity returns the default signing identity
GetDefaultSigningIdentity() (SigningIdentity, error)
// GetTLSRootCerts returns the TLS root certificates for this MSP
GetTLSRootCerts() [][]byte
// GetTLSIntermediateCerts returns the TLS intermediate root certificates for this MSP
GetTLSIntermediateCerts() [][]byte
// Validate checks whether the supplied identity is valid
Validate(id Identity) error
// SatisfiesPrincipal checks whether the identity matches
// the description supplied in MSPPrincipal. The check may
// involve a byte-by-byte comparison (if the principal is
// a serialized identity) or may require MSP validation
SatisfiesPrincipal(id Identity, principal *msp.MSPPrincipal) error
}
2、 BCCSP接口定義 BCCSP是加、解密及簽名服務(wù)。 bccp.go文件中默認(rèn)實(shí)現(xiàn)是sw/impl.go .
支持ecdsa、rsa以及aes算法 BCCSP的實(shí)現(xiàn)包括:
1,[sw]目錄為the software-based implementation of the BCCSP,即基于軟件的BCCSP實(shí)現(xiàn),通過調(diào)用go原生支持的密碼算法實(shí)現(xiàn),并提供keystore來保存密鑰
2,[pkcs11]目錄,為bccsp的pkcs11實(shí)現(xiàn),通過調(diào)用pkcs11接口實(shí)現(xiàn)相關(guān)加密操作,,密碼保存在pkcs11通過pin口令保護(hù)的數(shù)據(jù)庫(kù)或者硬件設(shè)備中。
type BCCSP interface {
KeyGen(opts KeyGenOpts) (k Key, err error) //生成Key
KeyDeriv(k Key, opts KeyDerivOpts) (dk Key, err error) //派生Key
KeyImport(raw interface{}, opts KeyImportOpts) (k Key, err error) //導(dǎo)入Key
GetKey(ski []byte) (k Key, err error) //獲取Key
Hash(msg []byte, opts HashOpts) (hash []byte, err error) //哈希msg
GetHash(opts HashOpts) (h hash.Hash, err error) //獲取哈希實(shí)例
Sign(k Key, digest []byte, opts SignerOpts) (signature []byte, err error) //簽名
Verify(k Key, signature, digest []byte, opts SignerOpts) (valid bool, err error) //校驗(yàn)簽名
Encrypt(k Key, plaintext []byte, opts EncrypterOpts) (ciphertext []byte, err error) //加密
Decrypt(k Key, ciphertext []byte, opts DecrypterOpts) (plaintext []byte, err error) //解密
}
//代碼在bccsp/bccsp.go
3、KeyStore接口(密鑰存儲(chǔ))定義如下: 其實(shí)現(xiàn)是bccsp/sw/fileks.go
type KeyStore interface {
ReadOnly() bool //密鑰庫(kù)是否只讀,只讀時(shí)StoreKey將失敗
GetKey(ski []byte) (k Key, err error) //如果SKI通過,返回Key.從相關(guān)文件中加載
StoreKey(k Key) (err error) //將Key存儲(chǔ)到密鑰庫(kù)中 sw實(shí)現(xiàn)是寫入相關(guān)文件
}
//代碼在bccsp/keystore.go
bccsp/sw/fileks.go中 StoreKey的實(shí)現(xiàn) 可見相關(guān)key寫入文件
func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error) {
if ks.readOnly {
return errors.New("Read only KeyStore.")
}
if k == nil {
return errors.New("Invalid key. It must be different from nil.")
}
switch k.(type) {
case *ecdsaPrivateKey:
kk := k.(*ecdsaPrivateKey)
err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)
if err != nil {
return fmt.Errorf("Failed storing ECDSA private key [%s]", err)
}
case *ecdsaPublicKey:
kk := k.(*ecdsaPublicKey)
err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)
if err != nil {
return fmt.Errorf("Failed storing ECDSA public key [%s]", err)
}
case *rsaPrivateKey:
kk := k.(*rsaPrivateKey)
err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)
if err != nil {
return fmt.Errorf("Failed storing RSA private key [%s]", err)
}
case *rsaPublicKey:
kk := k.(*rsaPublicKey)
err = ks.storePublicKey(hex.EncodeToString(k.SKI()), kk.pubKey)
if err != nil {
return fmt.Errorf("Failed storing RSA public key [%s]", err)
}
case *aesPrivateKey:
kk := k.(*aesPrivateKey)
err = ks.storeKey(hex.EncodeToString(k.SKI()), kk.privKey)
if err != nil {
return fmt.Errorf("Failed storing AES key [%s]", err)
}
4、mspconfig的初始化流程圖
其中g(shù)etMspConfig方法比較重要.也一目了然,加載相關(guān)證書存入byte[].最終串行化成json
func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.MSPConfig, error) {
///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/cacerts
cacertDir := filepath.Join(dir, cacerts)
///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/admincerts
admincertDir := filepath.Join(dir, admincerts)
// //data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/ntermediatecerts
intermediatecertsDir := filepath.Join(dir, intermediatecerts)
///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/crls
crlsDir := filepath.Join(dir, crlsfolder)
configFile := filepath.Join(dir, configfilename)
///data/config/hyperledger/fabric/crypto-config/peerOrganizations/org1.ygsoft.com/peers/peer0.org1.ygsoft.com/msp/tlscacerts
tlscacertDir := filepath.Join(dir, tlscacerts)
tlsintermediatecertsDir := filepath.Join(dir, tlsintermediatecerts)
cacerts, err := getPemMaterialFromDir(cacertDir)
if err != nil || len(cacerts) == 0 {
return nil, errors.WithMessage(err, fmt.Sprintf("could not load a valid ca certificate from directory %s", cacertDir))
}
admincert, err := getPemMaterialFromDir(admincertDir)
if err != nil || len(admincert) == 0 {
return nil, errors.WithMessage(err, fmt.Sprintf("could not load a valid admin certificate from directory %s", admincertDir))
}
intermediatecerts, err := getPemMaterialFromDir(intermediatecertsDir)
if os.IsNotExist(err) {
mspLogger.Debugf("Intermediate certs folder not found at [%s]. Skipping. [%s]", intermediatecertsDir, err)
} else if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("failed loading intermediate ca certs at [%s]", intermediatecertsDir))
}
tlsCACerts, err := getPemMaterialFromDir(tlscacertDir)
tlsIntermediateCerts := [][]byte{}
if os.IsNotExist(err) {
mspLogger.Debugf("TLS CA certs folder not found at [%s]. Skipping and ignoring TLS intermediate CA folder. [%s]", tlsintermediatecertsDir, err)
} else if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("failed loading TLS ca certs at [%s]", tlsintermediatecertsDir))
} else if len(tlsCACerts) != 0 {
tlsIntermediateCerts, err = getPemMaterialFromDir(tlsintermediatecertsDir)
if os.IsNotExist(err) {
mspLogger.Debugf("TLS intermediate certs folder not found at [%s]. Skipping. [%s]", tlsintermediatecertsDir, err)
} else if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("failed loading TLS intermediate ca certs at [%s]", tlsintermediatecertsDir))
}
} else {
mspLogger.Debugf("TLS CA certs folder at [%s] is empty. Skipping.", tlsintermediatecertsDir)
}
crls, err := getPemMaterialFromDir(crlsDir)
if os.IsNotExist(err) {
mspLogger.Debugf("crls folder not found at [%s]. Skipping. [%s]", crlsDir, err)
} else if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("failed loading crls at [%s]", crlsDir))
}
// Load configuration file
// if the configuration file is there then load it
// otherwise skip it
//加載配置文件 ../msp/config.yaml 存在就加載,不存在就跳過
var ouis []*msp.FabricOUIdentifier
var nodeOUs *msp.FabricNodeOUs
_, err = os.Stat(configFile)
if err == nil {
// load the file, if there is a failure in loading it then
// return an error
raw, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, errors.Wrapf(err, "failed loading configuration file at [%s]", configFile)
}
configuration := Configuration{}
err = yaml.Unmarshal(raw, &configuration)
if err != nil {
return nil, errors.Wrapf(err, "failed unmarshalling configuration file at [%s]", configFile)
}
// Prepare OrganizationalUnitIdentifiers
if len(configuration.OrganizationalUnitIdentifiers) > 0 {
for _, ouID := range configuration.OrganizationalUnitIdentifiers {
f := filepath.Join(dir, ouID.Certificate)
raw, err = readFile(f)
if err != nil {
return nil, errors.Wrapf(err, "failed loading OrganizationalUnit certificate at [%s]", f)
}
oui := &msp.FabricOUIdentifier{
Certificate: raw,
OrganizationalUnitIdentifier: ouID.OrganizationalUnitIdentifier,
}
ouis = append(ouis, oui)
}
}
// Prepare NodeOUs
if configuration.NodeOUs != nil && configuration.NodeOUs.Enable {
mspLogger.Info("Loading NodeOUs")
if configuration.NodeOUs.ClientOUIdentifier == nil || len(configuration.NodeOUs.ClientOUIdentifier.OrganizationalUnitIdentifier) == 0 {
return nil, errors.New("Failed loading NodeOUs. ClientOU must be different from nil.")
}
if configuration.NodeOUs.PeerOUIdentifier == nil || len(configuration.NodeOUs.PeerOUIdentifier.OrganizationalUnitIdentifier) == 0 {
return nil, errors.New("Failed loading NodeOUs. PeerOU must be different from nil.")
}
nodeOUs = &msp.FabricNodeOUs{
Enable: configuration.NodeOUs.Enable,
ClientOUIdentifier: &msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.ClientOUIdentifier.OrganizationalUnitIdentifier},
PeerOUIdentifier: &msp.FabricOUIdentifier{OrganizationalUnitIdentifier: configuration.NodeOUs.PeerOUIdentifier.OrganizationalUnitIdentifier},
}
// Read certificates, if defined
// ClientOU
f := filepath.Join(dir, configuration.NodeOUs.ClientOUIdentifier.Certificate)
raw, err = readFile(f)
if err != nil {
mspLogger.Infof("Failed loading ClientOU certificate at [%s]: [%s]", f, err)
} else {
nodeOUs.ClientOUIdentifier.Certificate = raw
}
// PeerOU
f = filepath.Join(dir, configuration.NodeOUs.PeerOUIdentifier.Certificate)
raw, err = readFile(f)
if err != nil {
mspLogger.Debugf("Failed loading PeerOU certificate at [%s]: [%s]", f, err)
} else {
nodeOUs.PeerOUIdentifier.Certificate = raw
}
}
} else {
mspLogger.Debugf("MSP configuration file not found at [%s]: [%s]", configFile, err)
}
// Set FabricCryptoConfig
cryptoConfig := &msp.FabricCryptoConfig{
SignatureHashFamily: bccsp.SHA2,
IdentityIdentifierHashFunction: bccsp.SHA256,
}
// Compose FabricMSPConfig
fmspconf := &msp.FabricMSPConfig{
Admins: admincert,
RootCerts: cacerts,
IntermediateCerts: intermediatecerts,
SigningIdentity: sigid,
Name: ID,
OrganizationalUnitIdentifiers: ouis,
RevocationList: crls,
CryptoConfig: cryptoConfig,
TlsRootCerts: tlsCACerts,
TlsIntermediateCerts: tlsIntermediateCerts,
FabricNodeOUs: nodeOUs,
}
//串行化成json格式的byte[]
fmpsjs, _ := proto.Marshal(fmspconf)
//MSPConfig的msp_config.pb.go文件中定義
//type MSPConfig struct {
//Type int32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"`
//Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"`
//}
mspconf := &msp.MSPConfig{Config: fmpsjs, Type: int32(FABRIC)}
return mspconf, nil
msp/mspimplsetup.go文件中根據(jù)上面生成的mspconf對(duì)證書進(jìn)行了相關(guān)設(shè)置,結(jié)果保存
在/mspimpl.go中的結(jié)體bccspmsp中
func (msp *bccspmsp) preSetupV1(conf *m.FabricMSPConfig) error {
// setup crypto config
if err := msp.setupCrypto(conf); err != nil {
return err
}
// Setup CAs //設(shè)置ca證書,中間證書等,涉及到x509包。并構(gòu)建相關(guān)identity類。
//根據(jù)證書內(nèi)容加hash后生成identity類
if err := msp.setupCAs(conf); err != nil {
return err
}
// Setup Admins
if err := msp.setupAdmins(conf); err != nil {
return err
}
// Setup CRLs
if err := msp.setupCRLs(conf); err != nil {
return err
}
// Finalize setup of the CAs
if err := msp.finalizeSetupCAs(conf); err != nil {
return err
}
// setup the signer (if present)
if err := msp.setupSigningIdentity(conf); err != nil {
return err
}
// setup TLS CAs
if err := msp.setupTLSCAs(conf); err != nil {
return err
}
// setup the OUs
if err := msp.setupOUs(conf); err != nil {
return err
}
return nil
}

]]>