可以在C#中验证哈希密码

发布于 2025-02-08 16:47:17 字数 3147 浏览 3 评论 0原文

在C#语言中,我的目的是使用Hash_password()Hash密码,然后使用veriafie()方法对其进行验证。我哈希和盐以获取密码“ s3cr3t”,然后检查两个示例,如果密码为's3cr3t',然后返回false false forse forse forsep forspass's3cr4t'。

using System;
using System.Text;
using System.Security.Cryptography;

public class Pbkdf2_test4
{
    public const int salt_size = 24;
    public const int hash_size = 24;
    public const int iteration = 100000;
    static byte[] salt1 = new byte[salt_size];

    private static Rfc2898DeriveBytes hash_password(string password)
    {
        RandomNumberGenerator generator = RandomNumberGenerator.Create();
        byte[] salt = new byte[salt_size];
        generator.GetBytes(salt);

        salt1 = salt;

        Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt1, iteration);
        return pbkdf2;
    }
    
    private static bool verify(Rfc2898DeriveBytes pw_hash, string password)
    {
        //data1 can be a string or contents of a file.
        string data1 = "Some test data";

        try
        {
            Rfc2898DeriveBytes k1 = pw_hash;
            Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(password, salt1, iteration);

            // Encrypt the data.
            Aes encAlg = Aes.Create();
            encAlg.Key = k1.GetBytes(16);
            MemoryStream encryptionStream = new MemoryStream();
            CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
            byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);

            encrypt.Write(utfD1, 0, utfD1.Length);
            encrypt.FlushFinalBlock();
            encrypt.Close();
            byte[] edata1 = encryptionStream.ToArray();
            k1.Reset();

            // Try to decrypt, thus showing it can be round-tripped.
            Aes decAlg = Aes.Create();
            decAlg.Key = k2.GetBytes(16);
            decAlg.IV = encAlg.IV;
            MemoryStream decryptionStreamBacking = new MemoryStream();
            CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
            decrypt.Write(edata1, 0, edata1.Length);
            decrypt.Flush();
            decrypt.Close();
            k2.Reset();
            string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());

            if (!data1.Equals(data2))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        catch (Exception e)
        {
            return false;
        }
    }
    public static void Run()
    {
        Rfc2898DeriveBytes pw_hash = hash_password("s3cr3t");
        Console.WriteLine(System.Text.Encoding.UTF8.GetString(pw_hash.GetBytes(hash_size)));

        var result1 = verify(pw_hash, "s3cr3t");
        Console.WriteLine(result1);

        var result2 = verify(pw_hash, "s3cr4t");
        Console.WriteLine(result2);
    }
}

我的问题,某种程度上有一个问题,它可以返回false的验证(pw_hash,“ s3cr3t”),但是它应该返回true。在验证()中,有一个问题,但仍然无法理解,因为我给键K1和K2 True,但仍然没有收到Hash/Salt相同,我该如何解决此问题?

除此之外,我添加了任何东西以使密码存储最安全?

In C# language, my purpose is to hash password with hash_password(), then verify it with verify() methods. I hash and salt for password 's3cr3t', then check for two examples and return true if password is 's3cr3t' and return false for password 's3cr4t'.

using System;
using System.Text;
using System.Security.Cryptography;

public class Pbkdf2_test4
{
    public const int salt_size = 24;
    public const int hash_size = 24;
    public const int iteration = 100000;
    static byte[] salt1 = new byte[salt_size];

    private static Rfc2898DeriveBytes hash_password(string password)
    {
        RandomNumberGenerator generator = RandomNumberGenerator.Create();
        byte[] salt = new byte[salt_size];
        generator.GetBytes(salt);

        salt1 = salt;

        Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt1, iteration);
        return pbkdf2;
    }
    
    private static bool verify(Rfc2898DeriveBytes pw_hash, string password)
    {
        //data1 can be a string or contents of a file.
        string data1 = "Some test data";

        try
        {
            Rfc2898DeriveBytes k1 = pw_hash;
            Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(password, salt1, iteration);

            // Encrypt the data.
            Aes encAlg = Aes.Create();
            encAlg.Key = k1.GetBytes(16);
            MemoryStream encryptionStream = new MemoryStream();
            CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);
            byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1);

            encrypt.Write(utfD1, 0, utfD1.Length);
            encrypt.FlushFinalBlock();
            encrypt.Close();
            byte[] edata1 = encryptionStream.ToArray();
            k1.Reset();

            // Try to decrypt, thus showing it can be round-tripped.
            Aes decAlg = Aes.Create();
            decAlg.Key = k2.GetBytes(16);
            decAlg.IV = encAlg.IV;
            MemoryStream decryptionStreamBacking = new MemoryStream();
            CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
            decrypt.Write(edata1, 0, edata1.Length);
            decrypt.Flush();
            decrypt.Close();
            k2.Reset();
            string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());

            if (!data1.Equals(data2))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        catch (Exception e)
        {
            return false;
        }
    }
    public static void Run()
    {
        Rfc2898DeriveBytes pw_hash = hash_password("s3cr3t");
        Console.WriteLine(System.Text.Encoding.UTF8.GetString(pw_hash.GetBytes(hash_size)));

        var result1 = verify(pw_hash, "s3cr3t");
        Console.WriteLine(result1);

        var result2 = verify(pw_hash, "s3cr4t");
        Console.WriteLine(result2);
    }
}

My question, somehow there is a problem that for verify(pw_hash, "s3cr3t") that returns false however it should return true. In verify(), there is a problem but still could not understand because I give keys k1 and k2 true, but still does not receive hash/salt same, how can I fix this problem?

Apart from this, shuld I add anything to make password storage safest?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱给你人给你 2025-02-15 16:47:17

这是加密和解密通行的程序

    internal class Program
    {
        static void Main(string[] args)
        {
            Pbkdf2_test4 test4 = new Pbkdf2_test4();
            test4.Run();
            Console.ReadLine();
        }
    }

    public class Pbkdf2_test4
    {
        static string key = string.Empty;
        static string iv = string.Empty;

        public Pbkdf2_test4()
        {
            Aes encAlg = Aes.Create();
            encAlg.GenerateKey();
            key = Convert.ToBase64String(encAlg.Key);
            encAlg.GenerateIV();
            iv = Convert.ToBase64String(encAlg.IV);
        }

        public string Encrypt(string plainText, string Key, string IV)
        {
            // Check arguments.
            if (string.IsNullOrWhiteSpace(plainText))
                throw new ArgumentNullException(nameof(plainText));
            if (string.IsNullOrWhiteSpace(Key))
                throw new ArgumentNullException(nameof(Key));
            if (string.IsNullOrWhiteSpace(IV))
                throw new ArgumentNullException(nameof(IV));
            byte[] encrypted;

            // Create an AesCryptoServiceProvider object
            // with the specified key and IV.
            using (Aes aes = Aes.Create())
            {
                aes.Key = Convert.FromBase64String(Key);
                aes.IV = Convert.FromBase64String(IV);

                // Create an encrypt-or to perform the stream transform.
                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                    }
                    encrypted = msEncrypt.ToArray();
                }                
            }

            // Return the encrypted bytes from the memory stream.
            return Convert.ToBase64String(encrypted);

        }

        public string Decrypt(string cipherText, string Key, string IV)
        {
            // Check arguments.
            if (string.IsNullOrWhiteSpace(cipherText))
                throw new ArgumentNullException(nameof(cipherText));
            if (string.IsNullOrWhiteSpace(Key))
                throw new ArgumentNullException(nameof(Key));
            if (string.IsNullOrWhiteSpace(IV))
                throw new ArgumentNullException(nameof(IV));

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = string.Empty;

            // Create an AesCryptoServiceProvider object
            // with the specified key and IV.
            using (Aes aes = Aes.Create())
            {
                aes.Key = Convert.FromBase64String(Key);
                aes.IV = Convert.FromBase64String(IV);

                // Create a decrypt-or to perform the stream transform.
                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.

                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }

        public void Run()
        {
            Console.WriteLine("Key is : " + key);
            Console.WriteLine("IV is : " + iv);

            string passord = "s3cr3t";
            string encryptedPassowrd = Encrypt(passord, key, iv);
            string decryptedPassowrd = Decrypt(encryptedPassowrd, key, iv);

            Console.WriteLine($"Password = {passord} and Encrypted password = {encryptedPassowrd}");
            Console.WriteLine($"Password = {passord} and Decrypted password = {decryptedPassowrd}");


            string passord1 = "s3cr4t";
            string encryptedPassowrd1 = Encrypt(passord1, key, iv);
            string decryptedPassowrd1 = Decrypt(encryptedPassowrd1, key, iv);

            Console.WriteLine($"Password = {passord1} and Encrypted password = {encryptedPassowrd1}");
            Console.WriteLine($"Password = {passord1} and Decrypted password = {decryptedPassowrd1}");

        }
    }

Here is program to encrypt and decrypt pass

    internal class Program
    {
        static void Main(string[] args)
        {
            Pbkdf2_test4 test4 = new Pbkdf2_test4();
            test4.Run();
            Console.ReadLine();
        }
    }

    public class Pbkdf2_test4
    {
        static string key = string.Empty;
        static string iv = string.Empty;

        public Pbkdf2_test4()
        {
            Aes encAlg = Aes.Create();
            encAlg.GenerateKey();
            key = Convert.ToBase64String(encAlg.Key);
            encAlg.GenerateIV();
            iv = Convert.ToBase64String(encAlg.IV);
        }

        public string Encrypt(string plainText, string Key, string IV)
        {
            // Check arguments.
            if (string.IsNullOrWhiteSpace(plainText))
                throw new ArgumentNullException(nameof(plainText));
            if (string.IsNullOrWhiteSpace(Key))
                throw new ArgumentNullException(nameof(Key));
            if (string.IsNullOrWhiteSpace(IV))
                throw new ArgumentNullException(nameof(IV));
            byte[] encrypted;

            // Create an AesCryptoServiceProvider object
            // with the specified key and IV.
            using (Aes aes = Aes.Create())
            {
                aes.Key = Convert.FromBase64String(Key);
                aes.IV = Convert.FromBase64String(IV);

                // Create an encrypt-or to perform the stream transform.
                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                    }
                    encrypted = msEncrypt.ToArray();
                }                
            }

            // Return the encrypted bytes from the memory stream.
            return Convert.ToBase64String(encrypted);

        }

        public string Decrypt(string cipherText, string Key, string IV)
        {
            // Check arguments.
            if (string.IsNullOrWhiteSpace(cipherText))
                throw new ArgumentNullException(nameof(cipherText));
            if (string.IsNullOrWhiteSpace(Key))
                throw new ArgumentNullException(nameof(Key));
            if (string.IsNullOrWhiteSpace(IV))
                throw new ArgumentNullException(nameof(IV));

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = string.Empty;

            // Create an AesCryptoServiceProvider object
            // with the specified key and IV.
            using (Aes aes = Aes.Create())
            {
                aes.Key = Convert.FromBase64String(Key);
                aes.IV = Convert.FromBase64String(IV);

                // Create a decrypt-or to perform the stream transform.
                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.

                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }

        public void Run()
        {
            Console.WriteLine("Key is : " + key);
            Console.WriteLine("IV is : " + iv);

            string passord = "s3cr3t";
            string encryptedPassowrd = Encrypt(passord, key, iv);
            string decryptedPassowrd = Decrypt(encryptedPassowrd, key, iv);

            Console.WriteLine(
quot;Password = {passord} and Encrypted password = {encryptedPassowrd}");
            Console.WriteLine(
quot;Password = {passord} and Decrypted password = {decryptedPassowrd}");


            string passord1 = "s3cr4t";
            string encryptedPassowrd1 = Encrypt(passord1, key, iv);
            string decryptedPassowrd1 = Decrypt(encryptedPassowrd1, key, iv);

            Console.WriteLine(
quot;Password = {passord1} and Encrypted password = {encryptedPassowrd1}");
            Console.WriteLine(
quot;Password = {passord1} and Decrypted password = {decryptedPassowrd1}");

        }
    }
匿名。 2025-02-15 16:47:17

我认为您误解了 rfc2898derivebytes 。此功能可用于密码哈希(PBKDF2),但是您不需要加密零件。像PBKDF2这样的密钥推导函数的原始用例是获取(弱)用户密码并将其变成(强)键,然后可以将其用于加密数据(因此名称键启用)。后来,人们看到相同的功能适合生成密码哈希。

在您的情况下,我建议使用合适的库进行密码哈希,例如 bcrypt.net 。用法看起来像:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
string hashToStoreInDb = BCrypt.HashPassword(password);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from existingHashFromDb.
bool isPasswordCorrect = BCrypt.Verify(password, existingHashFromDb);

I think you misunderstood the example in the documentation of Rfc2898DeriveBytes. This function can be used for password hashing (PBKDF2), but then you don't need the encryption parts. The original use case of a key derivation function like PBKDF2 was to take a (weak) user password and turn it into a (strong) key which can then be used to encrypt data (thus the name key-derivation). Later one saw that the same functions are suitable to generate password hashes.

In your case I would recommend to use an appropriate library for password hashing, like BCrypt.Net. The usage would look like:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
string hashToStoreInDb = BCrypt.HashPassword(password);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from existingHashFromDb.
bool isPasswordCorrect = BCrypt.Verify(password, existingHashFromDb);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文