【发布时间】:2015-08-15 17:21:09
【问题描述】:
我想做一些测试,这些测试需要一些具有相同哈希码的字符串,但不是相同的字符串。我找不到任何示例,所以我决定编写一个简单的程序来为我做这件事。
下面的代码一遍又一遍地生成两个随机字符串,直到它们生成相同的哈希码。
static Random r = new Random();
static void Main(string[] args)
{
string str1, str2;
do
{
str1 = GenerateString();
str2 = GenerateString();
} while (str1.GetHashCode() != str2.GetHashCode() && str1 != str2);
Console.WriteLine("{0}\n{1}", str1, str2);
}
static string GenerateString()
{
string s = "";
while (s.Length < 6)
{
s += (char)r.Next(char.MaxValue);
}
return s;
}
这段代码似乎可以正常工作(理论上),但可能需要几个世纪才能完成。所以我想反之亦然,从一个哈希码生成两个字符串。
我知道不可能从哈希码中检索字符串,但是否可以从中生成可能的字符串?
我正在使用 Visual Studio 2015 社区版。版本:14.0.23107.0D14REL。
.NET 框架:4.6.00081。
【问题讨论】:
-
如果您只想进行测试,您可以创建一个类并使用返回固定值的错误实现覆盖
GetHashCode,从而有效地在任何地方产生冲突。 -
只需要几秒钟,生日悖论让它变得很快。 "1241308".GetHashCode() == "699391".GetHashCode() 在 32 位代码中,"942".GetHashCode() == "9331582".GetHashCode() 在 64 位代码中。
-
利用生日悖论的方法是存储您迄今为止生成的所有字符串。每次您生成一个新的时,您都会将其与所有其他的进行检查。它极大地增加了找到匹配项的机会。如果有 N 个哈希码,那么您的方法在检查 N/2 个字符串后将有 50% 的机会发现冲突。在检查√N个字符串后,生日方法将有50%的机会。对于 N=~40 亿的 32 位哈希码,这是检查 20 亿个字符串或 65000 个字符串之间的差异。
-
@ScottChamberlain:这不是真的。该数学仅适用于哈希值近似均匀随机的情况。如果不是,您很容易需要更多的哈希值来发现冲突(例如
hash(x) = x%INT_MAX,在发现冲突之前您需要遍历INT_MAX值)。 -
如果你使用 64 位,你可以只使用
"\0Anything"和"\0Really, anything will work."-Why is String.GetHashCode() implemented differently in 32-bit and 64-bit versions of the CLR?。当然,最好为您当前的实现寻找这些字符串 -\0并不总是有效。