.Net SHA1CryptoServiceProvider与SQL Hashbytes不匹配

时间:2012-06-27 19:13:17

标签: .net sql vb.net cryptography sha1

使用Hashbytes转换存储在SQL中的一些明文密码后,似乎无法让.Net生成正确的匹配哈希。

用于转换密码的SQL:

UPDATE Users
SET UserPassword = HASHBYTES('SHA1', UserPassword + CAST(Salt AS VARCHAR(36)))

现在用于生成哈希的.Net代码:

Dim oSHA1 As New System.Security.Cryptography.SHA1CryptoServiceProvider
Dim bValue() As Byte
Dim bHash() As Byte

bValue = System.Text.Encoding.UTF8.GetBytes(sPlainTextPass)
bHash = oSHA1.ComputeHash(bValue)
oSHA1.Clear()

Dim sEncryptPass As String = String.Empty
For i As Integer = 0 To bHash.Length - 1
    sEncryptPass = sEncryptPass + bHash(i).ToString("x2").ToLower()
Next

补充说明:盐存储在数据库中。 sPlainTextPass包含纯文本密码+ salt。我尝试了几种不同的编码,包括ASCII,UTF7和UTF8。数据库字段是一个varchar,应该根据我的理解与UTF8匹配。

帮助?

4 个答案:

答案 0 :(得分:2)

您不能散列字符串,只能散列字节。因此,SQL Server和您必须使用编码将字符串转换为字节。

SQL Server不支持UTF8。您需要找出它的用途并在您的应用程序中匹配该编码。对于nvarchar,我会尝试Encoding.Unicode并使用稀有和特殊字符对其进行测试。

网上似乎有一些关于这个主题的信息,我发现谷歌搜索“哈希字节编码”:http://weblogs.sqlteam.com/mladenp/archive/2009/04/28/Comparing-SQL-Server-HASHBYTES-function-and-.Net-hashing.aspx虽然我必须说博客帖子包含明显的错误而且不可信任。

答案 1 :(得分:0)

我之前看到过这种事情发生在Sybase SQLAnywhere上。根据您正在使用的SQL数据库,它可能会自己填充哈希值,在这种情况下,您永远不会得到匹配的哈希值(不知道数据库的内部工作方式,即)

编辑:

如果您想要比较密码,根据任何内部盐析,您可以将.NET散列密码发送到数据库,在那里再次哈希,并检查与存储值的相等性。这当然假设您以类似的方式存储了密码。

答案 2 :(得分:0)

在T-SQL中使用nvarchar类型而不是varchar,结果也将匹配

答案 3 :(得分:0)

我经历过同样的事情...... 我认为它与update语句有关,以便在users表中填充哈希值。

我发现问题是数据类型。如果在表达式中

UserPassword + CAST(Salt AS VARCHAR(36))

UserPassword列是nvarchar,结果将是nvarchar和不同的哈希。

我通过强制转换表达式将密码和salt连接到varchar来解决我的问题。

一个很好的测试,看看这是否真的是同样的问题是运行这个......

SELECT HASHBYTES('SHA1', UserPassword + CAST(Salt AS VARCHAR(36))),
HASHBYTES('SHA1', CAST( UserPassword + CAST(Salt AS VARCHAR(36))as varchar)) 
FROM Users