关于抽奖机制的优化小建议

AIA的论坛抽奖机制为论坛注入了活力,也为社团运营搭建了一个很好的平台,感谢论坛的运营者付出的努力!

这是一个有关AIA论坛抽奖方式的一个可能建议~

此抽奖规则可能易受哈希爆破攻击。

上述规则中提到“开奖前后一分钟”,那么有关“开奖时间”的种子一共只有两种情况(两个不同的分钟数)。 攻击者A可以采用这样的策略,A用户在前5层楼抢一个位置,发送任意字符串,然后让攻击者B在开奖前卡点发一个指定字符串。任意一个字符串都有大约1/25的概率,使得无论开奖时间如何都能让攻击者A中奖。而因为抽奖的脚本是完全公开的,攻击者B平均而言只需要在实验几十次就能试出来一个这样的字符串。

这里有一个思路,可以避免这种攻击的可能性。

阶段一:发起抽奖时

发起人在本地生成一段随机字符串S;用哈希算法(如SHA-256),算出哈希值H;在发布抽奖主贴时,公布H。

阶段二:抽奖过程中

抽奖过程中,用户(U1, U2, …)可以选择生成某个秘密字符串(S1, S2, …)在自己的回帖内容中发送其哈希值(H1, H2, …),并按一定格式标明。

但不强制这么做。

阶段二:截止开奖

抽奖结束后,截止随机数种子的收集,发起人在开奖贴中,公布S;上述用户(U1, U2, …)可以选择以指定的方式公布字符串S1, S2, …(如果没有公布,视为弃权,跳过该字符串;如果哈希验证不通过,也跳过该字符串)

使用所有收集到的S和Sn 按顺序拼接作为随机数种子。

这个方案似乎漏洞要小一些,但是会增加一些开奖时论坛管理员的工作量,仅作为可能性的讨论和技术交流,并不是提议实装~

再次感谢论坛的运营者,这是一个非常好的社区,赞美AIA学社!

4 个赞

我发现我写了两个阶段二QAQ
后面那个应该是阶段三

打一个小补丁,抽奖的发起人应该在Sn收集截止后再公布S

楼主的方案有两个问题:
首先是需要有的人在开奖后二次参与,显得比较麻烦,理想的情况应该每个人抽完奖就等开奖就行;
其次是其实防不了串通,也就是说最后几层楼是开奖者小号/朋友的情况
我有一计:
开奖者预先抽奖前公布一个秘密S的hash:H(S)
开奖结束时,设总楼层为N,则计算关键楼层:k=H(N)%N
开奖种子为k楼上下2层发言第一行拼接S

我赞同有的人在开奖后二次参与这一点确实显得比较麻烦;

但是该协议是可以防串通的,只要提供种子的Un中有任意一个用户不是开奖者的小号,开奖者就无法通过合理计算复杂度的碰撞进行攻击。

您的方案在此前提下是有效的:假定开奖者无法串通至少5个人同时控制时间在关键楼层发送指定消息。这个前提在正常的抽奖时一般是满足的,我认为具有较强的可行性。

谢谢您的回复!

1 个赞

群友说话一股客服味:laughing:

1 个赞

我感觉可以把方案再简化成“主办方承诺 + 外部随机源 + 可复算映射”三件事:

  1. 抽奖开始前,主办方本地生成随机串 S_host,只公布 H = SHA-256(S_host)
  2. 截止后公布 S_host,并固定使用一个开奖后才知道的外部随机源(比如某个区块 hash / drand beacon)

  3. seed = SHA-256(S_host || topic_id || total_posts || last_post_id || external_randomness)
    再算 winner = seed mod N

这样做的好处是:

  • 不需要参与者二次 reveal,用户发完帖就结束
  • 主办方不能事后改种子,因为前面已经 commit 了 H(S_host)
  • 最后几层控楼/卡点发字符串的攻击面会小很多,因为真正决定结果的还有一个开奖后才出现的外部随机量
  • 全部过程都能公开复算,比较适合论坛这种场景

如果还想进一步防“主办方拖到自己喜欢的外部随机值再开奖”,可以在发帖时就把规则写死,比如:
“使用截止后第一个整点对应的 drand round / 第一个满足条件的区块高度”

这样我感觉会比纯论坛内种子更稳,也比完整 commit-reveal 对用户更友好。

2 个赞