NukeDraw可验证公平抽签

使用说明

使用流程

NukeDraw 通过承诺—揭示机制汇集多方随机输入,并在浏览器中核验材料、计算抽签结果。贡献者负责提交随机输入;候选条目是实际抽取或分组的对象,可以是人名、选项或任务。两者可以使用同一份名单,也可以相互独立。

  1. 准备:贡献者加入房间,填写本轮唯一的 ID。房主选择候选来源、抽签模式及参数,点击“冻结名单并开始”;系统会先保存当前名单与设置,再冻结本轮贡献者名单、候选名单及规则。
  2. 承诺:贡献者提交秘密的 SHA-256 摘要。承诺一经接受便不能替换;所有贡献者均提交后,轮次进入揭示阶段。
  3. 揭示:浏览器先保存完整承诺名单,再提交与本人承诺匹配的秘密。可在“贡献进度”中筛选尚未承诺或尚未揭示的 ID。
  4. 验证:所有有效揭示收齐后,服务器生成随机数。浏览器取得完整验证材料后,核对承诺、复算随机数,并按冻结规则计算抽签结果。已完成的历史轮次也可获取材料并验证。

加入与成员管理

房主可通过“邀请二维码”展示或保存房间邀请链接的二维码。二维码在浏览器本地生成,不包含管理凭据;持有二维码的人可以访问并转发房间。

房主可在建房时设置贡献者人数上限,并在准备阶段调整。点击“应用”立即生效,点击开始也会保存尚未应用的上限;上限不能低于已加入人数,开始后冻结,新轮继承。此设置不限制自定义候选条目数量。

新房间默认通过分享链接加入。房主点击“生成房间码”后,也可使用 6 位十六进制短码加入,不区分大小写。同一房间开启新轮次时,房间码保持不变。持有链接或短码的人可以访问房间,也可以将其转发给其他人。

房主只能在准备阶段移除贡献者,也可移除自己的参与席位并保留管理权限。移除不等于封禁,持有链接或短码的人仍可重新加入。开始后如需调整名单,应手动结束本轮,再开启新轮。

加入成功后,本浏览器在该房间的 ID 固定,刷新、重新进入及下一轮均沿用原 ID。首次进入准备中的房间会弹窗填写 ID,也可选择“仅查看”,不会加入贡献名单。房主移除成员后,准备阶段只能使用原 ID 重新加入。浏览器本地固定 ID 仅防止误操作,不是身份认证;更换浏览器或清理本地记录不提供身份归属证明。

秘密的生成与提交

自动模式使用浏览器的 crypto.getRandomValues 生成 32 字节秘密,保存在本地,揭示前不会上传;进入揭示阶段后自动填入。请保留浏览器数据,并通过“备份秘密”下载副本。秘密丢失后无法根据承诺恢复,也就无法完成揭示。

手动模式适用于了解算法、需要自行生成输入的用户。承诺和揭示均填写 64 个十六进制字符,分别表示 32 字节摘要和 32 字节秘密。承诺必须等于 SHA256(秘密的原始字节)

等待与手动结束

未收齐承诺或有效揭示时,轮次持续等待,不设自动超时。房主与成员自行协商后,可填写原因并结束本轮;系统记录结束人和原因,不设网页投票。手动结束的轮次不生成随机数,也不会跳过或替代任何贡献者的秘密。服务器清理房间或重启仍会中止该轮次。

候选名单与抽签规则

候选条目默认使用贡献者 ID。选择“自定义条目”后,可粘贴多行文本或导入 UTF-8 TXT,每行一项。候选对象无需上线,贡献者也无需出现在候选名单中。每项具有相同的抽取机会,是否贡献随机数不改变其机会。

每项最多 64 个 UTF-8 字节,最多 65,536 项;空行会被忽略,首尾空白会被去除,重复项会被拒绝。每轮贡献者同样最多 65,536 人,两项上限分别计算。填写完成后可直接开始,也可提前保存,供成员查看。新轮次继承上一轮的候选名单和抽签规则,并可在准备阶段修改。

模式规则
仅随机数生成并验证随机数 R,不进行抽取或分组。
抽取一项从候选名单中抽取 1 项。
抽取多项不重复抽取 k 项,保留抽出顺序;1 ≤ k ≤ n。
均衡分组将 n 项分为 g 组,每项仅进入一组;1 ≤ g ≤ n。各组数量最多相差 1,前 n mod g 组各多 1 项。

其中 n 为候选条目总数。抽签及分组结果在本地验证后优先展示,每页最多 25 项,支持条目搜索;分组结果还可按组号筛选。结果可下载为 JSON。若需保留完整的承诺与揭示记录,请同时下载验证材料。

名单摘要与抽签算法

自定义名单按 UTF-8 无符号字节字典序排序,以换行符 LF 连接各项,末尾不添加换行,再计算 SHA-256 摘要。浏览器在揭示前保存冻结的名单摘要和规则,取得最终材料后核对完整名单。

抽签算法版本为 draw-v1。浏览器在独立工作线程中完成材料验证,再按以下规则扩展随机数 R:

块 b = SHA256(ASCII("nukedraw/draw-v1") ‖ R 的 32 字节 ‖ U32BE(b))

计数器 b 从 0 开始,U32BE 表示大端无符号 32 位整数编码。每块依次读取 8 个大端无符号 32 位整数。对区间 [0, m) 采样时,舍弃 x ≥ 2³² − (2³² mod m) 的值,其余返回 x mod m,以避免直接取模造成的偏差;m = 1 时直接返回 0,不消耗随机数。

候选条目按 UTF-8 字节序排序后,使用正向 Fisher–Yates 算法:在第 i 步交换位置 i 与 i + 采样(n − i)。抽取模式执行前 k 步;分组模式完成洗牌后,按各组容量连续划分。例如,10 项分为 3 组时,各组数量依次为 4、3、3。

在候选名单、R 和算法版本相同的情况下,抽取一项的结果等于多项抽取的第一项;抽取 k 项的结果等于抽取 k + 1 项的前 k 项。抽签规则不参与 R 的计算。缺少抽签配置的旧材料按“仅随机数”处理,未知版本会被拒绝。

承诺公示

承诺公示按 ID 展示各贡献者提交的 SHA-256 摘要,支持查询、分页和导出。浏览器将首次收到的承诺保存在本地 IndexedDB 中;同一轮次、同一 ID 出现不同承诺时,会保留原记录并报告冲突。

提交本人揭示前,必须获取并保存完整的冻结名单及全部承诺。贡献者数与候选条目数均未超过自动推送阈值时,浏览器接收承诺更新,并在揭示阶段自动补齐缺失记录;任一数量超过阈值时,需点击“获取全部承诺”。本地保存失败或检测到承诺冲突时,浏览器会阻止揭示。

最终材料和历史材料均会与本浏览器此前保存的记录核对。轮次完成后才取得的材料,不能作为揭示前已见到这些承诺的依据。清除网站数据、更换浏览器或设备,会失去原有的本地核对记录;服务器清理房间不会删除浏览器中的记录。

随机数算法与验证

随机数算法版本为 sha256-simple-v2。首先按贡献者 ID 的 UTF-8 无符号字节字典序排序,逐项检查:

SHA256(揭示的原始字节) = 承诺

随后按同一顺序拼接全部揭示,计算最终随机数:

R = SHA256(揭示₁ ‖ 揭示₂ ‖ … ‖ 揭示ₙ)

表示字节拼接,每份揭示固定为 32 字节。输入不包含前缀、版本、ID、承诺或分隔符,总长度为 32 × 贡献者人数 字节。仅有一名贡献者时,R 等于其承诺,因此结果在承诺阶段就已公开。

十六进制仅用于显示字节,计算前必须先解码;直接对十六进制文本求哈希会得到不同结果。输入偏移从 0 开始:第一份揭示占第 0–31 字节,第二份占第 32–63 字节,依此类推。

本地核验

验证流程展示每人的承诺、揭示及本地计算的 SHA256(揭示),不匹配时标出错误;再对合并输入计算 SHA-256,并与服务器提供的 R 比较。搜索和分页仅影响展示,验证始终覆盖全部贡献者。

贡献者不超过 25 人时,可展开完整合并输入。下载的 .bin 文件包含原始输入字节,可直接使用 SHA-256 工具复算。完整验证材料还包含成员、承诺、揭示、随机数及抽签配置;使用自定义名单时包含候选条目及其摘要。

自动推送与按需获取

自动推送阈值 T 由服务器管理员设置。名单冻结后,贡献者数与候选条目数均不超过 T 时,服务器自动推送揭示值和结果,浏览器结合此前保存的完整承诺名单进行验证。任一数量超过 T 时,服务器仅通知轮次完成,由用户主动获取结果或完整材料。

本地承诺记录不完整时,可点击“获取材料并验证”。主动获取或下载的完整材料包含全部承诺。若缺少此前固定的完整承诺名单或冻结配置,验证结果会标注“仅材料自洽”:它说明本次材料内部的计算一致,不能据此确认此前的承诺、名单或规则未被替换。仅获取服务器随机数不代表已通过本地验证,也不会产生已验证的抽签结果。

数据保存

房间、轮次和历史记录仅保存在服务器内存中,服务停止或重启后全部清空。房间数据与验证材料缓存的预算默认是 64 MiB,可由管理员调整;该预算不等同于服务器进程的总内存上限。

预算不足时,服务器先释放材料缓存;仍不足时,按创建顺序删除最旧的房间及其全部历史,包括尚未结束的房间。在线页面会收到清理通知,已删除的数据无法恢复。短码可能重新分配,但旧分享链接不会指向新房间。

需要留存结果时,请及时下载完整验证材料。浏览器本地保存的秘密、管理凭据和核对记录,不会随服务器重启而删除,但也不能恢复已被清空的房间。

适用条件与限制

“可验证”是指用户能够复算结果,并将材料与本浏览器此前保存的承诺和冻结配置进行核对。系统不验证 ID 对应的真实身份,也不提供服务器操作历史的独立证明。参与者仍需在房间外确认身份及规则;不同浏览器收到的记录是否一致,也不能仅凭单个浏览器的验证结果确定。

随机性依赖贡献者提供新的、难以预测的秘密,以及 SHA-256 的密码学性质。至少应有一位诚实贡献者使用独立生成的新秘密,并在揭示前妥善保密。只有一名贡献者时,不具备多方共同生成随机数的保障。

最后揭示者可能在知道结果后拒绝揭示,使本轮无法完成。反复结束、重开并选择性接受结果,也可能引入偏差。承诺—揭示机制不能强迫任何一方完成揭示。

抽签使用有限的 256 位随机种子,不保证覆盖大规模名单的全部排列;其随机扩展依赖 SHA-256 的伪随机性假设。

HTTP 不加密传输,也不能防止网络中的第三方篡改页面代码或验证材料。局域网 HTTP 可用于功能测试,正式部署应使用 HTTPS。

本地历史与事前核对

名单、承诺记录和已获取的结果材料保存在当前浏览器的 IndexedDB 中。历史页直接读取这些记录,无需请求房间接口。只有完整名单与承诺在本浏览器看到揭示公示前已保存,且与最终材料一致,才显示“已核对公示前名单与承诺”。事后取得的材料只能证明计算一致,不能补作事前见证。

服务器在全部贡献者提交揭示后统一公示。小房间自动获取冻结名单与承诺;超过管理员设置的主动推送阈值时,需手动获取。提交揭示前必须完成上述保存。此标记描述本浏览器观察到的顺序,不是第三方时间戳或对服务器真实时间的证明。

名单单独缓存,结果材料的承诺和揭示以二进制保存;查看和搜索按页显示。删除房间记录会同时删除本地验证依据、秘密及房主管理凭据,管理员建房密钥保留。浏览器可能因存储配额、隐私模式或清理操作移除记录;重要材料可自行导出。

通过 HTTPS 首次打开并完成离线页面缓存后,可以断网重新打开本地历史。普通 HTTP 局域网不支持离线页面安装。历史页只包含此版本运行后保存的房间;“清空全部”同时清理旧版本遗留的承诺记录。