我对asp.net/c#相当陌生,我正尝试在C#中重新创建密码验证。我将此哈希存储在数据库中:
U2zdbUmZXCeOLs0OuS9bhg==7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=
此哈希的密码为1234567。之所以有用,是因为我可以在Web应用程序中使用此密码登录。
所以,如果我理解正确的话。哈希由base64编码的盐U2zdbUmZXCeOLs0OuS9bhg==
和用该盐哈希的密码组成:7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=
但是,如果我使用此示例,则会在Internet上找到。我没有得到相同的哈希结果。我已经尝试过使用编码(导致不同的哈希值),但是没有运气。在web.config中将hashAlgorithmType设置为HMACSHA256。我在做什么错了?
using System;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
var base64Salt = "U2zdbUmZXCeOLs0OuS9bhg==";
var base64Hash = "7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=";
// Decode the base64 salt to get the salt byte array
var saltBytes = Convert.FromBase64String(base64Salt);
// Provide the user's plain password
var plaintextPassword = "1234567";
// Salt the plaintext password, prepend to user's provided password, and then hash
try
{
var hmac256 = new HMACSHA256(saltBytes);
var hash = Convert.ToBase64String(hmac256.ComputeHash(Encoding.UTF8.GetBytes(plaintextPassword)));
Console.WriteLine(base64Salt+hash);
if (hash == base64Hash)
{
Console.WriteLine("Success! Both hashes match!");
}
else
{
Console.WriteLine("Passwords do not match.");
}
}
catch (Exception e)
{
Console.WriteLine("Error!", e.Message);
}
}
}
答案 0 :(得分:0)
您需要知道所使用的正确键,并且密码与盐串联在一起。
通常,盐字节与密码字节连接在一起,如下所示:
var password = "1234567";
var passwordBytes = Encoding.UTF8.GetBytes(password);
var salt = "U2zdbUmZXCeOLs0OuS9bhg==";
var saltBytes = Convert.FromBase64String(salt);
var passwordBytesAndSaltBytes = new byte[passwordBytes.Length + saltBytes.Length];
for (int i = 0; i < passwordBytes.Length; i++)
{
passwordBytesAndSaltBytes[i] = passwordBytes[i];
}
for (int i = 0; i < saltBytes.Length; i++)
{
passwordBytesAndSaltBytes[passwordBytes.Length + i] = saltBytes[i];
}
但是我们不知道使用了什么规则。
这个秘密很好,应该保密,像这样:
var secret = "this must be hidden";
var secretBytes = Encoding.UTF8.GetBytes(secret);
var hmac256 = new HMACSHA256(secretBytes);
var hash = Convert.ToBase64String(hmac256.ComputeHash(passwordBytesAndSaltBytes) );
不幸的是,我看不到代码,所以您不能复制它。
答案 1 :(得分:0)
终于让它起作用了!我在Umbraco的源代码中找到了答案(我使用Umbraco作为CMS)。我以为它使用的是默认的Membershipprovider,但事实并非如此。值得一提的是,盐值短于所需的密钥长度,因此它得到了扩展。
从源代码中,我创建了一个有效的示例:
using System;
using System.Security.Cryptography;
using System.Text;
public class Program
{
public static void Main()
{
var bytes = Encoding.Unicode.GetBytes("1234567");
var saltBytes = Convert.FromBase64String("U2zdbUmZXCeOLs0OuS9bhg==");
byte[] inArray;
var hashAlgorithm = HashAlgorithm.Create("HMACSHA256");
var algorithm = hashAlgorithm as KeyedHashAlgorithm;
var keyedHashAlgorithm = algorithm;
if (keyedHashAlgorithm.Key.Length == saltBytes.Length)
{
//if the salt bytes is the required key length for the algorithm, use it as-is
keyedHashAlgorithm.Key = saltBytes;
Console.WriteLine("length is ok");
}
else if (keyedHashAlgorithm.Key.Length < saltBytes.Length)
{
//if the salt bytes is too long for the required key length for the algorithm, reduce it
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
Buffer.BlockCopy(saltBytes, 0, numArray2, 0, numArray2.Length);
keyedHashAlgorithm.Key = numArray2;
Console.WriteLine("salt byte too long");
}
else
{
//if the salt bytes is too short for the required key length for the algorithm, extend it
Console.WriteLine("salt byte to short");
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
var dstOffset = 0;
while (dstOffset < numArray2.Length)
{
var count = Math.Min(saltBytes.Length, numArray2.Length - dstOffset);
Buffer.BlockCopy(saltBytes, 0, numArray2, dstOffset, count);
dstOffset += count;
}
keyedHashAlgorithm.Key = numArray2;
}
inArray = keyedHashAlgorithm.ComputeHash(bytes);
var hash = Convert.ToBase64String(inArray);
Console.WriteLine(hash);
var base64Hash = "7hQ60TTq0ZiT/z+eu4bdzpmBcp5uYa70ZDxQPncEG0c=";
if (hash == base64Hash)
{
Console.WriteLine("Success! Both hashes match!");
}
else
{
Console.WriteLine("Passwords do not match.");
}
}
}