Skip to content

14 · Fabric-X 认证与 MSP 协同

本章回答一个具体问题:Fabric-X 里这些 MSP 到底如何协同工作。所有 :line 引用指向 fabric-x-orderer/ / fabric-x-committer/,以及二者共享的 fabric-x-common/msp(vendored 于 fabric-x-orderer/vendor/.../fabric-x-common/msp/,与 module cache @v0.2.x 一致)。

一句话现状:Fabric-X 没有一个统一的 MSP 校验点。所有信任源自同一个 channel/shared config block —— 里面每个 party 一份 FabricMSPConfig;orderer 与 committer 各自把它重建成一个 channelconfig.Bundle(内含一个 MSPManager + PolicyManager),然后在不同检查点、以不均匀强度消费这些 MSP:有的走完整 Fabric MSP,有的为性能退化成裸 ECDSA 公钥,有的业务点甚至可以完全绕开 MSP

配套阅读:02 信任与身份模型(KMS/mTLS/链上权限 5 道关卡)、09 CA 与证书签发(fabric-ca / sign-pki / sign-kms 签发侧)。

1. 唯一信任根:一个 party = 一个 org MSP,身兼两职

  • 网络里的 MSP 集合 = 每个 party 一个 org{partyID}org1..orgN)。同一个 org{i} 同时被写进 config 的 Orderer.OrganizationsApplication.Organizations 两个组(fabric-x-orderer/config/generate/config_block_gen.go:70-122)——这与经典 Fabric(orderer org ≠ application org)不同。没有单独的 "client org",客户端 / 管理员是同一 org 下的 users/userusers/adminfabric-x-orderer/common/tools/armageddon/cryptogen.go:76-86)。
  • 每个节点角色(router / batcher / consenter / assembler)共享该 party 的 LocalMSPID = org{partyID}fabric-x-orderer/config/generate/local_config_gen.go:215),但各自有独立的 LocalMSPDir(自己的 cert/key)。
  • Consenter 条目引用 MSPID: org{i} + Identity: party.ConsenterConfig.SignCertconfig_block_gen.go:52-61fabric-x-orderer/config/shared_config.go:75)。

1.1 签名 CA 与 TLS CA 全程分离

每 party 生成两套 CAcryptogen.go:242-266):

维度签名 CATLS CA
磁盘目录msp/cacerts(+ intermediatecertsmsp/tlscacerts(+ tlsintermediatecerts
引擎存储bccspmsp.rootCerts / intermediateCertsbccspmsp.tlsRootCerts / tlsIntermediateCerts
校验逻辑validateCAIdentityvalidateTLSCAIdentity(独立 x509.VerifyOptions

来源:fabric-x-common/msp/mspimplsetup.go:109-169(signing)与 :472-523(TLS,作为独立信任根)。一个 FabricMSPConfig / 一个 MSP 对象内部并存两套互不混用的信任根 —— 对应磁盘上 cacerts vs tlscacerts 两个目录。

1.2 实际生成器 + NodeOUs 现状

角色区分靠 admincerts,不是 NodeOUs

Arma 网络引导用的是 common/tools/armageddon/cryptogen.goGenerateCryptoConfig:87-107;目录布局 :45-86),不是 internal/cryptogen/msp(后者只有测试在调,等于死代码)。armageddon 不生成 config.yaml / NodeOUs —— 用显式 admincerts(逐字节比对)做管理员识别(createAdminSignCertAndPrivateKeycryptogen.go:357-377),尽管 MSP 引擎完整支持 NodeOU 枚举与强制(mspimplsetup.go:341-416mspimplvalidate.go:234-291)。签名证书严格来说只有 batcher / consenter 必需(签 BAS / 区块),但对所有角色都生成了。

1.3 MSP 配置怎么"流通"

MSP 配置内嵌在 config block 的每个 Organization 组里fabric-x-common/common/channelconfig/organization.go:25-27OrganizationProtos.MSP)。NewChannelConfigchannel.go:85-124)遍历 Application/Orderer 子组的每个 org MSP,最后 CreateMSPManager()channelconfig/msp.go:99-110)把它们汇成一个 MSPManager

于是每个 orderer / committer 节点独立地从(引导或最新)config block 重建这个 Bundle —— 大家的 MSP 视图天然一致,且随 config-update 区块一起轮换。此外每个节点从本地磁盘加载自己那张 SignCert(fabric-x-orderer/common/msputils/localmsp.go:17-49,被 node/server/arma.go:71,106,147,188 各角色调用)作为签名身份 SigningIdentity

2. 同一张 SignCert,三种用法(协同的关键机巧)

一个 consenter 的同一张签名证书用在三处,验证代码路径却完全不同:

用途验证方式出处
区块背书策略里的 MSP 身份完整 MSP + SignaturePolicyEnvelope(N-of-M)fabric-x-orderer/node/consensus/synchronizer/sig_verifier.go:90-262msppb.NewIdentity(MspId, Identity) + EvaluateSignedData;consenter 按 ID 查 :264-271
BFT 共识快路径签名裸 ECDSA 公钥 map(shard,partyID)→ecdsa.PublicKey),公钥从 SignCert 提取,不走 MSPnode/crypto/verifier.go:30-77;公钥来源 config/config.go:697-703;验签 node/consensus/consensus.go:483-560,629-631
节点间 RPC 认证握手{ver,ts,from,to,SessionBinding}SessionBinding = TLS 导出密钥材料(绑定到具体 mTLS 连接、防重放);对照 MemberMapping(nodeID→裸公钥/身份)node/comm/commauth.go:240-284node/comm/clusterservice.go:114-167;密钥材料 node/comm/util.go:657-680(label "orderer v3 authentication label"

签名者始终是节点本地 MSP 的 SigningIdentity(同一把私钥/算法),只是 orderer 内部为低延迟走裸 ECDSA、区块校验走完整 MSP/policy。MemberMapping 由 config 的 consenter 集填充(clusterservice.go:229-254),所以裸公钥路径与 MSP 路径咬合在同一份 consenter 证书上

3. 认证检查点全景

检查点用的 MSP强度 / 出处
① 传输 mTLS只验 TLS CA(tlscacerts),与签名 CA 分离,不提取身份只证"连得上",不做业务授权;内部端口强制 mTLS(node/utils/util.go:84-91,155-162),客户端端口可选
② 客户端广播完整 MSP:SigFilter/Channel/WritersDeserializeIdentity + Validate + SatisfiesPrincipal(member)common/requestfilter/sigfilter.go:35-53;policy 名 policies.ChannelWriters,来自 bundle.PolicyManager()node/config/utils.go:39-73);默认关clientSignatureVerificationRequired=falsetest/utils/utils.go:147);batcher 独立复验(node/batcher/requests_inspector_verifier.go:143-161
③ orderer 内部裸 ECDSA + TLS 会话绑定握手(见 §2),非 MSP高性能快路径;⚠️ ConsenterSupportAdapter.SignatureVerifier() 目前是返回 nil 的 stub(TODO 缺口,node/consensus/consenter_support_adapter.go:43-51
④ 区块校验完整 MSP:/Channel/Orderer/BlockValidation = N-of-M over consenter MSP 身份orderer 同步器(synchronizer/sig_verifier.go:90-262)与 committer(下 §4)都这么验;config 加载时强制该策略"必须正好是 consenter 集"(config/verify/orderer_rules.go:528-585,consenter 一致性 :416-463,TLS-CA 一致性 :590-614
⑤ committer 每笔交易每 namespace 一套策略,可选 MSP:MspRule(Fabric cauthdsl DSL) ThresholdRule(裸公钥,完全不碰 MSP业务合法性的真正闸门;见 §4

4. Committer 的关键分叉:业务身份可绕开 MSP

Committer 侧刻意把两层解耦。

4.1 orderer 区块投递验证 —— 完整 Fabric MSP

  • 连 orderer 的客户端身份是一份完整 Fabric MSP 本地身份utils/ordererdial/identity.go:20-41msp.LoadLocalMspDir + GetDefaultSigningIdentity),用于签 deliver 流的 SeekInfo
  • orderer 端点的 TLS 信任根直接取自 config block 的 orderer-org CA 证书utils/ordererdial/dialinfo.go:37-83,从 m.OrdererOrganizationsorg.CACerts 推),不是单独的信任库。
  • 区块校验走 policies.BlockValidation + protoutil.BlockSigVerifier(BFT 时按数字 consenter ID 查身份)—— 标准 Fabric MSP/policy(utils/deliverorderer/verify.go:193-251,279-301);config 区块到来时重载 Bundle/policy,信任随之轮换(verify.go:256-277)。

4.2 每笔交易的 namespace 签名策略 —— MSP 可选

applicationpb.NamespacePolicy 是个 oneof(fabric-x-common/api/applicationpb/config.proto):

规则含义是否用 MSP出处
ThresholdRule{scheme, public_key},对裸公钥验签,不解析证书/不查 MSP(endorsement 的 Identity 字段被忽略)❌ 无 MSPutils/signature/verify.go:91-110NewNsVerifierFromKey)、verify_ecdsa.go:23-48
MspRule一个 Fabric SignaturePolicyEnvelope,经 cauthdsl.NewPolicyProvider(idDeserializer) 评估(如 OR('Org1MSP.member')),与经典 Fabric 链码背书策略同款,只是按 namespace 而非 chaincode 作用域✅ 完整 MSPutils/signature/verify.go:63-82NewNsVerifierFromMsp

分派开关:NewNsVerifierswitchutils/signature/verify.go:63-72)。逐 namespace 校验入口:service/verifier/verify.go:125-167(找不到策略 → ABORTED_SIGNATURE_INVALID)。支持方案 ECDSA / EdDSA / BLS(utils/signature/types.go:29-38);三者都是"公钥 + 方案",无证书链逻辑。

一个可疑常量

EdDSA 验签用了固定 Context: "Example_ed25519ctx"utils/signature/verify_eddsa.go:14-30)—— 看起来像遗留的占位/测试上下文串,值得留意。

4.3 谁能设/改 namespace 策略 —— 治理仍归完整 MSP

  • 设/改一个 namespace 的策略,是一笔写入 _meta namespace 的交易(key = 目标 namespace ID,value = 序列化 NamespacePolicy);通道级配置变更走 _configcommitterpb.MetaNamespaceID="_meta" / ConfigNamespaceID="_config")。
  • 这两类治理交易由通道级 /Channel/Application/LifecycleEndorsement(完整 Fabric MSP) 把关(service/verifier/policy/policy.go:34,149-156)—— namespace 不能自证 / 自改自己的治理
  • _config namespace 的交易"不在此处按 namespace 策略验签,其签名由排序服务验"(service/verifier/verify.go:138-142)。
  • 策略更新的来源严格是已落账的链上状态:coordinator 只在 VC 报 COMMITTED 后才 updateFromTxservice/coordinator/validator_committer_manager.go:368-393),再经 VerifierUpdates 增量下发,Verifier 端 updatePolicies 解析后 atomic 无锁热替换service/verifier/verify.go:39-104)。

5. MSP 引擎如何校验一个身份

共享引擎 fabric-x-common/mspbccspmsp(X.509/BCCSP 实现)身份生命周期:

DeserializeIdentity  →  Validate  →  SatisfiesPrincipal
(解析 cert / 查已知    (建链 + CRL      (role / identity / OU /
  cert-ID)             撤销 + OU 校验)    combined / anonymity 主体)
  • MSPManager.DeserializeIdentitymspmgrimpl.go:75-106)先按 MspIdmspsMap,查不到直接报 "MSP %s is not defined on channel":82-84)—— 身份必须属于 config 里声明过的某个 org
  • bccspmsp.DeserializeIdentitymspimpl.go:398-418)→ validateIdentitymspimplvalidate.go:21-61:算法检查 → 建证书链 → CRL 撤销比对 → OU 校验)。
  • SatisfiesPrincipalmspimpl.go:448-705)处理 ROLE(MEMBER/ADMIN/CLIENT/PEER/ORDERER)、IDENTITY(逐字节 cert 匹配)、ORGANIZATION_UNITCOMBINED、匿名等主体;NodeOU 开启时 admin/orderer role 走 hasOURole,否则回退到 admincerts 逐字节匹配。

Setup 管线(mspimplsetup.go)依次装载:签名 CA(setupCAs)、TLS CA(setupTLSCAs,独立信任根)、NodeOUs(setupNodeOUsV142FabricNodeOus 为空则 ouEnforcement=false)、admins、CRL、本地签名身份。

6. 与 CBDC 部署的映射

  • CBDC 的链上闸门包括 committer 上 namespace 策略;Auditor 审计与 Endorser 背书由 Panurus/FSC 交易链路实施。认证层次见信任与身份模型,不要再用固定“每笔五签”概括所有 driver 与钱包类型。
  • 网络层 MSP 由 Fabric-X topology 生成;开发环境证书流程位于 dev/scripts/gen_crypto.shdev/internal/controller/(见 09 CA 与证书签发)。
  • Orderer / Committer 的 KMS-enabled 镜像与网络构建逻辑当前归 cbdc-infra/cbdc-network/;开发 topology 来源是 dev/config/network/,生成结果在 dev/run/config/cbdc-network/。旧顶层 cbdc-network/Makefile 不是当前入口。

7. 已知软点与缺口

#问题出处
1客户端广播签名默认关(ClientSignatureVerificationRequired=falsefabric-x-orderer/test/utils/utils.go:147
2MSP 的 admin/member role 在部分 config 路径不严格区分(组织私钥即可满足策略)02 信任模型 · 缺陷清单
3mTLS 只做连通性证明,不提取调用方身份做授权node/router/shard_router.go
4armageddon 不生成 NodeOUs,角色识别退回 admincertscommon/tools/armageddon/cryptogen.go(无 config.yaml
5ConsenterSupportAdapter.SignatureVerifier() 为返回 nil 的 stubnode/consensus/consenter_support_adapter.go:43-51

[未核]

  • internal/cryptogen/msp 仅被测试引用(grep 无生产调用点),据此判为死代码/遗留;未见显式弃用注释。
  • applicationpb.Tx.ASN1Marshal 的逐字节签名输入未追(位于 fabric-x-common);仅确认它是 VerifyNs 的签名对象(utils/signature/verify.go:121)。
  • policies.ChannelWritersImplicitMetaPolicy 到 per-org SignaturePolicy 的完整评估逻辑在 vendored fabric-x-common/common/policies,仅核对了常量定义,未逐行追评估器。
  • batcher→consenter 的 BAF 提交(consenter_control_event_sender.go,走 Consensus.NotifyEvent 流)是否也套用 §2 的 NodeAuthRequest 握手,未确认。
  • §2/§4 各缺口在 fabric-x 最新主干是否已修,未核。