簡體   English   中英

C#中的哈希密碼? Bcrypt / PBKDF2

[英]Hash Password in C#? Bcrypt/PBKDF2

我查詢了msdn和其他資源如何做到這一點,但我想出了沒有明確的解決方案。 這是我找到的最好的http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/generating-a-key-from-a-password.aspx?Redirected=true

我想使用bcrypt或PBKDF2(看起來與bcrypt相關)在C#中散列密碼。 我想試驗一下我的計算機散列密碼需要多少輪。 然而,一切似乎都是關於加密,而每個人都談論哈希。 我無法弄清楚。 我如何哈希密碼? 它看起來更像PBKDF2(Rfc2898?)是一個隨機數生成器,我使用GetBytes(金額)來選擇我的散列大小有多大。

我糊塗了。 我究竟如何用bcrypt / PBKDF哈希密碼?

PBKDF2

你真的很親密。 您給出的鏈接向您展示了如何調用Rfc2898DeriveBytes函數來獲取PBKDF2哈希結果。 但是,由於示例使用派生密鑰進行加密(PBKDF1和2的原始動機是創建適合用作加密密鑰的“密鑰”派生函數),因此您被拋棄了。 當然,我們不希望將輸出用於加密,而是將其作為哈希本身。

如果你想要PBKDF2,你可以嘗試為此目的編寫的SimpleCrypto.Net庫。 如果你看看實現 ,你可以看到它實際上只是一個薄的包裝(你猜對了) Rfc2898DeriveBytes

BCrypt

如果你想試驗這個變種,可以試試名為(還有什么) BCrypt.NET的C#實現。

免責聲明:我沒有使用或測試過我鏈接過的任何庫... YMMV

我花了很長時間 (需要幾天的時間)才能找到實際編碼的代碼來獲取散列密碼! 所以我把它放在這里是為了方便。

你需要閱讀文檔理論1 理論2 ,然后一些或你可能對安全漏洞開放。 安全是一個非常大的話題! 買家要小心!

將NuGet包BCrypt.Net添加到解決方案中

const int WorkFactor = 14;
var HashedPassword = BCrypt.Net.BCrypt.HashPassword(Password, WorkFactor); 

您應該將WorkFactor調整為適當的參見討論 它是一個log2函數

“這個數字是log2,因此每次計算機速度加倍時,請將默認數字加1。”

然后將散列密碼作為passwordFromLocalDB存儲在數據庫中,並測試傳入password如下所示:

if (BCrypt.Net.BCrypt.Verify(password, passwordFromLocalDB) == true)

祝好運!

今年早些時候,我正在研究為ASP.NET Web Forms項目創建哈希的相同事情,我想以與MVC項目開箱即用的方式相同的方式進行。

我偶然發現了這個問題=> ASP.NET Identity默認密碼Hasher,它是如何工作的並且它是否安全? 然后我在這里找到了帶有ByteArraysEqual方法的源=> http://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.Core/2.0.0-rtm-140327/Release/Default/ Microsoft.AspNet.Identity.Core / Microsoft.AspNet.Identity.Core / Crypto.cs?ImageName = Microsoft.AspNet.Identity.Core

首先,我敦促大家使用平台本身附帶的加密驗證參考算法

請勿使用第三方軟件包和未經驗證的OSS組件或您剛剛從Internet復制粘貼的任何其他代碼。

對於.NET, 使用PBKDF2不是bCrypt,因為沒有經過認證的bCrypt for .NET實現

我並不是說對任何高尚的開源開發者(我自己)都不尊重,但你永遠不能確定他們的網站在10年內不會被黑客入侵你最終會從Nuget / npm或其他人那里獲得惡意軟件包包管理員。

有關驗證的更多信息,請參閱此SO答案

現在,回到PBKDF2,這是簡單的代碼

public static byte[] PBKDF2Hash(string input, byte[] salt)
{
    // Generate the hash
    Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(input, salt, iterations: 5000);
    return pbkdf2.GetBytes(20); //20 bytes length is 160 bits
}

如果你需要哈希的字符串表示(不是字節數組) - 你可以從這個答案中使用這個超高速轉換類http://stackoverflow.com/a/624379/714733

對於PBKDF2,您可以使用System.Security.Cryptography.Rfc2898DeriveBytes。

請參閱MSDN: http//msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

PBKDF2使用HMACSHA1,如果你想要一個更現代和可定制的解決方案,你應該使用HMACSHA256或512關鍵拉伸來看看這個API,就像PBKDF2一樣

https://sourceforge.net/projects/pwdtknet/

源代碼中包含的示例GUI演示了如何從密碼中獲取哈希,包括創建加密隨機鹽.....享受:)

對於使用.Net Core的任何人,Microsoft都有一個使用PB​​KDF2的示例代碼頁面:

在ASP.NET Core中散列密碼

來自文章:

using System;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;

public class Program
{
    public static void Main(string[] args)
    {
        Console.Write("Enter a password: ");
        string password = Console.ReadLine();

        // generate a 128-bit salt using a secure PRNG
        byte[] salt = new byte[128 / 8];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(salt);
        }
        Console.WriteLine($"Salt: {Convert.ToBase64String(salt)}");

        // derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
        string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: password,
            salt: salt,
            prf: KeyDerivationPrf.HMACSHA1,
            iterationCount: 10000,
            numBytesRequested: 256 / 8));
        Console.WriteLine($"Hashed: {hashed}");
    }
}

/*
 * SAMPLE OUTPUT
 *
 * Enter a password: Xtw9NMgx
 * Salt: NZsP6NnmfBuYeJrrAKNuVQ==
 * Hashed: /OOoOer10+tGwTRDTrQSoeCxVTFr6dtYly7d0cPxIak=
 */

PBKDF2

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx中的示例中,當您到達“Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1,salt1,myIterations)”行時; “,k1是哈希。 該示例用於加密的原因是Rfc2898DeriveBytes最初設計用於創建加密密鑰。

如果你不提供鹽,Rfc2898DeriveBytes將創建它自己的,但我不知道RNGCryptoServiceProvider是否能更好地加密隨機。

根據OWASP( https://www.owasp.org/index.php/Using_Rfc2898DeriveBytes_for_PBKDF2 ),Rfc2898DeriveBytes對SHA1的基礎使用意味着它僅適用於長度最多為160位的散列。 如果你創建一個更長的哈希,攻擊者仍然只需要擔心前160位,但你已經使密碼哈希/身份驗證對你自己更加昂貴而沒有任何收益。

以下是Rfc2898DeriveBytes密碼散列的一些示例代碼(在數據庫中存儲散列,salt和迭代):

public class Rfc2898PasswordEncoder
{
    private int _byteLength = 160 / 8; // 160 bit hash length

    public class EncodedPassword
    {
        public byte[] Hash { get; set; }
        public byte[] Salt { get; set; }
        public int Iterations { get; set; }
    }

    public EncodedPassword EncodePassword(string password, int iterations)
    {
        var populatedPassword = new EncodedPassword
        {
            Salt = CreateSalt(),
            Iterations = iterations
        };

        // Add Hash
        populatedPassword.Hash = CreateHash(password, populatedPassword.Salt, iterations);

        return populatedPassword;
    }

    public bool ValidatePassword(string password, EncodedPassword encodedPassword)
    {
        // Create Hash
        var testHash = CreateHash(password, encodedPassword.Salt, encodedPassword.Iterations);

        return testHash == encodedPassword.Hash;
    }

    public byte[] CreateSalt()
    {
        var salt = new byte[_byteLength]; // Salt should be same length as hash

        using (var saltGenerator = new RNGCryptoServiceProvider())
        {
            saltGenerator.GetBytes(salt);
        }

        return salt;
    }

    private byte[] CreateHash(string password, byte[] salt, long iterations)
    {
        byte[] hash;
        using (var hashGenerator = new Rfc2898DeriveBytes(password, salt, (int)iterations))
        {
            hash = hashGenerator.GetBytes(_byteLength);
        }

        return hash;
    }
} 

我對不涉及任何圖書館的答案感興趣。

我讀了這篇文章https://crackstation.net/hashing-security.htm ,它鏈接了不同語言C#的實現,我將在這里鏈接

https://github.com/defuse/password-hashing/blob/master/PasswordStorage.cs

有趣的是,它使用的Rfc2898DeriveBytes在這里提到過幾次。

private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes){
    using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt)) {
        pbkdf2.IterationCount = iterations;
        return pbkdf2.GetBytes(outputBytes);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM