Corda中多方保密身份共享方案问询:四方交互场景
嘿,这个问题我在项目里碰到过好几次——Corda的IdentitySyncFlow确实有点“死板”,只能同步自己的身份,不能帮别人发。不过针对你说的四方互享保密身份的场景,有几个实用的方案,我给你拆解一下:
这是最推荐的方式,利用Corda交易签署的内置机制来自动完成身份交换,不需要额外的手动操作。
核心逻辑是:构建一个包含四方保密身份的空交易,让所有节点参与签署。在签署过程中,每个节点都会自动请求并存储自己缺失的保密身份——毕竟要验证交易的合法性,必须确认对方身份的有效性。
你可以写一个专门的Flow来实现这个逻辑,比如:
@InitiatingFlow @StartableByRPC class SyncAllConfidentialIdsFlow(private val otherParties: List<Party>) : FlowLogic<Unit>() { override fun call() { // 生成自己的保密身份 val myConfidentialId = serviceHub.keyManagementService.freshKeyAndCert( serviceHub.myInfo.legalIdentities.first(), false ).party // 和每个对方节点交换保密身份 val allConfidentialIds = mutableListOf(myConfidentialId) otherParties.forEach { party -> val session = initiateFlow(party) session.send(myConfidentialId) val theirId = session.receive<AbstractParty>().unwrap { it } allConfidentialIds.add(theirId) } // 构建一个仅包含参与方的空交易 val notary = serviceHub.networkMapCache.notaryIdentities.first() val txBuilder = TransactionBuilder(notary) .addCommand(Command(EmptyCommand(), allConfidentialIds.map { it.owningKey })) .addOutputState(EmptyState(participants = allConfidentialIds), EmptyContract.ID) // 本地验证并签名 txBuilder.verify(serviceHub) val signedTx = serviceHub.signInitialTransaction(txBuilder) // 收集所有对方的签名 val sessions = otherParties.map { initiateFlow(it) } val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx, sessions)) // 最终广播(可选,哪怕不广播,签署过程已经完成身份同步) subFlow(FinalityFlow(fullySignedTx, sessions)) } } @InitiatedBy(SyncAllConfidentialIdsFlow::class) class SyncAllConfidentialIdsResponder(private val session: FlowSession) : FlowLogic<Unit>() { override fun call() { // 接收对方的保密身份,同时发送自己的 val theirId = session.receive<AbstractParty>().unwrap { it } val myConfidentialId = serviceHub.keyManagementService.freshKeyAndCert( serviceHub.myInfo.legalIdentities.first(), false ).party session.send(myConfidentialId) // 处理交易签名(只做验证,不做额外逻辑) val signFlow = object : SignTransactionFlow(session) { override fun checkTransaction(stx: SignedTransaction) = Unit } val txId = subFlow(signFlow) subFlow(ReceiveFinalityFlow(session, expectedTxId = txId)) } } // 配套的空状态和空合约,用来凑交易结构 @BelongsToContract(EmptyContract::class) data class EmptyState(override val participants: List<AbstractParty>) : ContractState class EmptyContract : Contract { override fun verify(tx: LedgerTransaction) = Unit companion object { const val ID = "com.yourpackage.EmptyContract" } } class EmptyCommand : CommandData
只要任意一个节点发起这个Flow,把另外三方的合法身份传进去,跑完之后四方就都拥有彼此的保密身份了。
如果不想搞交易,也可以用最直接的方式:让每个节点主动给另外三个节点发自己的保密身份。
因为IdentitySyncFlow.Send只能发送自身的身份,那我们就写一个批量Flow,让节点一次性给所有目标节点发起同步:
@StartableByRPC class BatchIdentitySyncFlow(private val targetParties: List<Party>) : FlowLogic<Unit>() { override fun call() { targetParties.forEach { party -> // 向目标节点同步自己的所有身份(包括保密身份) subFlow(IdentitySyncFlow.Send(initiateFlow(party), IdentitySyncFlow.Send.allIdentities())) } } }
然后你需要在每个节点上都调用这个Flow,传入另外三个节点的合法身份。等四方都跑完这个Flow,彼此就都拿到对方的保密身份了。这个方案简单直接,但需要每个节点单独执行。
如果你的Corda网络用了Network Map Service,还可以配置节点把保密身份注册到网络地图上,这样其他节点可以通过IdentitySyncFlow.Receive从网络地图拉取所有节点的保密身份。
不过这个方案有个大问题:保密身份会被公开到整个网络的地图服务上,完全失去了“保密”的意义。所以只适合对身份保密性要求极低的场景,一般不推荐。
- 不管用哪个方案,前提是四方已经互相注册了合法身份(Legal Identity)——因为保密身份是基于合法身份生成的,节点必须先信任对方的合法身份,才会接受对应的保密身份。
- 保密身份是持久化存储的,一旦同步完成,后续交易可以直接使用,不需要重复操作。
内容的提问来源于stack exchange,提问作者Joel

