HyperLedgerFabric源码解读(3)-certsto
2018-11-20 本文已影响7人
神奇的考拉
关于gossip中证书/身份存储的内容
package gossip
// 传播所有的身份信息
// certStore supports pull dissemination of identity messages
type certStore struct {
selfIdentity api.PeerIdentityType // peer自身的身份
idMapper identity.Mapper // 公钥和身份的映射关系:公钥PKIid :身份
pull pull.Mediator // 获取消息中介
logger util.Logger
mcs api.MessageCryptoService // 信息加密服务
}
// 新建身份存储
func newCertStore(puller pull.Mediator, // PullEngine的包装类 提供获取同步相关的方法
idMapper identity.Mapper, // <PKIid, Certificates/identifies> 公钥ID 与 证书或身份的映射
selfIdentity api.PeerIdentityType, // 自身标识
mcs api.MessageCryptoService) *certStore { // 信息加密服务
// 获取对应身份的公钥UD
selfPKIID := idMapper.GetPKIidOfCert(selfIdentity)
//
logger := util.GetLogger(util.LoggingGossipModule, string(selfPKIID))
certStore := &certStore{
mcs: mcs, // 信息加密服务
pull: puller, // 获取者
idMapper: idMapper, // 本地公钥、身份/证书映射器
selfIdentity: selfIdentity, // 自身标识
logger: logger,
}
// 添加自身公钥ID与身份的关联关系
if err := certStore.idMapper.Put(selfPKIID, selfIdentity); err != nil {
certStore.logger.Panicf("Failed associating self PKIID to cert: %+v", errors.WithStack(err))
}
// 创建身份信息
selfIDMsg, err := certStore.createIdentityMessage()
if err != nil {
certStore.logger.Panicf("Failed creating self identity message: %+v", errors.WithStack(err))
}
// 添加到获取中间代理上 并将注册一个钩子到指定类型的消息(RegisterMsgHook)
puller.Add(selfIDMsg)
puller.RegisterMsgHook(pull.RequestMsgType, func(_ []string, msgs []*proto.SignedGossipMessage, _ proto.ReceivedMessage) {
// 遍历签名的Gossip Message 获取每个消息里面的每个对等节点peer的公钥ID 、身份证书; 并将公钥ID 、身份证书放到映射表中
for _, msg := range msgs {
pkiID := common.PKIidType(msg.GetPeerIdentity().PkiId)
cert := api.PeerIdentityType(msg.GetPeerIdentity().Cert)
if err := certStore.idMapper.Put(pkiID, cert); err != nil {
certStore.logger.Warningf("Failed adding identity %v, reason %+v", cert, errors.WithStack(err))
}
}
})
return certStore
}
// 处理消息
func (cs *certStore) handleMessage(msg proto.ReceivedMessage) {
// 获取GossipMessage的更新数据
if update := msg.GetGossipMessage().GetDataUpdate(); update != nil {
// 提取更新的数据 并解码Envelope转为对应的gossip message签名消息
for _, env := range update.Data {
m, err := env.ToGossipMessage()
if err != nil {
cs.logger.Warningf("Data update contains an invalid message: %+v", errors.WithStack(err))
return
}
// 转换的签名gossip message是否是身份信息
if !m.IsIdentityMsg() {
cs.logger.Warning("Got a non-identity message:", m, "aborting")
return
}
// 检验身份信息的有效性
if err := cs.validateIdentityMsg(m); err != nil {
cs.logger.Warningf("Failed validating identity message: %+v", errors.WithStack(err))
return
}
}
}
// 通过获取中间代理处理消息
cs.pull.HandleMessage(msg)
}
// 验证身份消息
func (cs *certStore) validateIdentityMsg(msg *proto.SignedGossipMessage) error {
// 从签名消息SignedGossipMessage中提取对等节点peer的身份
idMsg := msg.GetPeerIdentity()
if idMsg == nil {
return errors.Errorf("Identity empty: %+v", msg)
}
// 提取对等节点peer身份信息中的公钥ID
pkiID := idMsg.PkiId
// 提取对等节点peer身份信息中的证书
cert := idMsg.Cert
// 根据对等节点peer的身份类型提取对应的证书公钥ID
calculatedPKIID := cs.mcs.GetPKIidOfCert(api.PeerIdentityType(cert))
// 声明的公钥ID
claimedPKIID := common.PKIidType(pkiID)
// 对比计算的公钥ID 和 声明的公钥id进行比较,判断计算的公钥ID是否与对等节点peer的身份信息的内容匹配
if !bytes.Equal(calculatedPKIID, claimedPKIID) {
return errors.Errorf("Calculated pkiID doesn't match identity: calculated: %v, claimedPKI-ID: %v", calculatedPKIID, claimedPKIID)
}
// 定义检验函数:通过消息加密服务(Message Crypto Service )
verifier := func(peerIdentity []byte, signature, message []byte) error {
return cs.mcs.Verify(api.PeerIdentityType(peerIdentity), signature, message)
}
// 检验消息
err := msg.Verify(cert, verifier)
if err != nil {
return errors.Wrap(err, "Failed verifying message")
}
// 验证身份
return cs.mcs.ValidateIdentity(api.PeerIdentityType(idMsg.Cert))
}
// 创建身份消息
func (cs *certStore) createIdentityMessage() (*proto.SignedGossipMessage, error) {
// 对等节点身份
pi := &proto.PeerIdentity{
Cert: cs.selfIdentity, // 自身身份(标识)
Metadata: nil, // 元数据
PkiId: cs.idMapper.GetPKIidOfCert(cs.selfIdentity), // 从映射表中获取公钥ID
}
// Gossip消息
m := &proto.GossipMessage{
Channel: nil, // 通道
Nonce: 0, //
Tag: proto.GossipMessage_EMPTY, // gossip message的标记
Content: &proto.GossipMessage_PeerIdentity{ // 对等节点身份Gossip消息的内容:对等节点身份内容
PeerIdentity: pi,
},
}
signer := func(msg []byte) ([]byte, error) { // 消息签名函数
return cs.idMapper.Sign(msg)
}
sMsg := &proto.SignedGossipMessage{ // 签名后的gossip message
GossipMessage: m,
}
_, err := sMsg.Sign(signer) // 绑定签名和消息
return sMsg, errors.WithStack(err) // 返回签名后的gossip 消息 作为身份消息
}
// 异常节点
func (cs *certStore) suspectPeers(isSuspected api.PeerSuspector) {
cs.idMapper.SuspectPeers(isSuspected)
}
// 关闭证书存储: 获取中间代理关闭、公钥和身份映射关闭
func (cs *certStore) stop() {
cs.pull.Stop()
cs.idMapper.Stop()
}