代码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
是什么意思?
答案 0 :(得分:2)
“代码2”的含义是什么?0x7f?
& 0x7f
表示& 128
,即“仅保留第一个(最不重要)7位”,这会强制输出保持纯ASCII(ASCII仅使用7位) - 只需投掷远离任何不适合的信息。
是否有任何
map()
函数可以使用result1
评估result2
?
但是,最大的问题是在开始时使用不同的编码:除非input
仅包含ASCII文本(即只使用前7位的字符),否则您将完全不同的字节数组进行哈希处理(bs
),因此最终输出不会以任何方式相同。由于散列不是简单可逆的,你将无法弥补这一点。
答案 1 :(得分:2)
你的第二个代码在四个方面都很糟糕:
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,则会立即让不同的东西进行哈希处理,这是不可调和的。