在 Corda 中,两个节点如何相互证明它们都知道一条信息?
In Corda, how can two nodes prove to each other that they both know a piece of information?
我想编写一个 Corda 流程,其中双方只有在双方都能证明他们共享一条共同信息的情况下才能进行交易。流程概要如下:
@InitiatingFlow
@StartableByRPC
class ChallengeResponseFlow(val otherParty: Party, val proofOfKnowledge: Int) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val otherPartySession = initiateFlow(otherParty)
otherPartySession.send(proofOfKnowledge)
val theirProofOfKnowledge = otherPartySession.receive<Int>().unwrap { theirProofOfKnowledge -> theirProofOfKnowledge }
verifySecretValue(theirProofOfKnowledge)
TODO("Challenge-response passed. Continue with flow.")
}
private fun verifyTheirProofOfKnowledge(theirProofOfKnowledge: Int) {
TODO("Write verification logic.")
}
}
两个问题:
- 这里有什么知识证明可以证明我知道与我的交易对手相同的秘密?
- 我如何根据对方发送给我的知识证明来检查对方是否知道相同的秘密?
重要的是,在此挑战-响应协议期间,绝不会泄露秘密。
我可以用 SHA256 散列我的秘密,将前 128 位发送到另一方,让另一方检查他的秘密 SHA256 散列是否与他的前 128 位匹配。然后他可以将他的后半部分发送给第一方以验证它是否与他的匹配。
根据您的要求,有多种策略:
- 假设秘密有足够的熵(即至少 128 位),双方可以随机选择一个
nonce
并发送 SHA3-256(secret, nonce)
或 SHA2-256d
(双哈希)甚至更好HMAC
连同他们nonce
给对方。
注意 A: 如您所见,我省略了简单的 SHA256,因为它容易受到 length extension attacks.
的影响
NoteB: 发送一半的哈希值,正如@Kid101 已经提到的那样,仍然有效,但它降低了安全级别,因此 nonce 方法被认为更安全和优雅.
NoteC: nonce 方法提供了额外的(可能是需要的)不可链接性 属性,据此恶意攻击者无法判断是否相同 secret
在两个不同的transactions/flows中重复使用。需要的是始终生成一个新的随机数。
- 然而,在某些情况下,秘密没有足够的熵或根本不是随机的(即计数器或可预测的
String
,例如弱密码或用户 ID)。然后,一个人(中间人)可以简单地暴力破解简单的哈希或 MAC 方法(即使应用了随机数)来轻松提取 "weak" 秘密。此问题的解决方案更为复杂,需要某种加密(即通过安全通道或使用 password authenticated key agreement protocol 发送散列消息)。
NoteD: Corda 节点无论如何都是通过 TLS 连接的,但是如果你需要保护静态数据(即检查点),应该使用额外的加密层。
如果要提供针对重放攻击的安全性,则需要一种质询-响应协议。通过重放攻击,我们的意思是故意重复使用相同的随机数(即,以前的身份验证令牌以某种方式被破坏并在未来的身份验证尝试中重复使用)。第一种情况(具有足够熵的秘密)的一个技巧是从对方接收一个具有挑战性的随机数并将这个随机数用于身份验证令牌 SHA3-256(secret, nonce)
。因此,每个客户端都使用另一方收到的随机数。
扩展上述挑战-响应解决方案,有时建议同时使用两个随机数,例如,
甲方发SHA3-256(secret, noncefromPartyA, noncefromPartyB)
和
乙方发SHA3-256(secret, noncefromPartyB, noncefromPartyA)
这是为了提供额外的保证,即聚合随机数由双方控制,如果只有一方是恶意的或其 PRNG 有缺陷,您仍然可以产生唯一的随机数。
NoteE:我们应该保证noncefromPartyA != noncefromPartyB
,因为第二个回复的人可以重用(转发)与第一方相同的身份验证令牌(也是一种重放攻击)。
NoteF:沿着同样的思路,我们强调上述哈希值中随机数的顺序应该不同,以再次防止内部重放攻击,即使我们使用不同的随机数每个用户!
我想编写一个 Corda 流程,其中双方只有在双方都能证明他们共享一条共同信息的情况下才能进行交易。流程概要如下:
@InitiatingFlow
@StartableByRPC
class ChallengeResponseFlow(val otherParty: Party, val proofOfKnowledge: Int) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
val otherPartySession = initiateFlow(otherParty)
otherPartySession.send(proofOfKnowledge)
val theirProofOfKnowledge = otherPartySession.receive<Int>().unwrap { theirProofOfKnowledge -> theirProofOfKnowledge }
verifySecretValue(theirProofOfKnowledge)
TODO("Challenge-response passed. Continue with flow.")
}
private fun verifyTheirProofOfKnowledge(theirProofOfKnowledge: Int) {
TODO("Write verification logic.")
}
}
两个问题:
- 这里有什么知识证明可以证明我知道与我的交易对手相同的秘密?
- 我如何根据对方发送给我的知识证明来检查对方是否知道相同的秘密?
重要的是,在此挑战-响应协议期间,绝不会泄露秘密。
我可以用 SHA256 散列我的秘密,将前 128 位发送到另一方,让另一方检查他的秘密 SHA256 散列是否与他的前 128 位匹配。然后他可以将他的后半部分发送给第一方以验证它是否与他的匹配。
根据您的要求,有多种策略:
- 假设秘密有足够的熵(即至少 128 位),双方可以随机选择一个
nonce
并发送SHA3-256(secret, nonce)
或SHA2-256d
(双哈希)甚至更好HMAC
连同他们nonce
给对方。
注意 A: 如您所见,我省略了简单的 SHA256,因为它容易受到 length extension attacks.
的影响NoteB: 发送一半的哈希值,正如@Kid101 已经提到的那样,仍然有效,但它降低了安全级别,因此 nonce 方法被认为更安全和优雅.
NoteC: nonce 方法提供了额外的(可能是需要的)不可链接性 属性,据此恶意攻击者无法判断是否相同 secret
在两个不同的transactions/flows中重复使用。需要的是始终生成一个新的随机数。
- 然而,在某些情况下,秘密没有足够的熵或根本不是随机的(即计数器或可预测的
String
,例如弱密码或用户 ID)。然后,一个人(中间人)可以简单地暴力破解简单的哈希或 MAC 方法(即使应用了随机数)来轻松提取 "weak" 秘密。此问题的解决方案更为复杂,需要某种加密(即通过安全通道或使用 password authenticated key agreement protocol 发送散列消息)。
NoteD: Corda 节点无论如何都是通过 TLS 连接的,但是如果你需要保护静态数据(即检查点),应该使用额外的加密层。
如果要提供针对重放攻击的安全性,则需要一种质询-响应协议。通过重放攻击,我们的意思是故意重复使用相同的随机数(即,以前的身份验证令牌以某种方式被破坏并在未来的身份验证尝试中重复使用)。第一种情况(具有足够熵的秘密)的一个技巧是从对方接收一个具有挑战性的随机数并将这个随机数用于身份验证令牌
SHA3-256(secret, nonce)
。因此,每个客户端都使用另一方收到的随机数。扩展上述挑战-响应解决方案,有时建议同时使用两个随机数,例如,
甲方发SHA3-256(secret, noncefromPartyA, noncefromPartyB)
和
乙方发SHA3-256(secret, noncefromPartyB, noncefromPartyA)
这是为了提供额外的保证,即聚合随机数由双方控制,如果只有一方是恶意的或其 PRNG 有缺陷,您仍然可以产生唯一的随机数。
NoteE:我们应该保证noncefromPartyA != noncefromPartyB
,因为第二个回复的人可以重用(转发)与第一方相同的身份验证令牌(也是一种重放攻击)。
NoteF:沿着同样的思路,我们强调上述哈希值中随机数的顺序应该不同,以再次防止内部重放攻击,即使我们使用不同的随机数每个用户!