按关键词阅读:
看了其他答案才明白问的是啥,其实这个没有穷举的必要啦……这个hash纯用异或,构造的实在是太差了,最差的地方就在于它是线性的。下面我来演示怎么迅速用手写的方法找到一个碰撞。我们首先稍微改变一下这个Hash函数,我们可以看到它将字符串长度作为第一个元素参与Hash,我们改写一下这个形式,把字符串的长度编码成一个字符,比如说这个字符串长度是11,就编码为\u0026#39;\\x0b000000000A1\u0026#39;。经过编码之后的字符串计算Hash值是完全线性的,这源于布尔代数中异或操作其实相当于加法,具有许多加法的性质。如果我们有两个字符串,首先我们将两个字符串左边补0(注意是补\\x00,而不是补\u0026#39;0\u0026#39;字符,显然补0不影响Hash值计算)补到一样长,然后把对应的字符的ASCII码进行异或,很容易证明,原来的两个字符串的Hash值的异或,就等于异或后的字符串的Hash值,这就是异或的线性性质。证明我就不写了,不相信的话可以计算一下\u0026#39;\\x0f\\x0f\\x0f\\x0f\u0026#39;和\u0026#39;\\xf0\\xf0\\xf0\\xf0\u0026#39;的Hash值(不包含长度的),然后看是不是\u0026#39;\\xff\\xff\\xff\\xff\u0026#39;的Hash值。接下来我们要考虑这个字符串的特性,它由数字、大小写字母组成,我们来复习一下这些字母的ASCII码的特性,数字从0x30 - 0x39, 大写字母从0x41到0x5a,小写字母从0x61到0x7a。不难发现,与0x20异或,恰好可以将一个大写字母与小写字母互换。接下来我们利用线性性,构造一个Hash值为0的字符串,然后与原始字符串进行异或,来制造一个碰撞。由于Hash每次移位5位,而字符串每次移位8位,中间相差了3位,我们可以构造一个包含两个bit的字符串,让这相差的3位撞在一起然后消除掉,比如说\u0026#39;\\x01\\x20\u0026#39;,它的Hash值恰好是0。那么在这个字符串右边补上若干个\\x00,Hash值仍然是0。我们就利用这个最简单的0值Hash字符串来制造碰撞。我们前面已经看到了,一个大写字母与0x20异或会变成小写字母,而数字0与0x1异或会变成数字1,所以我们把0x20与A对齐,这样0x1会对齐到A前面的数字0,于是我们就得到一个异或的结果:000000001a1这个字符串就满足条件。这当然不是唯一的答案,比如说\u0026#39;\\x02\\x40\u0026#39;也是合法的碰撞字符串,而0x40与数字0异或的结果是0x70,\u0026#39;p\u0026#39;,与数字1异或的结果是0x71, \u0026#39;q\u0026#39;,所以000000000Cq00000002pA12p0000000A1也是符合条件的答案当然把这些碰撞字符串组合起来用也是可以的,这样我们可以生成出一大堆一大堆的碰撞。
■网友
答案其实特别特别多,因为11位字符串至少有127^11之多(只考虑ascii为正的字符),而long在java中不过也才2^64范围,所以肯定有大量重复。首先把代码敲进来,输出一下运算过程中hash的结果,发现依次是 【求解 乌云白帽子大会 直播的第三道题是咋解的呢】
ok,前两个字符的hash结果是10800,所以只需要找一个字符串,长度也是11,后面是0000000A1,前面hash的结果是10800就可以了,所以暴力枚举一下
然后发现四组解
1后面估计是个没图案的字符,或者是空格,懒得搞出来,所以2p0000000A1显然就是一组答案了,或者3P0000000A1。验证后无误,不知道所问是否是这个。
■网友
熊猫tv乌云白帽子大会的网页下面的题目? - 白帽黑客 (White Hat)
来源:(未知)
【】网址:http://www.shadafang.com/c/gx04219A50H020.html
标题:求解 乌云白帽子大会 直播的第三道题是咋解的呢