在C#

时间:2019-11-27 12:15:34

标签: c# asp.net security hash hmac

我对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);
        }
    }
}

2 个答案:

答案 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.");
            }
    }
}