19

我正在考虑编写一款半流行纸牌游戏的电脑改编版。我想让它在没有中央服务器的情况下运行,并且我正在尝试提出一个方案,使作弊变得不可能而不必信任客户端。

我看到的基本问题是每个玩家都有几堆牌(抽牌,当前手牌和弃牌)。除非游戏规则允许(即抓牌或弃牌),否则任何玩家都不可能改变这些牌堆的组成,玩家也不应该知道他们或对手的牌堆中有什么。

我觉得应该有某种方法可以使用诸如公钥密码学之类的东西来实现这一点,但我一直在我的方案中发现漏洞。任何人都可以建议一个协议或向我指出有关此主题的一些资源吗?

[编辑] 好的,所以我一直在考虑这个问题,这是我想出的一个想法。如果你能在其中戳任何洞,请告诉我。

在洗牌的时候,玩家有一堆牌,他们知道牌的价值。他们获取这些值,将随机盐连接到每个值,然后对它们进行哈希处理。他们记录盐分,并将哈希值传递给他们的对手。

对手连接自己的盐,再次散列,然后将散列洗牌并将牌组传回给原来的玩家。

我相信在这一点上,套牌是随机的,任何玩家都不知道这些值。但是,当抽到一张牌时,对手可以显示他们的盐,让第一个玩家确定原始值是多少,而当出牌时,玩家会显示自己的盐,让对手验证卡值。

4

6 回答 6

8

你的问题是密码学中著名的心理扑克问题(这是我在大学密码课中最喜欢的部分之一)。这可能的,并且已经解决了(在某种程度上,就像所有加密货币一样,由Ron Rivest解决),只要您不介意巨大的性能损失。

查看 wiki 页面以获取更多详细信息。

于 2011-07-02T00:27:28.633 回答
5

传统的心理扑克计划是矫枉过正的。由于没有共享套牌,您的情况实际上要容易得多。你可以这样做:

玩家 A 拿走他的牌并用密钥 Ka 加密它们。他将它们发送给 B,B 将它们打乱,用密钥 Kb 加密它们。每次 A 想打一张牌,他都要求 B 解密下一张牌的 (Kb)。A 对此进行解密以找出他抽到的牌。最后,A 和 B 显示 Ka 和 Kb 并将它们与游戏日志进行比较,这应该可以防止作弊。

更新:经过反思,这是一个更简单的解决方案:如上所述,玩家 A 加密他的牌并将它们发送给 B。B 将它们洗牌。每当 A 想要一张牌时,他都会告诉 B 他从哪一副牌中抽牌。B 从适当的堆中返回(加密的)卡。

于 2011-07-02T14:16:53.963 回答
5

我想描述一个很快出现在我脑海中的想法。我不知道它是否满足您的所有需求,所以请随时对此发表评论。

假设玩家A有牌A1, A2, , ... 来自由数字, , ...A3表示的集合。这些卡片也可能被分成几堆,但这不会改变以下内容。01N-1

[A1, A2, A3, ...]您可以使用其中两张[A1_a, A2_a, A3_a, ...][A1_b, A2_b, A3_b, ...]一张与 player 一起使用A,另一张与 player一起使用,而不是使用单个列表处理这些卡B。它们以这样一种方式生成,即每个都是随机的(在范围内0...N-1),但两者都是相关的,因此A1_a + A1_b = A1, A2_a + A2_b = A2, ... (所有运算都取模N)。

  • 因此,没有玩家实际上知道没有互补牌堆的牌(即他不能合理地改变他的牌)
  • 每当您需要知道一张牌时,两个玩家都会显示其相应的值,然后您将这些模数相加N
  • 你可以很容易地实现像“抽牌”这样的事情,两个桩都必须以同样的方式对待
于 2011-07-01T20:17:52.540 回答
2

也许玩家可以在游戏开始时交换他们的堆的哈希值。

然后当游戏结束时,玩家交换他们的牌堆在游戏开始时的实际组成。现在玩家的客户端可以检查它是否与他们之前获得的哈希值匹配,然后检查所做的所有动作是否适用于这些套牌。

唯一的问题是套牌最初是如何洗牌的。你需要确保玩家不能只是按照他选择的任何顺序开始他的套牌。

也许让玩家通过从某个特定来源获得随机性来生成他们的初始套牌顺序。但在某种程度上,其他玩家无法计算出其他玩家的套牌顺序,直到游戏结束,但仍然可以检查玩家没有摆弄他们的甲板。不知道你怎么能做到这一点。

编辑:

另一个想法。也许不是在游戏开始时生成随机牌组,而是可以随着游戏的进行而生成。

每次玩家需要从牌堆中取出一张新牌时,他们的对手都会向他们发送一些随机种子,用于选择下一张牌是什么。

这样用户就无法知道卡片在他们的牌组中的顺序。

我不确定你会如何阻止其他玩家说出他们将为对手挑选的牌。如果种子用于从某种随机排序的卡片列表中选择一张卡片,对手有哈希值来验证..他们可以检查所有可能的卡片组合并找出哪一个与哈希匹配,从而能够通过向他们发送将导致选择该卡的种子来指示他们希望其他玩家绘制哪张卡。

于 2011-07-01T20:12:21.843 回答
2

虽然中央服务器可能是最简单的方法,但如果您想避免它,您可以使用分布式系统,其中每个玩游戏的人都是其他玩家套牌的存储主机(不是为他自己或他的对手,而是为其他任何人) . 我相信 Limewire 和 Bittorrent 都是这样工作的,所以你可以通过研究这些来源获得一些想法。

于 2011-07-01T20:19:26.403 回答
0

这是 Acorns 方法的改编:

设置:

每个玩家都有他们的牌组(完全有序的牌组)......这些牌组是公开的并且是自然顺序的

每个玩家都需要一个不对称(签名)密钥对,交换公钥

现在到随机性问题:

由于玩家可能无法提前看到他们会抽什么牌,因此对手将成为我们随机性的来源:

当我们需要一些随机值时,我们会询问我们的对手......随机值与稍后检查的移动一起存储

由于我们的对手可能无法操纵我们牌的顺序,我们将接收到的随机值并用我们的私钥对其进行签名......该签名的值将是我们的 RNG 种子(对手无法预测),然后对手可能会根据他/她生成的随机数验证签名(因此我们也将签名存储起来,并在比赛结束后进行交换)

因为我们可以在每一轮都进行这种随机数交换,所以玩家事先不知道随机值 -> 不要偷看我们的堆栈顺序

并且由于我们现在有一个种子 RNG,我们可以从那个“共享”随机值中获得随机值……这样我们就可以从我们的牌组中抽取“随机”(完全确定的,具有可重复验证结果的)牌……牌组/pile 不需要洗牌,因为我们可以从我们的 RNG 中获得随机位置

因为我们都交换了随机值、签名、初始牌组(按总顺序)和所有动作,我们可以在之后重玩整个游戏并检查是否有违规行为

于 2011-07-01T23:45:02.743 回答