跳到正文
Clash Watchdog实验室计数
菜单

自己动手验证哈希:一步一步检查可自行验证的一局

主题
公平性和验证
发布日期
更新日期
篇幅
约 5 分钟读完
本页内容

检查一局可自行验证的崩盘游戏,只要几分钟,不需要任何特别的软件,只要一个新一点的浏览器,愿意复制粘贴两串十六进制字符就行。这篇一步一步讲「服务器种子、客户端种子和 nonce」这种设计的一般做法,教你确认锁定有没有被守住。

验证一局,我需要准备什么?

三样东西:

  1. 一个新一点的网页浏览器:Chrome、Firefox、Edge 或 Safari。你会用到浏览器内置的开发者控制台。
  2. 你的可自行验证种子:服务器种子(更换之后才揭晓)、你的客户端种子,以及你想验证的那一局的 nonce。这些都可以在平台的公平性设置里找到。
  3. 几分钟时间,第一次的话。

不需要特别的软件,不用下载,也不用命令行工具。你需要的一切,浏览器里都有。

如果你想在开始前,先弄懂你在验证什么、为什么重要,先读《可自行验证是什么》。这篇假设你已经懂这个概念,想要的是动手做的步骤。

服务器种子、客户端种子和 nonce,在哪里找?

位置每款游戏、每个网站都不一样,所以要看游戏自己的公平性页面,或者叫可自行验证的页面。在每个玩家各自一套的设计里,你通常会找到:

  • 服务器种子哈希:对现在正在用的种子的 SHA-256 锁定。
  • 你的客户端种子:常常可以自己改。
  • nonce:一个计数器,每下一注就加一。
  • 停用种子的方法,常常叫作更换种子,它会揭晓旧的服务器种子,再开始一个新的。

建在哈希链上、大家共用局的游戏,做法不一样:开局前公布链的末端,每一局结束后再揭晓那一局的哈希。

停用种子之前:记下你现在的客户端种子,以及你想检查的那一局的 nonce。换了之后,旧的数值可能就不再显示了。

怎样算出揭晓的种子的 SHA-256?

更换之后,你会看到真正的服务器种子,一长串十六进制字符。第一步,是确认这个种子算出来的 SHA-256 哈希,和更换之前显示的哈希一样。

方法 1:浏览器控制台

打开浏览器的开发者控制台(按 F12,再点「Console」),粘贴:

async function sha256(message) {
  const encoder = new TextEncoder();
  const data = encoder.encode(message);
  const hash = await crypto.subtle.digest('SHA-256', data);
  return Array.from(new Uint8Array(hash))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

// 换成你真正揭晓的服务器种子
sha256('your_revealed_server_seed_here').then(console.log);

输出是一串 64 个字符的十六进制字符串。把它和更换之前显示的服务器种子哈希,一个字符一个字符地对比。

方法 2:我们的哈希检查工具

打开哈希检查工具,粘贴揭晓的服务器种子,以及更换之前显示的哈希,选 SHA-256。它用你浏览器的 Web Crypto 运行,不会传任何东西给我们。它确认的是锁定;它不会重新算出这一局。

如果对得上:平台在任何一局开始之前,就锁定了这个种子。继续下一步。

如果对不上:平台在锁定哈希之后,换了种子。这是严重的失败。把一切都记录下来,然后报告。

怎样重新算出这一局的哈希?

现在你知道服务器种子是真的。下一步,重新算出某一注背后的带密钥哈希(HMAC-SHA256)。把这段粘贴到浏览器控制台:

async function hmacSha256(key, message) {
  const encoder = new TextEncoder();
  const cryptoKey = await crypto.subtle.importKey(
    'raw', encoder.encode(key), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
  );
  const sig = await crypto.subtle.sign('HMAC', cryptoKey, encoder.encode(message));
  return Array.from(new Uint8Array(sig))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

// 换成你真正的数值
// 信息的格式(这里是 "client:nonce")由游戏的说明决定,对比之前先确认
hmacSha256('your_revealed_server_seed', 'your_client_seed:42').then(console.log);

把哈希变成倍数。这最后一步,每款游戏都有自己公开的公式,而且公式各不相同:读哈希的哪一部分、庄家优势怎么加进去、结果怎么取整。用游戏公平性页面上的公式。我们不在这里放一条公式,因为从一款游戏抄来的公式,用在另一款游戏上会算出错的答案,看起来就像检查没通过。

重要的提醒:

  • 信息的格式、公式和取整方式,全部都来自游戏的说明。
  • nonce 通常数的是下注,不是局。如果你跳过了一些局,那些局你的 nonce 不会变。
  • 取整可能让最后一位小数差 0.01。差 0.01 是取整造成的;像 2.47 对 3.12 这样的差距,才是对不上。

如果我的验证对不上,该怎么做?

先排除自己弄错的可能:

  1. 检查你的客户端种子。你用的,是你要验证的那一局当时正在用的客户端种子吗?如果你改过,就要用旧的那个。
  2. 检查 nonce。nonce 是按每一注算的。如果平台数 nonce 的方式和你想的不一样,对不上可能只是 nonce 差了几个。
  3. 检查公式。不同的游戏,用不同的计算公式。确认你用的是游戏自己说明的那一条。
  4. 检查服务器种子。你用的揭晓的服务器种子,是对的那一次更换的吗?如果你换过好几次,要确认这个种子,对应的是那一局当时正在用的那一次。

如果你已经排除了自己弄错的可能,验证还是对不上:

  1. 把一切都截图。揭晓的服务器种子、锁定的哈希、你的客户端种子、nonce、显示的爆点,以及你算出来的爆点。
  2. 再试几局。从同一次更换里,再验证 3 到 5 局。如果全部都对不上,问题是系统性的。如果只有一局对不上,可能是数据显示出错。
  3. 报告给平台。大部分平台都有处理可自行验证争议的客服渠道。
  4. 保留证据。在正确进行的检查里,一个有记录、可以重复的对不上,是很严重的事,而且这是任何人都能重新跑一遍的证据。

一个正确实现的系统,不应该有任何一次验证对不上。这些密码学运算是确定的:同样的输入,永远得到同样的输出。如果输出对不上,要么是输入错了(自己弄错),要么是系统没有照它说的运作(平台的问题)。

怎样一次验证很多局?

抽查的话,几局就够了。要验证很多局,就把同一个函数,套在一段 nonce 上循环,再把每个结果和游戏的历史记录对比:

async function hashesForRange(serverSeed, clientSeed, startNonce, endNonce) {
  const rows = [];
  for (let nonce = startNonce; nonce <= endNonce; nonce++) {
    rows.push({ nonce, hash: await hmacSha256(serverSeed, clientSeed + ':' + nonce) });
  }
  return rows;
}

hashesForRange('your_revealed_server_seed', 'your_client_seed', 1, 100).then(console.table);

对每个哈希套用游戏公开的公式,再和那个 nonce 显示的结果对比。

检查通过了,还有什么是它说明不了的?

检查通过,证明的是这一局在下注之前就定好了,之后也没有被改过。它证明不了游戏整体的返还率,和官方公布的一样;那需要数大量的局,附上误差范围公布。一款游戏过了最低样本量,实验室就一款一款做这件事。见《返还率是什么》。

它也不能告诉你任何关于下一局的事。一个种子要等它产生的局都结束了,才会揭晓,所以验证永远是往回看的。历史记录说明的是过去的表现,它预测不了下一局。说能从哈希读出下一局结果的软件,看不到那个保密的种子;见预测软件和机器人的检查。

哪些游戏可以这样检查?

只有可自行验证的游戏,比如 Aviator、Mines 和 Stake Crash,才让你从种子重新算出一局。每款游戏用的是它自己公开的公式,而我们的工具暂时还不能重新算出 Aviator 的倍数。先公布哈希的游戏,比如 JetX,让你检查锁定,但没有公布从哈希到结果的公式。第三方认证随机的游戏,比如 Spaceman,完全没办法一局一局检查。每款游戏的页面都有一个公平性标签,写明适用哪一种。

检查的价值,不管是五局还是五十局,都一样:它把「相信平台」从一种信念,变成一个任何人都能检验的说法。

这一页对你有用吗?

匿名:不用账号,也不设 cookie。

问答

验证哈希,需要安装什么吗?
不需要。只用你的网页浏览器,就能验证可自行验证的哈希。打开浏览器的控制台(按 F12,Mac 上按 Cmd+Option+J),用浏览器内置的 Web Crypto API 算出 SHA-256 和 HMAC-SHA256。你也可以用我们在 /zh/tools/verify 的哈希检查工具,它在你的浏览器里运行,不会传任何东西给我们。不用下载,不用安装,也不用任何插件。
如果验证对不上,怎么办?
如果揭晓的服务器种子算出来的 SHA-256,和事先锁定的哈希对不上,或者你算出来的爆点和显示的结果对不上,你手上就有锁定被破坏的证据。把一切都记录下来:截图种子、哈希、nonce 和显示的爆点。把这个差异报告给平台,并且保留你的记录。一个正确实现的可自行验证系统,不应该有任何一次验证对不上;如果有,不是程序出错,就是有人动了手脚。
我能验证我加入之前的局吗?
只有当那些局用的服务器种子,后来已经揭晓了,才可以。在大部分可自行验证的做法里,服务器种子在更换的时候揭晓。用现在这个(还没揭晓的)服务器种子玩的局,暂时还不能验证:验证需要真正的种子,光有哈希不够。在你开始玩之前的局,用的是别人的客户端种子和 nonce,所以除非平台提供公开的验证工具,否则你没办法重新算出来。
验证要花多少时间?
知道那些数值在哪里之后,验证一局只要几分钟。第一次会久一点,因为你要在游戏的公平性页面上找到种子,也要熟悉控制台的指令。验证同一次更换里的很多局会更快:服务器种子和客户端种子都一样,只要改 nonce。

全部文章

  • 可自行验证是什么:先不用数学讲一遍,再用数学讲一遍

    可自行验证(provably fair)是一种密码学方法,让玩家可以在事后检查,平台没有改过一局的结果。它用 SHA-256 哈希,在开局前锁定一个随机种子,开局后再把种子揭晓:揭晓的种子和事先锁定的哈希对得上,这一局就没有被动过。这篇先用直白的方式讲这个概念,再给想看的人讲数学,最后说清楚可自行验证能证明什么、不能证明什么。

  • Stake Crash 详解:一款可自行验证的崩盘游戏怎么运作,检查又能证明什么

    Stake Crash 是 Stake 在自己网站上运营的崩盘游戏,它说自己是可自行验证的。我们没有记录到它返还率的第一手来源,所以不显示任何数字。这篇讲一局怎么进行、两种常见的可自行验证设计、一般怎样检查一局,以及检查能证明什么、不能证明什么。

  • 崩盘游戏随机数:SHA-256 哈希怎样变成倍数

    崩盘游戏的随机性,来自一个伪随机数生成器(PRNG)。现代的伪随机数生成器,只要种子设得好,产生的数列在任何实际用途上,用统计都分不出和真正的随机有什么不同。这篇讲伪随机数生成器在崩盘游戏里怎么运作、「种子设得好」是什么意思,以及如果没人盯着,一个作弊的平台怎样照样能让检查通过。