在我的数据库中,我有一个计算列,其中包含一个名为URLString的列的SHA1哈希,该列包含URL(例如“http://xxxx.com/index.html”)。
我经常需要查询表以根据URLString列查找特定的URL。 该表包含100K,这些查询需要几秒钟(使用SQL Azure)。 由于URL可能很长,我无法在此列上创建索引(大于450字节)。
为了加快速度,我想从C#计算SQL Server哈希字节('SHA1',[URLString])的等效值,并根据此值进行查询。
我尝试了下面的代码,但是我获得的值与数据库计算的值不同。
var urlString = Encoding.ASCII.GetBytes(url.URLString); //UTF8 also fails
var sha1 = new SHA1CryptoServiceProvider();
byte[] hash = sha1.ComputeHash(urlString);
我在这里错过了一些小事吗? 我对其他可以解决相同问题的想法持开放态度(只要SQL Azure支持它们)。
示例:在数据库中,URL http://www.whatismyip.org/的自动计算SHA1值为0xAE66CA69A157186A511ED462153D7CA65F0C1BF7。
答案 0 :(得分:9)
你可能会被字符编码差异所困扰:
您可以尝试通过Encoding.ASCII.GetBytes(url)
或Encoding.Unicode.GetBytes(url)
获取字节,并查看您的数据库正在使用哪个字节。
答案 1 :(得分:4)
下面是两种对字符串和字节进行散列的方法。 HashBytes方法返回结果字节的Base64,但如果您愿意,则只返回字节
public static string HashString(string cleartext)
{
byte[] clearBytes = Encoding.UTF8.GetBytes(cleartext);
return HashBytes(clearBytes);
}
public static string HashBytes(byte[] clearBytes)
{
SHA1 hasher = SHA1.Create();
byte[] hashBytes = hasher.ComputeHash(clearBytes);
string hash = System.Convert.ToBase64String(hashBytes);
hasher.Clear();
return hash;
}
答案 2 :(得分:1)
下面的代码等效于SQL Server的hashbytes('sha1')
using (SHA1Managed sha1 = new SHA1Managed()) {
var hash = sha1.ComputeHash(Encoding.Unicode.GetBytes(input));
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash) {
// can be "x2" if you want lowercase
sb.Append(b.ToString("X2"));
}
string output = sb.ToString();
}