今日新玩具:sha256.closeai.moe
256核心的处理器就是厉害,今天终于算出来了。(虽然有点小贵)
我找到了一个只包含64位阿拉伯数字的字符串X,它经过SHA-256散列后的结果用十六进制表示也是一个只包含64位阿拉伯数字的字符串。
完整的SHA-256目前还是比较安全的,意思就是说,散列后的256bit输出是非常均匀的。对于随机输入,输出的每个bit是0还是1,概率都是接近50%。
256bit输出转换为十六进制表示后是64个字符,有0-9和a-f共计16种可能。那么1个字符是数字的概率就是10/16,而64个字符都是数字的概率就是 (10/16)^64
我需要做的就是不断地随机生成64个数字的字符串,然后计算其SHA256的散列值,并判断16进制转换后是不是只有数字。单次尝试也叫做伯努利试验(注意不是白努力)。但如果进行巨量次的小概率尝试,结果就会服从泊松分布。
如果想要达到统计学上的保底线(63.2%),需要进行2.27万亿次尝试。不过我运气不错,在概率达到61.79249663%的时候就碰上了一组。也就是说,差不多计算了2.18万亿个随机产生的数字后就碰上了。
在输入端我采用的FastRng实际上是一个线性同余生成器(LCG),循环周期是2^64 。
self.0 = self.0.wrapping_mul(6364136223846793005).wrapping_add(1);
想让一个LCG算法达到全周期,需要满足Hull-Dobell定理。这里用到的常数 6364136223846793005 感兴趣的朋友可以去了解下。
想要找到满足我这个规则的X固然困难,但这个计算量即便是在个人电脑上也可以在有生之年跑出来。而在256核心的 AMD EPYC™ MILAN 处理器的帮助下,这个时间被压缩到了小时级别。
其实我跑了两组出来。下午准备去力量训练的时候第一组跑出来了,于是我把输入的prefix改成了自己的生日,又跑了一遍。结果这次运气是极极极好,5分钟就跑出来了。我简直有点怀疑是不是脚本错了,但验证了下结果,是对的。(或许相当于中了一次彩票)(带生日prefix的这组我就私藏了)
这个快速碰出结果的体验让我一下子就忘记了概率的神圣。我把脚本改成了随机的64个a-f输入,想找到64个a-f的输出。
脚本跑起来后我算了一下概率,发现不对啊不对啊。这应该是算不出来了。为什么呢。因为(10/16)^64 是 (6/16)^64 的300万亿倍以上。也就是说,即便是运气爆棚,我也得买2650亿张5090来帮我算,才有可能在一天内找到。
然后我就 Ctrl+C 了。不过接下来可能还会找一些可能有趣,但计算量是有生之年的数据。
说到这次找到的这组数据,我肯定是需要做一些“可信时间戳”证明的,证明我是在今天而不是明天才找到的。我用了两个办法,一个是Github的commit记录,一个是在opentimestamps.org 上生成了.ots文件。
补一张图2。本以为找到的这个X除了好看以外“没啥用”,不过现在看来还是“有点用”的。起码骗到了kimi,让kimi以为自己写的一个简单的计算SHA256脚本都写错了,于是kimi自己重新又算了一遍,思考了一会儿才承认这是个小概率事件。

