Asp.Net Core 密码加密方案
使用PBKDF2算法來創(chuàng)建哈希的方法。PBKDF2全稱Password-Based Key Derivation Function,它的基本原理是通過一個(gè)偽隨機(jī)函數(shù)(例如HMAC函數(shù)),把明文和一個(gè)鹽值作為輸入?yún)?shù),然后重復(fù)進(jìn)行運(yùn)算,最終產(chǎn)生秘鑰。如果重復(fù)的次數(shù)足夠大,破解的成本將非常大。
PBKDF2定義如下
DK = PBKDF2(PRF, Password, Salt, c, dkLen)- PRF 是一個(gè)偽隨機(jī)函數(shù),可以簡(jiǎn)單的理解為 Hash 函數(shù)。
- Password 表示口令 。
- Salt 表示鹽值,一個(gè)隨機(jī)數(shù)。
- c 表示迭代次數(shù)。
- dkLen 表示最后輸出的密鑰長(zhǎng)度。
我們先引入NuGet包
Install-Package Microsoft.AspNetCore.Cryptography.KeyDerivation -Version 3.1.6我們創(chuàng)建一個(gè)加密密碼的方法,傳入需要加密密碼,和鹽。參數(shù)的含義已經(jīng)寫在注釋里了。
private static string HashPassword(string value, string salt){var valueBytes = KeyDerivation.Pbkdf2(password: value,//密碼salt: Encoding.UTF8.GetBytes(salt),//鹽prf: KeyDerivationPrf.HMACSHA512,//偽隨機(jī)函數(shù),這里是SHA-512iterationCount: 10000,//迭代次數(shù)numBytesRequested: 256 / 8);//最后輸出的秘鑰長(zhǎng)度return Convert.ToBase64String(valueBytes);}現(xiàn)在密碼有了,還缺點(diǎn)鹽,我們?cè)賹懸粋€(gè)隨機(jī)鹽生成的方法。
private static string GenerateSalt(){byte[] randomBytes = new byte[128 / 8];using (var generator = RandomNumberGenerator.Create()){generator.GetBytes(randomBytes);return Convert.ToBase64String(randomBytes);}}好了,現(xiàn)在我們有了密碼,有了鹽,也有了加密好的hash值,那么用戶登錄的時(shí)候,如何校驗(yàn)密碼是否正確呢,我們?cè)賹懸粋€(gè)hash校驗(yàn)的方法。這時(shí)我們需要輸入用戶輸入的密碼,鹽,以及生成好的hash值,就可以判斷用戶輸入的密碼是否正確了。
private static bool Validate(string password, string salt, string hash)=> HashPassword(password, salt) == hash;至此,內(nèi)部的密碼加密和校驗(yàn)部分已經(jīng)完成了,但還有一個(gè)問題,就是創(chuàng)建用戶密碼的時(shí)候,如何存儲(chǔ)的用戶密碼的hash值和鹽呢,這里我采取使用“點(diǎn)”進(jìn)行拼接存儲(chǔ),即使用salt.hash的形式,相應(yīng)的,取值校驗(yàn),再以“點(diǎn)”進(jìn)行拆分。具體代碼如下
public static string HashPassword(string password){var salt = GenerateSalt();var hash = HashPassword(password, salt);var result = $"{salt}.{hash}";Console.WriteLine("hash result:{0}", result);return result;}相應(yīng)的,我們?cè)偬峁┮粋€(gè)對(duì)外的密碼校驗(yàn)函數(shù)
public static bool VerifyHashedPassword(string password, string storePassword){if (string.IsNullOrEmpty(password)){throw new ArgumentNullException(nameof(password));}if (string.IsNullOrEmpty(storePassword)){throw new ArgumentNullException(nameof(storePassword));}var parts = storePassword.Split('.');var salt = parts[0];var hash = parts[1];return Validate(password, salt, hash); ;}至此,所有代碼編寫完成,我們下面來試試效果。
我們輸入一個(gè)簡(jiǎn)單的密碼,1234,循環(huán)了5次,模擬5個(gè)用戶都使用1234這個(gè)密碼,我們看一下效果。
var password = "1234";for (int i = 0; i < 5; i++){var result = PasswordHasher.HashPassword(password);var right = PasswordHasher.VerifyHashedPassword(password, result);Console.WriteLine("password is right:{0}", right);}可以看出這五條數(shù)據(jù)雖然擁有相同的密碼,但是擁有不同的鹽和hash值。
-
完整的代碼如下
- public class PasswordHasher{private static string HashPassword(string value, string salt){var valueBytes = KeyDerivation.Pbkdf2(password: value,salt: Encoding.UTF8.GetBytes(salt),prf: KeyDerivationPrf.HMACSHA512,iterationCount: 10000,numBytesRequested: 256 / 8);return Convert.ToBase64String(valueBytes);}public static string HashPassword(string password){var salt = GenerateSalt();var hash = HashPassword(password, salt);var result = $"{salt}.{hash}";Console.WriteLine("hash result:{0}", result);return result;}private static bool Validate(string password, string salt, string hash)=> HashPassword(password, salt) == hash;public static bool VerifyHashedPassword(string password, string storePassword){if (string.IsNullOrEmpty(password)){throw new ArgumentNullException(nameof(password));}if (string.IsNullOrEmpty(storePassword)){throw new ArgumentNullException(nameof(storePassword));}var parts = storePassword.Split('.');var salt = parts[0];var hash = parts[1];return Validate(password, salt, hash); ;}private static string GenerateSalt(){byte[] randomBytes = new byte[128 / 8];using (var generator = RandomNumberGenerator.Create()){generator.GetBytes(randomBytes);return Convert.ToBase64String(randomBytes);}}}
總結(jié)
以上是生活随笔為你收集整理的Asp.Net Core 密码加密方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# - 习题07_计算1分2分5分硬币
- 下一篇: 设计模式之状态模式(State)