如何评估这两个哈希函数?

时间:2013-04-10 05:45:36

标签: c# hash

代码1 :(将SHA1结果转换为字符串的简单方法)

byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
SHA1CryptoServicesProvider x = new SHA1CryptoServicesProvider();
bs = x.ComputeHash(bs);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in bs)
   s.Append(b.ToString("x2").ToLower());
result1 = s.ToString();

Code2 :(来自世界之初的项目中存在的遗留代码)

byte[] bs = System.Text.ASCIIEncoding.GetBytes(input);
SHA1CryptoServicesProvider x = new SHA1CryptoServicesProvider();
bs = x.ComputeHash(bs);
char[] c = new char[bs.length]
for(int i=0; i<bs.length; i++)
  c[i] = (char)(bs[i] & 0x7f);
resutl2 = new StringBuilder().Append(c).ToString();

是否有任何map()函数可以使用result1评估result2

result1 == map(result2)

“代码2”的含义是0x7f是什么意思?

3 个答案:

答案 0 :(得分:2)

  

“代码2”的含义是什么?0x7f?

& 0x7f表示& 128,即“仅保留第一个(最不重要)7位”,这会强制输出保持纯ASCII(ASCII仅使用7位) - 只需投掷远离任何不适合的信息。

  

是否有任何map()函数可以使用result1评估result2

但是,最大的问题是在开始时使用不同的编码:除非input仅包含ASCII文本(即只使用前7位的字符),否则您将完全不同的字节数组进行哈希处理(bs),因此最终输出不会以任何方式相同。由于散列不是简单可逆的,你将无法弥补这一点。

答案 1 :(得分:2)

你的第二个代码在四个方面都很糟糕:

  • 假设输入字符串完全由ASCII字符组成。 (您的第一个代码应对所有Unicode)
  • 它通过使用b & 0x7f丢失结果中每个字节的最高位 - 这只是与二进制值01111111的按位“AND”,因此结果在0-127而不是0-的范围内255
  • 在许多情况下,它最终会出现不可打印的文本,最终可能会在某些转换中被破坏
  • (远没那么重要)它无缘无故地使用了StringBuilder;最后一行可能只是

    result2 = new string(c);
    

给定result1值,可以判断原始文本是否会映射到给定的result2值(假设原始文本首先是ASCII) ,但你无法反过来工作,因为数据已经丢失。 (有几个result2值可以产生相同的result1值。)甚至假设你可以获得确切的result2值 - 由于它最终使用控制的方式你可能会发现更多的数据正在丢失。

答案 2 :(得分:0)

在代码1中,我们看到:

s.Append(b.ToString("x2").ToLower());

http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx我们看到字节的toString(“x2”)意味着每个字节将呈现为两个十六进制数字,然后是小写的 - 所以0a,f9等。

但在代码2中我们看到:

c[i] = (char)(bs[i] & 0x7f);

做(bs [i]&amp; 0x7f);意味着我们在将第八位(将其设置为0)之前将其放入返回值中。这意味着我们在原始哈希中有丢失的信息 - 大约八分之一的信息被消灭了。这意味着我们无法确定result1将在result2上使用任何函数 - 但你可以采用另一种方式,在result1上执行一个函数,通过将结果转换为字节数组来提供结果2。

如果代码2的意图是将哈希呈现为可打印的字符串,那么base64编码是一个更好的主意(google it)(当然,可打印的十六进制编码也很好)

此外,代码1和代码2在开始时使用不同的编码。如果传递给代码1/2的字符串中包含unicode,而不仅仅是纯ASCII,则会立即让不同的东西进行哈希处理,这是不可调和的。