Fowler–Noll–Vo hash function
具体请参见 https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function。
2018 网鼎杯 hashcoll
其实这道题是从 NSU Crypto 抄过来的,https://nsucrypto.nsu.ru/archive/2017/problems_solution,具体的 wp 之前 hellman 也写了,https://gist.github.com/hellman/9bf8376cd04e7a8dd2ec7be1947261e9。
简单看一下题目
h0 = 45740974929179720441799381904411404011270459520712533273451053262137196814399
# 2**168 + 355
g = 374144419156711147060143317175368453031918731002211L
def shitty_hash(msg):
h = h0
msg = map(ord, msg)
for i in msg:
h = (h + i) * g
# This line is just to screw you up :))
h = h & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
return h - 0xe6168647f636题目希望我们给出两个消息,其哈希值相同。如果我们将该函数展开的话,那么
$hash(m)=h_0g^n+x_1g^n+x_2g_{n-1}+...+x_ng \bmod 2^{256}$
假设两个消息的 hash 值相同那么
$h_0g^n+x_1g^n+x_2g_{n-1}+...+x_ng \equiv h_0g^n+y_1g^n+y_2g_{n-1}+...+y_ng\bmod 2^{256}$
进而
$(x_1-y_1)g^{n-1}+(x_2-y_2)g^{n-2}+...+(x_n-y_n)g^0 \equiv 0 \bmod 2^{256}$
即我们只需要找到一个 n 维向量 $z_i=x_i-y_i$,满足上述等式即可,我们可以进一步将其化为
$z_1g^{n-1}+z_2g^{n-2}+...+z_ng^0-k*2^{256}=0$
即找到一组向量满足上述这个式子。这可以认为是 LLL Paper 中第二个例子的简单情况(参见格问题部分)。
那么我们可以快速构造矩阵,如下
之后我们使用LLL 算法即可获得两个一样的哈希值
注意不能直接仅仅使用 pow(g, N - i, mod),不然生成的数会在 mod 对应的域中,这真是个大坑。
如下
即成功。
Last updated