我试图使用SHA-512算法在Server 2008中实现哈希和加密密码的解决方案。此解决方案基于Michael的“专家SQL Server 2008加密”一书。根据他的例子,我能够在visual 2010中构建这个项目(.NET 3.5在C#中),并部署到Server 2008 (如下面的代码所示)。
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;我想使用它来验证登录,在这里我假设我需要检索存储给用户记录的salt值,并将它传递给SaltedHash函数,在那里它将返回哈希值。从那里开始,我将比较函数返回的散列值和存储在用户记录中的散列值。
我遇到的问题是,当我测试传递一个硬编码的盐值('0x0E5ECC235FF6BD7337FFDDE5799D4EEA')以及明文('ABCDEFGHIJ')以模拟哈希值时(例如,用于比较散列密码)。如果我用相同的硬编码盐值提供明文值('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;我假设问题在于“将明文与salt相结合”代码,但不确定。
对于如何解决这个问题,有什么想法吗?
发布于 2013-10-30 21:51:28
是的,您对数组副本犯了错误,您从未将PlainText的最后一个PlainText字节复制到目标数组中。这里是您的原始代码的更正版本。所有需要做的就是i需要上升到PlainText.Length + Salt.Length
// 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 + Salt.Length; i++)
PlainTextWithSalt[i] = PlainText.Value[i - Salt.Length];然而,使用Array.Copy更容易做到这一点
byte[] PlainTextWithSalt = new byte[PlainText.Length + Salt.Length];
Array.Copy(Salt, PlainTextWithSalt, Salt.Length);
Array.Copy(PlainText, PlainTextWithSalt, Salt.Length, PlainText.Length);还有一件事要注意。修改密码是很好的,但是那仅仅是一半的战斗,您也需要使哈希慢。通常,这是通过像bcrypt或PBKDF2这样的函数来完成的,这些函数为您管理salt和PBKDF2,另外它们还允许您将哈希的迭代次数设置为对密码执行的次数(您通常会选择一个大的数字,您希望这个数字尽可能大,这在您的终端系统中是可以容忍的)。
https://stackoverflow.com/questions/19693615
复制相似问题