美文网首页区块链-HyperLedger Fabric
HyperLedgerFabric源码解读(3)-certsto

HyperLedgerFabric源码解读(3)-certsto

作者: 神奇的考拉 | 来源:发表于2018-11-20 16:03 被阅读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()
    }
    

    相关文章

      网友评论

        本文标题:HyperLedgerFabric源码解读(3)-certsto

        本文链接:https://www.haomeiwen.com/subject/ztjxqqtx.html