我正在尝试使用SHA-512算法实现SQL Server 2008中的散列和密码解决方案。此解决方案基于Michael Coles出版的书籍“Expert SQL Server 2008 Encryption”。基于他的例子,我能够在Visual Studio 2010(C#中的.NET 3.5)中构建项目并部署到SQL Server 2008(如下面的代码所示)。使用SQL Server 2008密码散列CLR
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Cryptography;
namespace Apress.Samples
{
public partial class CustomEncryption
{
[Microsoft.SqlServer.Server.SqlFunction
(
IsDeterministic = true,
DataAccess = DataAccessKind.None
)]
public static SqlBytes SaltedHash
(
SqlString Algorithm,
[SqlFacet(MaxSize = -1)] SqlBytes PlainText,
SqlBytes Salt
)
{
// Return NULL if any of the parameters is NULL
if (Algorithm.IsNull || PlainText.IsNull || Salt.IsNull)
return SqlBytes.Null;
// Determine which algorithm to use
bool HashDefined = true;
HashAlgorithm Hash = null;
switch (Algorithm.Value.ToUpper())
{
case "SHA256":
Hash = new SHA256Managed();
break;
case "SHA384":
Hash = new SHA384Managed();
break;
case "SHA512":
Hash = new SHA512Managed();
break;
default:
HashDefined = false;
break;
}
if (!HashDefined)
throw new Exception
("Unsupported hash algorithm - use SHA256, SHA384 or SHA512");
// Combine the plaintext with the salt
byte[] PlainTextWithSalt = new byte[PlainText.Length + Salt.Length];
for (long i = 0; i < Salt.Length; i++)
PlainTextWithSalt[i] = Salt[i];
for (long i = Salt.Length; i < PlainText.Length; i++)
PlainTextWithSalt[i] = PlainText.Value[i - Salt.Length];
// Generate the hash and return the result
byte[] HashBytes = Hash.ComputeHash(PlainTextWithSalt);
return new SqlBytes(HashBytes);
}
}
}
当我使用下面的代码从SQL执行测试时,按照预期为每个算法生成哈希。
DECLARE @plaintext varchar(15);
SET @plaintext = 'ABCDEFGHIJ';
DECLARE @salt varbinary(16);
SET @salt = Crypt_Gen_Random(16);
DECLARE @sha256 varbinary(32)
DECLARE @sha384 varbinary(48)
DECLARE @sha512 varbinary(64)
SELECT @sha256 = dbo.SaltedHash('SHA256', CAST(@plaintext AS varbinary(max)), @salt);
SELECT @sha384 = dbo.SaltedHash('SHA384', CAST(@plaintext AS varbinary(max)), @salt);
SELECT @sha512 = dbo.SaltedHash('SHA512', CAST(@plaintext AS varbinary(max)), @salt);
SELECT 'SHA-256' AS algorithm, @sha256 AS hash
UNION ALL
SELECT 'SHA-384', @sha384
UNION ALL
SELECT 'SHA-512', @sha512;
我想用这个验证登录,在这里我假设我需要检索存储在用户记录中的盐值并将其传递到SaltedHash功能,哪里会返回哈希值。从那里,我将比较函数返回的哈希值和存储在用户记录中的哈希值。
我遇到的问题是当我测试传递一个硬编码盐值('0x0E5ECC235FF6BD7337FFDDE5799D4EEA'),以及明文('ABCDEFGHIJ')模拟检索哈希值(例如比较散列密码)。如果我使用相同的硬编码salt值提供明文值('1234567890'),它将返回完全相同的哈希值。实际上,任何10个字符的明文值都会返回相同的哈希值。
DECLARE @plaintext varchar(15);
SET @plaintext = 'ABCDE12345';
DECLARE @salt varbinary(16);
SET @salt = 0x0E5ECC235FF6BD7337FFDDE5799D4EEA; // Hardcoded salt value!
SELECT @salt
DECLARE @sha256 varbinary(32)
DECLARE @sha384 varbinary(48)
DECLARE @sha512 varbinary(64)
SELECT @sha256 = dbo.SaltedHash('SHA256', CAST(@plaintext AS varbinary(max)), @salt);
SELECT @sha384 = dbo.SaltedHash('SHA384', CAST(@plaintext AS varbinary(max)), @salt);
SELECT @sha512 = dbo.SaltedHash('SHA512', CAST(@plaintext AS varbinary(max)), @salt);
SELECT 'SHA-256' AS algorithm, @sha256 AS hash
UNION ALL
SELECT 'SHA-384', @sha384
UNION ALL
SELECT 'SHA-512', @sha512;
我假设问题在于“结合明文与盐”的代码,但不确定。
有关如何解决此问题的任何想法?
请注意,如果盐在您的最终解决方案中进行了硬编码,则它不是盐。这将是一个[Pepper],盐每个密码都是唯一的,你通常会只需将salt存储在下一列中,或将其连接到密文字节阵列的前面或后面。 –
谢谢你的提示,因为我不熟悉'胡椒'。我的意图是按照您的建议为每个密码创建一个独特的salt。 – vanexellent