彩虹表的反推,使md5加密也不安全了,所以一些的程序員想出了個辦法,即使用戶的密碼很短,只要我在他的短密碼后面加上一段很長的字符,再計算 md5 ,那反推出原始密碼就變得非常困難了。加上的這段長字符,我們稱為鹽(Salt),通過這種方式加密的結果,我們稱為 加鹽 Hash 。比如:md5(md5(password)+salt)
但是這種也不是特別安全,假如攻擊者拿到了salt,然后窮舉出6位密碼的所有md5(md5(password)+salt)值,那么依舊會被破解,所以更安全的一種方法就是加鹽慢哈希加密。
所謂慢哈希,其實就是指執行這個哈希函數非常慢,這樣暴力破解需要枚舉遍歷所有可能結果時,就需要花上非常非常長的時間。最好對不同用戶的密碼隨機生成不同的salt,salt庫和密碼庫分離開。
代碼
class Program { static void Main(string[] args) { string pwd = "123456"; string pwdMd5 = Md5Encryption(pwd); string salt = Guid.NewGuid().ToString("N"); string pwdSlowHash = GetSlowHashPWD(pwdMd5, salt); Console.WriteLine("鹽值:" + salt + " 加密后:" + pwdSlowHash); Console.ReadKey(); } /// <summary> /// md5加密 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string Md5Encryption(string input) { byte[] result = Encoding.Default.GetBytes(input); MD5 md5 = new MD5CryptoServiceProvider(); byte[] output = md5.ComputeHash(result); return BitConverter.ToString(output).Replace("-", ""); } /// <summary> /// 慢哈希加密 /// </summary> /// <param name="passwordMd5"></param> /// <param name="salt"></param> /// <returns></returns> internal static string GetSlowHashPWD(string passwordMd5, string salt) { int iterations = 1000;//密碼慢哈希迭代次數 byte[] saltBytes = Encoding.UTF8.GetBytes(salt); var pbkdf2 = new Rfc2898DeriveBytes(passwordMd5.ToUpper(), saltBytes, iterations); //用密碼、salt 值和迭代次數返回偽隨機密鑰。 byte[] keyBytes = pbkdf2.GetBytes(16); return BitConverter.ToString(keyBytes).Replace("-", ""); } }
參考:http://www.jianshu.com/p/d3f5aab48158
https://linux.cn/article-2722-2.html
