Skip to content

09 · CA 与证书签发

本章只描述代码与配置中可直接定位的事实。证书层级、根 CA / 中间 CA / 叶子证书的实际部署模式以 sign-ca/fabric-ca/ 源码为准;cbdc-chain 内部 docs/ 不作引用。

1. 系统中所有 CA 触点

触点角色主要文件
sign-ca/Dockerfile构建 fabric-ca-server + PKCS#11 库的镜像sign-ca/Dockerfile:7-93
sign-ca/cmd/sign-ca-cli/离线签名工具(root self-sign + intermediate sign-csr)sign-ca/cmd/sign-ca-cli/commands/*.go
sign-ca/deploy/multi-ca/per-bank intermediate CA 部署样板sign-ca/deploy/multi-ca/docker-compose.yamlroot/README.md
fabric-ca/lib/enroll/register/reenroll/revoke/gencrl/idemix 全部 HTTP 处理fabric-ca/lib/server*.go
cbdc-infra/cbdc-tool/Dockerfile打包 fabric-ca-client + fxconfig + libkms_pkcs11.socbdc-infra/cbdc-tool/Dockerfile
cbdc-network/Makefilemake setup-kms 调 cbdc-tool 生成网络层证书,并从 CA 拉 TLS rootcbdc-network/Makefile:85-117, 208-237
cbdc-biz/scripts/gen_crypto.sh在 setup 阶段为 issuer / auditor wallet + bizhub admin 调 fabric-ca-client enroll,并 gen_institution_cert 签发 institution 证书cbdc-biz/scripts/gen_crypto.sh:22-75, 268-405
cbdc-biz/app/bizhub/internal/biz/ca.go运行时调 fabric-ca /enroll /register(仅 bizhub)cbdc-biz/app/bizhub/internal/biz/ca.go:166-295
cbdc-biz/app/bizhub/internal/server/mtls_middleware.go从 mTLS 客户端证书 OU/CN 提取 institution_codecbdc-biz/app/bizhub/internal/server/mtls_middleware.go:62-105

2. 三件套:fabric-ca + sign-ca + sign-kms 的分工

组件出处关键事实
fabric-ca-serversign-ca/Dockerfile:47-54FABRIC_CA_REF=v1.5.16GO_TAGS=pkcs11
Idemix 默认曲线sign-ca/Dockerfile:93CMD 强制 --idemix.curve gurvy.Bn254,覆盖 fabric-ca 默认 amcl.Fp256bnfabric-ca/lib/server/idemix/config.go:30
PKCS#11 库sign-ca/Dockerfile:78${SIGN_KMS_IMAGE} COPY libkms_pkcs11.so/usr/local/lib/
KMS 接口sign-kms/p11client/proto/kms.proto:7-135 个 RPC:GenerateKeypair / GetPublicKey / Sign / Verify / HealthCheck
私钥不出库sign-kms/internal/biz/kms_biz.go:268-317Sign 只接收 digest + key handle,PKCS#11 C_Sign 在 HSM 内完成;protobuf 无 ExportPrivateKey 类 RPC
namespace = HSM partitionsign-kms/internal/biz/kms_biz.go:56-69namespace.TokenLabel 字段绑定到 PKCS#11 partition;JWT 中的 partitionID 用于路由
PKCS#11 PINsign-ca/deploy/multi-ca/docker-compose.yaml:94fabric-ca-server 通过 FABRIC_CA_SERVER_BCCSP_PKCS11_PIN=${KMS_PIN_BANK1} 注入 JWT 作 PIN

3. 证书层级(含中间 CA)

                          Root CA (offline / 离线)
                          ├─ 私钥:sign-kms root partition
                          ├─ 证书:sign-ca/deploy/multi-ca/root/ca-cert.pem(静态)
                          └─ 由 sign-ca-cli self-sign 生成

                                │ sign-ca-cli sign-csr(离线签 CSR)

              ┌──────────────────────────────────────────────┐
              │                                              │
   Intermediate CA (per-bank)                fabric-ca-server(cbdc-ca-server-kms)
   ├─ 私钥:sign-kms partition KMS_PIN_BANKn   ├─ 私钥:sign-kms partition KMS_USER_PIN
   ├─ 证书:deploy/multi-ca/bank<n>/ca-cert.pem ├─ 仓库内 conf/ca 配为 root/独立运行
   └─ 运行 fabric-ca-server (sign-ca 镜像)     │  (parentserver.url 留空,见 §5.4/§11)
                                              └─ 是否做中间 CA 取决于部署方
              │                                              │
              ▼                                              ▼
        Bank wallet certs                         Orderer/Committer/Biz-app
        (institution-NNN admin / users)           (issuer, endorser, auditor,
                                                   institution-001, mTLS server)

仓库现状

  • sign-ca/deploy/multi-ca/完整的 root → intermediate → leaf 三层模板sign-ca/deploy/multi-ca/docker-compose.yaml:1-26root/README.md:1-51)。
  • cbdc-network/configs/test-full-kms.yamlkms: 块(:23-27)只给出 endpoint / token_label / ca_url,未声明任何分层/中间 CA(无 intermediate.parentserver.url);意味着 cbdc-network 默认走"单 fabric-ca-server"形态——这台 server 自身既可以是 root,也可以是 intermediate,取决于 ${CA_URL} 指向的 fabric-ca-server 启动配置(见 §6)。
  • 是否启用 intermediate 由部署方通过 fabric-ca-server-config.yaml: intermediate.parentserver.url 决定,配置定义见 fabric-ca/lib/caconfig.go:160-171

4. Bootstrap:root → intermediate 的离线签发

来源:sign-ca/deploy/multi-ca/docker-compose.yaml:1-26sign-ca/deploy/multi-ca/root/README.md:1-51sign-ca/cmd/sign-ca-cli/

4.1 sign-ca-cli 三个命令的代码事实

命令入口关键逻辑是否调 KMS
self-signsign-ca/cmd/sign-ca-cli/commands/self_sign.go:19, 59-104x509.CreateCertificate(rand.Reader, tmpl, tmpl, ..., signer)(template=parent=tmpl 表示自签)OpenP11Signerpki/p11.go:52-102)+ C_Sign
gen-csrsign-ca/cmd/sign-ca-cli/commands/gen_csr.go:17, 67x509.CreateCertificateRequest(rand.Reader, tmpl, signer)✅ 同上,调 C_Sign 给 CSR 自签
sign-csrsign-ca/cmd/sign-ca-cli/commands/sign_csr.go:17-127读 issuer cert 与 CSR → 校验 CSR 签名 → 由 issuer cert 推 issuer SKI → 校验 KMS key 与 issuer cert 公钥一致 → BuildCATemplate(PathLen)x509.CreateCertificate(tmpl, issuerCert, csr.PublicKey, signer)✅ issuer 私钥

BuildCATemplatesign-ca/cmd/sign-ca-cli/pki/cert.go:36-64)固定 IsCA: trueKeyUsage = CertSign | CRLSign | DigitalSignatureBasicConstraintsValid: true

  • PathLen < 0 → 不设约束(无限层级,根用)
  • PathLen == 0MaxPathLen=0, MaxPathLenZero=true(该 cert 不可再签下级 CA,叶级 intermediate 用)
  • PathLen > 0MaxPathLen=PathLen(多级 intermediate)

4.2 multi-ca 部署的 bootstrap 顺序

sign-ca/deploy/multi-ca/docker-compose.yaml:8-26 注释中明确:

  1. docker compose up -d kms postgres 启基础设施
  2. 浏览器打开 :9201,per-bank 创建 partition,拿 JWT 写入 .envKMS_PIN_BANK<n>
  3. docker compose run --rm pg-init(profile=initdocker-compose.yaml:63-81)初始化 PG role + database
  4. 预放 bank<n>/ca-cert.pem(由前述 sign-csr 离线签好),fabric-ca-server 启动时检测到该文件存在则跳过自动 self-sign
  5. docker compose up -d ca-bank<n>

root/README.md:1-6 强调:root partition 无 fabric-ca-server service、无 DB、无端口,私钥只活在 sign-kms root partition 内,由密钥仪式委员会持有 JWT。

5. fabric-ca 内置 intermediate CA 模式

仓库现状之外,fabric-ca-server 自身支持"启动时向父 CA enroll 拿 sub-CA cert"的内置 intermediate 模式(与 §4 的"离线 sign-csr 预放"是两种不同实现)。代码事实:

5.1 配置字段

fabric-ca/lib/caconfig.go:160-171

go
type ParentServer struct {
    URL    string `opt:"u" help:"URL of the parent fabric-ca-server (e.g. http://<username>:<password>@<address>:<port)" mask:"url"`
    CAName string `help:"Name of the CA to connect to on fabric-ca-server"`
}

type IntermediateCA struct {
    ParentServer ParentServer
    TLS          tls.ClientTLSConfig
    Enrollment   api.EnrollmentRequest
}

YAML 路径:intermediate.parentserver.url / intermediate.parentserver.caname / intermediate.tls.* / intermediate.enrollment.*

启动 flag:-u <parent-url>opt:"u" 标签)。

5.2 Bootstrap 流程

fabric-ca/lib/ca.go:271-300

go
if ca.Config.Intermediate.ParentServer.URL != "" {
    log.Debugf("Getting CA cert; parent server URL is %s", ...)
    // 构造 ClientConfig(TLS + Enrollment + CAName)
    resp, err = clientCfg.Enroll(ca.Config.Intermediate.ParentServer.URL, ca.HomeDir)
}

启动时若 ParentServer.URL 非空 → 当前 server 作为 client 向父 CA 调 /enroll 拿 sub-CA cert,落盘到 ca.HomeDir

5.3 证书链构造

fabric-ca/lib/ca.go:390-406, 435

go
func (ca *CA) getCAChain() (chain []byte, err error) {
    // 1) 若 ca-chain.pem 已存在 → 直接返回
    // 2) 若 ParentServer.URL == "" → 该 CA 是 root,返回 ca-cert.pem
    // 3) 否则报错——intermediate 必须有 ca-chain.pem(由 enroll 流程创建)
}

链文件默认名:ca-chain.pemfabric-ca/lib/caconfig.go:122 def:"ca-chain.pem")。链拼接顺序受环境变量 CA_CHAIN_PARENT_FIRST 控制(fabric-ca/lib/ca.go:368-377)。

5.4 两种 intermediate 模式对比

维度离线 sign-csr(§4)内置 enroll(§5)
触发点仪式机手动一次性fabric-ca-server 启动时自动
Root 在线性永久离线,root 私钥只在 sign-kms root partition父 CA 必须在线,否则 sub-CA 起不来
私钥流动全程不出 sign-kms同上(用 BCCSP PKCS#11 即可)
链文件部署方手工拼 ca-chain.pem 或 fabric-ca 启动后 /cainfo 返回fabric-ca 自动写 ca-chain.pem
当前仓库使用sign-ca/deploy/multi-ca/ 走这条部署方在 fabric-ca-server-config.yamlintermediate.parentserver.url 启用;cbdc-biz/conf/ca/fabric-ca-server-config.yaml:195-199intermediate: 块但 url 为空(即未启用,作 root/独立运行)

6. 签发流程(fabric-ca HTTP API)

6.1 端点清单

来源:fabric-ca/lib/server.go:549-570registerHandlers + registerHandler,前缀 /api/v1/ 与裸路径 /<path> 双注册)。

路径处理函数注册位置方法成功码
/enrollenrollHandlerfabric-ca/lib/serverenroll.go:49-57POST201
/reenrollreenrollHandlerfabric-ca/lib/serverenroll.go:59-67POST201
/registerregisterHandlerfabric-ca/lib/serverregister.go:23-31POST201
/revokerevokeHandlerfabric-ca/lib/serverrevoke.go:36-43POST200
/gencrlgenCRLHandlerfabric-ca/lib/servergencrl.go:36-43POST200
/cainfocainfoHandlerfabric-ca/lib/serverinfo.go:14-21GET/POST/HEAD200
/idemix/credentialhandleIdemixEnrollReqfabric-ca/lib/serveridemixenroll.go:16-24POST201
/idemix/crihandleIdemixCRIReqfabric-ca/lib/serveridemixcri.go:13-21POST201
/healthzhealthz libfabric-ca/lib/server/operations/system.go:149200

API 路径前缀常量:fabric-ca/lib/server.go:52 apiPathPrefix = "/api/v1/"

6.2 enroll 流程时序

关键代码:

  • 签名核心:fabric-ca/lib/serverenroll.go:156 cert, err := ca.enrollSigner.Sign(req.SignRequest)
  • enrollSigner 初始化:fabric-ca/lib/ca.go:749-753
    go
    ca.enrollSigner, err = util.BccspBackedSigner(c.CA.Certfile, c.CA.Keyfile, policy, ca.csp)
  • BCCSP CSP(ca.csp)通过 bccsp.factory 在初始化时按 Default: PKCS11 走 PKCS#11,CA 私钥的句柄存在 fabric-ca-server 进程内、私钥本身永远在 sign-kms 内(见 §2)。

6.3 reenroll 与 enroll 的差异

fabric-ca/lib/serverenroll.go:87-94

go
func reenrollHandler(ctx *serverRequestContextImpl) (interface{}, error) {
    id, err := ctx.TokenAuthentication()    // 用现有 cert 的 token 鉴权
    ...
    resp, err := handleEnroll(ctx, id)       // 共用 handleEnroll
}

唯一区别:鉴权方式 — enroll 用 BasicAuthentication(user+pass),reenroll 用 TokenAuthentication(持有的有效 X.509 cert 派生 token)。证书生成逻辑完全相同。

6.4 register 流程

fabric-ca/lib/serverregister.go:34-68(HTTP 层)+ 135-177(核心 registerUserID):

users 表 schema:fabric-ca/lib/server/db/sqlite/sqlite.go:138(id / token / type / affiliation / attributes / state / max_enrollments / level / incorrect_password_attempts)。

返回的 Secret 即"一次性口令",配合 enroll 的 Basic Auth 使用。

6.5 revoke 与 gencrl

fabric-ca/lib/serverrevoke.go:60-191

模式入口分支持久化动作
按 Serial+AKI:86-129certDBAccessor.RevokeCertificate(req.Serial, req.AKI, reason) :124
按身份:129-175certDBAccessor.RevokeCertificatesByID(req.Name, reason) :162 + user.Revoke() :155

req.GenCRL == true:182-189),同步生成 CRL。独立 /gencrl 端点:fabric-ca/lib/servergencrl.go:46-83,需 hf.GenCRL 属性(:70-72)。

吊销原因码 RFC 5280:fabric-ca/lib/serverrevoke.go:46-57

certificates 表:fabric-ca/lib/server/db/sqlite/sqlite.go:154(含 status / reason / revoked_at 列)。

6.6 Idemix 凭证签发

fabric-ca/lib/serveridemixenroll.go:16-33

go
// POST /api/v1/idemix/credential
ca.issuer.IssueCredential(&idemixServerCtx{ctx})

Idemix issuer 初始化:fabric-ca/lib/ca.go:136-143

go
ca.issuer = idemix.NewIssuer(ca.Config.CA.Name, ca.HomeDir,
    &ca.Config.Idemix, ca.csp, idemix.NewLib(curveID), curveID)

曲线选择:fabric-ca/lib/ca.go:1299-1312 curveIDFromConfig();默认 amcl.Fp256bnfabric-ca/lib/server/idemix/config.go:30),可选 gurvy.Bn254 / amcl.Fp256Miraclbnfabric-ca/lib/common/idemix/common.go:45-48)。sign-ca 镜像在 CMD 强制 --idemix.curve gurvy.Bn254sign-ca/Dockerfile:93

Issuer key 文件(fabric-ca/lib/server/idemix/config.go:17-26, 41-66):

文件位置
IssuerPublicKey$HomeDir/IssuerPublicKey
IssuerSecretKey$HomeDir/msp/keystore/IssuerSecretKey
IssuerRevocationPublicKey$HomeDir/IssuerRevocationPublicKey
IssuerRevocationPrivateKey$HomeDir/msp/keystore/IssuerRevocationPrivateKey

7. cbdc-* 仓库如何调 CA

7.1 cbdc-network setup 阶段(网络层证书)

来源:cbdc-network/Makefile:85-117, 208-237

事实:

  • setup-fabric-kmsMakefile:95-98,KMS_CONFIG 缺省 configs/test-full-kms.yamlMakefile:82):调 cbdc-tool 容器内 config-builder setup,生成 orderer/committer 的 crypto material 与 yaml 到 ./out/out/ 内的具体证书来自 config-builder(cbdc-tool 内置工具),不直接 shell 调 fabric-ca-client
  • fetch-fabric-ca-rootMakefile:208-233):TLS_ENABLED=true 时,从 ${CA_URL}/cainfo(去掉 URL 中凭证后)拿 result.CAChain(base64),分发到 out/local-deployment/committer-*/config/tls/ 各目录。此处仅取 Fabric CA 根证书,不做 enroll
  • ${CA_URL} 默认值(cbdc-network/.env.example:32):http://admin:adminpw@cbdc-dev.sign.global:7054

configs/test-full-kms.yaml:23-27 的 KMS 段:

yaml
kms:
  enabled: true
  endpoint: '${SIGN_KMS_ENDPOINT}'
  token_label: '${KMS_TOKEN_LABEL}'
  ca_url: '${CA_URL}'

未声明 intermediate.parentserver.url;是否启用 intermediate 由 ${CA_URL} 背后那台 fabric-ca-server 的 fabric-ca-server-config.yaml 决定(部署方配置,不在仓库内)。

7.2 cbdc-biz setup 阶段(业务层身份)

来源:cbdc-biz/scripts/gen_crypto.sh。脚本里 fabric-ca-client enroll 出现在三类钱包/MSP 身份:

  • issuer wallet(issuer/keys/wallet/issgen_crypto.sh:22-35
  • auditor wallet(auditor/keys/wallet/aud:41-54
  • bizhub admin MSP(bizhub/ca-msp/msp:63-76

每段结构相同:

bash
docker run --rm \
    -v "${dir}:/app/msp" \
    -e SIGN_KMS_ENDPOINT="..." \
    -e KMS_TOKEN_LABEL="..." \
    -e KMS_USER_PIN="..." \
    -e CA_URL="..." \
    ${DOCKER_TOOLS_IMAGE} \
    sh -c '
        envsubst < fabric-ca-client-config.yaml.tpl > fabric-ca-client-config.yaml
        ./fabric-ca-client enroll \
            -c "./fabric-ca-client-config.yaml" \
            --url "$CA_URL" \
            --mspdir "./msp"
    '

拿到的 cert 落到容器挂载的 MSP 目录,运行时由各应用 core.yamlfabric.default.msps[] 直接读。

institution 的身份则由 gen_institution_certgen_crypto.sh:268-408)单独生成,不走上面的 enroll 模板:

  • 先 enroll 出一张 TLS Intermediate CA(--enrollment.profile ca + hf.IntermediateCA=true:114-147,得到 CA:TRUE 证书);
  • 再用 openssl req -subj "/O=CBDC/OU=institution/CN=institution-${code}-01" + openssl x509 -req(由该 Intermediate CA 签)生成 institution 统一证书(FSC P2P + bizhub mTLS 共用,:340-362);
  • 同时为该 institution enroll 一份 KMS 支撑的 CA admin MSP(bizhub/ca-msp/institution-<code>/msp,PIN 取 INSTITUTION_<code>_KMS_PIN:375-405),供 §7.3 的 bizhub 运行时加载。

证书链:Fabric CA(Root,私钥在 KMS)→ Bank Intermediate CA (pathlen:0) → institution / bizhub 叶子证书(gen_crypto.sh:262 注释)。

7.3 cbdc-biz 运行时:bizhub 调 enroll / register

来源:cbdc-biz/app/bizhub/internal/biz/ca.go

bizhub 运行时直接 import github.com/hyperledger/fabric-ca/libca.go:31),为每家 institution 构造独立的 lib.Client + admin Identity(loadInstitutionAdminca.go:166-245):

go
cspOpts := &factory.FactoryOpts{
    Default: "PKCS11",
    PKCS11: &pkcs11.PKCS11Opts{
        Library:  defaults.GetLibrary(),
        Label:    label,            // pkcs11TokenLabel(defaults)
        Pin:      caCfg.GetPin(),   // 每家 institution 自己的 JWT
        Hash:     defaults.GetHash(),
        Security: int(defaults.GetSecurity()),
    },
}
client := &lib.Client{Config: &lib.ClientConfig{
    URL:    caCfg.GetUrl(),
    MSPDir: caCfg.GetAdminMsp(),
    CSP:    cspOpts,
}}
client.Init()

token label 由 pkcs11TokenLabel(defaults)ca.go:149-158)从全局配置 ca.pkcs11Defaults.label 读取——所有 institution 共享同一 label(缺省即报错,无 os.Getenv 兜底);per-institution 的隔离靠各自的 Pin(JWT,Bootstrap institutions[].ca.pin)路由到不同 partition。

institution admin 按需懒加载getInstitutionAdminca.go:121-137)首次被调用时才 loadInstitutionAdmin 并缓存,不是启动时全量加载。后续 Registerca.go:247-295)经 admin.identity.Register() 动态注册机构用户,Enrollca.go:297+)另起一个临时 lib.Client/enroll

7.4 其他业务应用:静态 MSP + KMS 签名

  • issuer / endorser / auditor / institution 的 main.go 没有 import fabric-ca-client,启动时不调 enroll;
  • 它们读 core.yaml: fabric.default.msps[].path 指向的静态 MSP 目录(cert 已经在 setup 阶段由 gen_crypto.sh 放好),私钥句柄通过 BCCSP PKCS#11 走 sign-kms:
yaml
fabric:
  default:
    driver: fabricx
    msps:
      - id: user
        mspType: bccsp
        mspID: Org1MSP
        path: ./keys/fabric/user
    opts:
      BCCSP:
        Default: PKCS11
        PKCS11:
          Library: /usr/local/lib/libkms_pkcs11.so
          Label: KMS_TK
          Pin: ${KMS_USER_PIN}

来源:cbdc-biz/conf/issuer/core.yaml:71-92。Token SDK wallet 同样走 PKCS#11(:144-155)。

7.5 cbdc-infra/cbdc-tool 镜像

来源:cbdc-infra/cbdc-tool/Dockerfile:1-50cbdc-infra/Makefile:18-22

  • 基础镜像:FROM ghcr.io/built-by-sign/fabric-x-tool:${FABRIC_X_TOOL_TAG}Dockerfile:8ARG 默认 v0.0.9Dockerfile:1),fabric-ca-client 由该基础镜像自带(cbdc-tool/Dockerfile 内未显式 RUN install)。
  • libkms_pkcs11.soDockerfile:20 COPY --from=so_source /usr/lib/libkms_pkcs11.so /app/so_source = ${SIGN_KMS_IMAGE})。

cbdc-infra/Makefile:18-22build-cbdc-tool

makefile
$(CONTAINER_CLI) build --platform=$(PLATFORM) -f ./cbdc-tool/Dockerfile \
  $(if $(FABRIC_X_TOOL_TAG),--build-arg FABRIC_X_TOOL_TAG=$(FABRIC_X_TOOL_TAG)) \
  --build-arg SIGN_KMS_IMAGE=$(SIGN_KMS_IMAGE) \
  -t $(IMAGE_PREFIX)/cbdc-tool:$(TAG) .

cbdc-ca-server-kms 镜像(sign-ca/Dockerfile):cbdc-infra/Makefile:15build-all 依赖 build-ca-server-kms:29 push cbdc-ca-server-kms:$(TAG),但 build-ca-server-kms 的 target 实体并未在 cbdc-infra/Makefile 内定义(sign-ca 仓库的镜像构建 target 名为 build,见 sign-ca/Makefile:41)。

8. mTLS 与运行时身份提取

来源:cbdc-biz/app/bizhub/internal/server/grpc.go:21-91cbdc-biz/app/bizhub/internal/server/mtls_middleware.go:22-134

8.1 服务端 TLS 装配

grpc.go:64 tls.LoadX509KeyPair(cfg.Cert, cfg.Key) 加载 server cert / key;:74-87RequireClientCert==true 时读 CA 证书并设 ClientAuth = tls.RequireAndVerifyClientCert

cbdc-biz/conf/bizhub/core.yaml:52-57

yaml
tls:
  enabled: true
  cert: ./keys/mtls-server.crt
  key:  ./keys/mtls-server.key
  ca_cert: ./keys/mtls-ca.crt       # Fabric CA root
  require_client_cert: true

8.2 客户端证书 → 角色 / institution_code

extractMTLSIdentitymtls_middleware.go:73-105)读 client cert 的 Subject OUleaf.Subject.OrganizationalUnit[0]),按 auth.Role 常量(pkg/common/auth/context.go:16,19,22)匹配:

OU 值角色institution_code 来源行号
institutionRoleInstitution从 CN(约定 institution-<code>-<seq>,split - 取 parts[1]):91-100
centralRoleCentralBank无(服务身份,不带 institution_code):101-102
auditorRoleAuditor:101-102

其它 OU(issuer/bizhub/endorser/orderer-* 等)或无 cert → 不识别,请求放行(:104)。仅 RoleInstitution 会强制校验/回填请求体的 institution_code:38-55,通过 protobuf 反射,:107-134)。

这意味着:institution client cert 的 OU 必须是字面量 institution、CN 必须是 institution-<code>-<seq>。该 cert 由 cbdc-biz/scripts/gen_crypto.sh:340-352openssl req -subj "/O=CBDC/OU=institution/CN=institution-${code}-01" 生成(见 §7.2 末),并由 TLS Intermediate CA 签发。

9. 撤销链路

  • X.509 cert 撤销:fabric-ca /revoke → certificates 表 → /gencrl 拉 CRL → cbdc-biz/pkg/common/revocation 缓存(refreshInterval = 30 * time.Secondcache.go:32;详见 02 信任与身份模型 §失效与撤销)。
  • KMS token 撤销:sign-kms DisableAccessToken 把 access token 记录置为 disabledkms_manage_biz.go:506-510),后续 JWT 校验拒绝,签名调用立即失败(无需等 CRL)。两条路独立:cert 撤销影响 mTLS / MSP 身份,KMS token 撤销影响 PKCS#11 签名调用。

10. 关键事实速查表

问题答案出处
默认 Idemix 曲线gurvy.Bn254(被 sign-ca Dockerfile CMD 强制)sign-ca/Dockerfile:93
fabric-ca 版本v1.5.16sign-ca/Dockerfile:47
fabric-ca build tagpkcs11sign-ca/Dockerfile:54
PKCS#11 库路径(容器内)/usr/local/lib/libkms_pkcs11.sosign-ca/Dockerfile:78sign-ca/cmd/sign-ca-cli/commands/doc.go:20
PKCS#11 PIN 来源FABRIC_CA_SERVER_BCCSP_PKCS11_PIN env,注入 JWTsign-ca/deploy/multi-ca/docker-compose.yaml:94
Token label固定 KMS_TK(全局),按 JWT 路由 partitionsign-ca/cmd/sign-ca-cli/pki/p11.go:35cbdc-network/.env.example:29
HTTP API 前缀/api/v1/fabric-ca/lib/server.go:52
Intermediate CA 启动 flag-u <parent-url>fabric-ca/lib/caconfig.go:161
Intermediate CA 链文件ca-chain.pem(默认)fabric-ca/lib/caconfig.go:122ca.go:435
bizhub 运行时是否 enroll是(动态注册/enroll 机构用户)cbdc-biz/app/bizhub/internal/biz/ca.go:247-295, 297+
其他业务应用是否运行时 enroll否,读静态 MSP + KMS 签名cbdc-biz/app/<app>/cmd/<app>/main.go 无 fabric-ca/lib import
setup 阶段 enroll 入口cbdc-biz/scripts/gen_crypto.sh 通过 cbdc-tool 容器跑 fabric-ca-client enrollcbdc-biz/scripts/gen_crypto.sh:22-75
TLS root 拉取make fetch-fabric-ca-rootcurl ${CA_URL}/cainfo → 解 base64 CAChaincbdc-network/Makefile:208-233

11. [未核]

  • cbdc-biz/scripts/gen_crypto.sh 中 issuer / auditor / bizhub-admin enroll 用的 fabric-ca-client-config.yaml.tpl 模板内容(决定这些钱包私钥是落盘还是走 PKCS#11)—— 模板由 cbdc-tool 镜像内置,不在本仓库。
  • cbdc-network config-builder setup 生成的 orderer / committer crypto material 内部走 cryptogen 还是 fabric-ca-client 的具体分支(config-builder 实体在 fabric-x-tool 镜像内,本仓库不含其源码)。
  • cbdc-biz/conf/ca/fabric-ca-server-config.yamlintermediate.parentserver.url 字段但留空(未启用内置 intermediate 模式);启用该模式所需的 parent URL / 凭证由部署方填入,仓库未给出可用样例。
  • Idemix issuer key 在多机部署下是否每个 CA 实例独立生成 vs 共享(fabric-ca 默认每实例独立,cbdc-chain 部署侧编排不在本仓库)。