如何查找与给定字符串hashcode()值相同且等长的字符串
构造和指定字符串等长、同Java hashCode值的字符串方法
你需要找的是和den长度相同(3个字符)、hashCode为99341的字符串,核心是利用Java String.hashCode()的计算规则构造碰撞:
首先修正原规则的笔误,hashCode()的正确计算规则为:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
其中n是字符串长度,s[i]是字符串第i位的ASCII码值
对于3位字符串,公式可以简化为:hash = c1 * 31² + c2 * 31 + c3 = c1*961 + c2*31 + c3,其中c1、c2、c3对应三个字符的ASCII码。
具体构造方法
核心思路是利用系数的整数倍关系,调整两个字符的取值,让整体hash值的变动完全抵消:
- 调整前两位:因为
961 = 31 * 31,所以只要满足「第一位ASCII码加k,第二位ASCII码减31*k」,整体hash值就不会变化,只要调整后两位的ASCII码落在合法可打印范围(通常取32~126)即可。 - 调整后两位:因为
31 = 31 *1,所以只要满足「第二位ASCII码加k,第三位ASCII码减31*k」,整体hash值也不会变化。
实操示例
我们按第一种调整方式构造,取k=1:
- 原字符串
den的三个字符ASCII码分别为:c1=100(对应'd')、c2=101(对应'e')、c3=110(对应'n') - 调整后c1 = 100 + 1 = 101(对应字符'e')
- 调整后c2 = 101 - 31*1 = 70(对应字符'F')
- c3保持110(对应'n')不变
得到新字符串eFn,可以通过代码验证hash值完全一致:
String s1 = "den"; String s2 = "eFn"; System.out.println(s1.hashCode()); // 输出 99341 System.out.println(s2.hashCode()); // 输出 99341
如果需要找更多符合要求的字符串,只要调整k的取值,保证调整后的字符ASCII码在合法范围内即可,比如取k=2时可以得到字符串f'n,hash值同样为99341。
内容的提问来源于stack exchange,提问作者Wyrmbeard
相关产品推荐
相关产品推荐

