[英]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哈希密碼?
你真的很親密。 您給出的鏈接向您展示了如何調用Rfc2898DeriveBytes函數來獲取PBKDF2哈希結果。 但是,由於示例使用派生密鑰進行加密(PBKDF1和2的原始動機是創建適合用作加密密鑰的“密鑰”派生函數),因此您被拋棄了。 當然,我們不希望將輸出用於加密,而是將其作為哈希本身。
如果你想要PBKDF2,你可以嘗試為此目的編寫的SimpleCrypto.Net庫。 如果你看看實現 ,你可以看到它實際上只是一個薄的包裝(你猜對了) Rfc2898DeriveBytes 。
如果你想試驗這個變種,可以試試名為(還有什么) 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都有一個使用PBKDF2的示例代碼頁面:
來自文章:
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.