扑克是一种牌桌上的游戏,但如果在没有物理扑克的互联网上,没有一个可信第三方维护公平,且参与玩家皆是不诚实的,这个时候怎么来一场公平的扑克游戏?
这个问题由Rivest, Shamir and Adleman于1979年提出,并将这个问题称为“Mental Poker”,下面是摘自原文的一段关于Mental Poker的描述:
自此大量的解决方案涌现出来,但都不经打,主要因为这些方案计算和通信成本太大,这对于一个实时游戏来说是无法接受的。时至今日,受益于分布式账本,零知识证明等技术的发展,Mental Poker有机会再次登上舞台,并成为现实。具体可见Geometry的github开源代码。
问题回顾
Mental Poker主要面临以下三个挑战:
- 对所有玩家隐藏扑克牌的值
- 向特定玩家或一组玩家展示一张牌
- 确定发牌正确性,具有公平的随机性
其它一些更高阶的属性如在游戏结束后还能对某些信息继续保密–使得玩家在游戏中虚张声势而不被揭穿,以及玩家能够自由的加入或退出游戏。
为了实现这些属性,我们必须考虑1)每张卡牌需要存储哪些消息?2)多少信息需要交互?3)玩家需要进行什么样的计算?
Geometry Mental Poker
Geometry主要参考了Barnett和Smart在2003年发表的《Mental Poker Revisited》一文中的协议。该协议安全性假设基于Decisional Diffie-Hellman;其次,该协议设计清晰且合乎逻辑的抽象,方便“即插即用”;最后,该协议的计算和通信成本依赖于由零知识证明算法,但这是一个自2003年以来性能显著提高的领域。
Barnett-Smart协议主要依赖两种抽象的密码学概念。第一种抽象是对卡牌的操作使用可验证的门限掩码函数(verifiable -out-of- threshold masking functions),这听起来可能有点复杂,但下一部分会进行解释。第二种抽象是使用零知识证明进行洗牌,这个相对容易理解。
原始论文中的掩码函数使用了El Gamal加密方案的门限变种算法,这个算法可以在椭圆曲线上实现,不仅可以提高安全性,还能简洁表示卡牌信息,每张卡牌椭圆曲线上的两个点表示。另一方面,Barnett-Smart协议中的洗牌算法时至今日已经过时,但今天有更高效的零知识证明算法可以代替,这也是Geometry的主要改进点。
Verifiable -out-of- Threshold Masking Functions(VTMFS)
VTMFs是在Barnett-Smart协议中引入的,主要将具体的实现细节抽象出来。首先我们将名字拆开来看:
- 掩码(masking):这个函数允许我们“掩盖”或隐藏数据的一部分。在这个意义上,加密其实就是一种掩码。
- 可验证(verifiable):观察者或验证者能够检查掩码函数是否被正确使用,即使该函数运行需要一些秘密信息。
- 门限(threshold):有一些函数需要达到给定的玩家数量才能运行。在这种情况下,门限可设置为玩家的数量,即要求所有玩家参与。
综合这三个性质,VTMFs算法允许我们隐藏卡牌的值(掩码),同时确保没有玩家作弊(可验证),也没有玩家合谋(阈值)。VTMFS函数主要包括密钥生成(key generation)、掩码(mask)、重新掩码(remask)和去掩码(unmask),接下来将逐个介绍这些函数。
key generation
每个玩家都需要运行这个算法去生成公私钥对。对于玩家A,其公私钥对表示为( p k A , s k A pk_A,sk_A pkA,skA)。每个玩家需要将公钥公开,且同时伴随公开一个零知识证明(证明拥有对应的私钥),如可以使用schnorr身份证明,这个证明主要用来抵抗denial-of-service attacks and rogue key attacks。
一旦所有玩家公开了他们的公钥,我们可以生成一个聚合公钥 p k a g g pk_{agg} pkagg,只要有一个玩家保密且不泄漏私钥,那么我们就算不出来这个聚合公钥对应的私钥。下面的图示解释了密钥聚合过程:
Mask
掩码即加密操作。利用明文卡牌、聚合公钥和 随机因子生成掩码卡牌(masked card),这其实是用聚合公钥去加密明文卡牌得到掩码卡牌,要恢复明文卡牌,必须去解密掩码卡牌,但这个过程需要所有玩家配合行动,因为每个玩家都掌握了聚合公钥对应私钥的一份子。
一个不错思维模型是将掩码卡牌想象成一个带有一组挂锁的不透明盒子。每个挂锁可以被其中一个玩家的私钥打开。下面的图示解释了这个模型:
单纯的掩码操作并不能保证游戏的公平性。因为执行掩码操作的玩家知道卡牌值到盒子标签的映射关系。在上面的例子中,梅花A映射到标签“A”。为了打破这种映射关系,需要引入了重掩码(remask)操作。
Remask
重掩码即对掩码卡牌再次加密,生成一个新的掩码卡牌。这个操作不需要解密密文,因此可以由任何玩家执行。按照此前的模型,重掩码操作就像是替换盒子上的标签。
Unmask
去掩码是一种门限解密,每个玩家都必须贡献他们的私钥去解密。例如玩家A、B和C依次执行去掩码操作,最终的密文让玩家D单独解密,那么玩家D解密卡牌后是唯一知道卡牌值的人。
ZK洗牌
在下面模型中,洗牌是通过改变掩码卡牌的顺序并重新进行掩码来实现的。因为每张掩码卡牌都是唯一可识别的(与现实中卡牌大大不同),仅仅改变掩码卡牌的顺序不会隐藏任何信息,因此执行重新掩码操作才会达到真正的洗牌效果。
Barnett-Smart协议使用零知识证明来证明这个操作被正确执行。然而,这个代价是昂贵的,因此它要求证明者进行大量的洗牌操作,因此需要大量的重新掩码操作。相反Geometry使用argument of knowledge来代替。
argument of knowledge计算成本较低,但安全性略微较弱,虽然恶意证明者永远无法伪造有效的证明,但足够强大的对手还是可以伪造。因此只有假设对手在计算上是有上限的情况下,argument of knowledge才具有意义。
今天,存在着各种argument of knowledge,可以用来证明正确的洗牌操作:通用SNARKs(例如Marlin、PlonK)、电路特定SNARKs(Groth16)和内积证明(Bulletproofs、Bayer-Groth)等等,这些算法都是不错选择,具体我们可以根据这些算法的不同性质来选择,如setup,证明大小,prover和verifier的运行时间等
Mental Poker的设置与一般的SNARK非常不同。首先,参与一局游戏的玩家数量有限且固定,在这种情况下,可信设置( trusted setup)类算法是一种选择。其次,扑克类游戏输入大小相对较小,经典的扑克牌由52张牌组成,其他卡牌类游戏也很少使用超过几百张牌,因此 O n O\sqrt{n} On和 o ( l o g ( n ) ) o(log(n)) o(log(n))的算法差距不对。对于证明大小也是同样的道理。
德州扑克案例
下面的表格呈现了德州扑克的一个示例回合,在左侧显示了现实生活中玩家动作,右侧显示了互联网中的对应动作。
Setup
Texas Hold’Em | Mental Texas Hold’Em | |
---|---|---|
1. | Gather a group of players around a table | Players each run the key generation algorithm, publish their public key and prove in zk that they own the corresponding secret key. A master public key is computed. |
2. | Bring a deck of 52 standard cards. | Publicly encode each card value to a card (plaintext). Mask all 52 cards with a public randomness value and publish all proofs. |
Round n
Texas Hold’Em | Mental Texas Hold’Em | |
---|---|---|
3. | Dealer shuffles the deck | All players take turns running a shuffle and provide a zero-knowledge proof |
4. | Give out the cards: top card goes to the first player, second card goes to second, etc… | Take part in the unmask process to allow players to see their cards: all players but the first partially unmask the first card, all players but the second partially unmask the second card, etc… |
5. | Betting using physical chips | Betting using physical chips |
6. | Discard and reveal cards using the game rules | Following the order of the deck, ignore discarded cards. To open a card, all players collaborate to perform a full unmask of the chosen card |
7. | Repeat 5 and 6 as mandated by the rules | Repeat 5 and 6 as mandated by the rules |
8. | Final betting. Open hands and declare a winner | Final betting. Each player can complete the unmask process for their private cards. Compare hand values and declare a winner. |
在对现有协议中改进的最后一个方面是可以利用分布式账本和智能合约技术。Barnett-Smart协议要求“所有玩家之间有一个广播通道”。智能合约可以被视为这种广播通道的扩展,其中通道本身可以执行一些计算。
在这种情况下,可以将所有的证明验证委托给智能合约,而不是每个玩家都对每个证明运行一个验证器,我们只需要对每个证明进行一次验证。智能合约的代码是公开的,只要玩家愿意,都可以对其进行审计,当然极其不信任的玩家仍然可以选择自己验证。