<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

      詳細說明對密碼執行散列與 salt 運算方法

      [摘要]大家對密碼執行散列和Salt運算一定不陌生。兩個Visual Studio企業版示例都是用的這個方法來加密這個方法的。結合示例代碼,我總結了一個包含對密碼進行加密,比較等靜態方法的類! ∈褂谜f明:先用HashAndSalt方法對密碼進行加密,然后存儲到數據庫中。 在用戶登錄時用ComparePa...

        大家對密碼執行散列和Salt運算一定不陌生。兩個Visual Studio企業版示例都是用的這個方法來加密這個方法的。結合示例代碼,我總結了一個包含對密碼進行加密,比較等靜態方法的類。
        使用說明:先用HashAndSalt方法對密碼進行加密,然后存儲到數據庫中。 在用戶登錄時用ComparePasswords方法在對用戶輸入的密碼和用戶注冊時存儲在數據庫中的密碼進行比較,判斷用戶輸入的密碼是否正確。

       

      Credentials.cs

      using System;
      using System.IO;
      using System.Text;
      using System.Security.Cryptography;
       
      namespace BookStore.Common
      {
             /// <summary>
             /// Credentials 的摘要說明。
             /// 原理:
             /// 對密碼執行散列運算
             /// 若要避免以明文形式存儲密碼,一種常見的安全做法是對密碼執行散列運算。如以下代碼所示,使用 System.Security.Cryptography 命名空間(它實現 160 位 SHA-1 標準)對密碼進行散列運算。有關更多信息,請參見 SHA1 成員。
             /// 對散列執行 Salt 運算
             /// 雖然對密碼執行散列運算的一個好的開端,但若要增加免受潛在攻擊的安全性,則可以對密碼散列執行 Salt 運算。Salt 就是在已執行散列運算的密碼中插入的一個隨機數字。這一策略有助于阻止潛在的攻擊者利用預先計算的字典攻擊。字典攻擊是攻擊者使用密鑰的所有可能組合來破解密碼的攻擊。當您使用 Salt 值使散列運算進一步隨機化后,攻擊者將需要為每個 Salt 值創建一個字典,這將使攻擊變得非常復雜且成本極高。
             /// Salt 值隨散列存儲在一起,并且未經過加密。所存儲的 Salt 值可以在隨后用于密碼驗證。
             /// </summary>
             public class Credentials
             {
                    private static string key = "!48%0d-F=cj>,s&2";  //密鑰(增加密碼復雜度,好像比較多余)
                    private const int saltLength = 4;                         //定義salt值的長度
       
                    /// <summary>
                    /// 對密碼進行Hash 和 Salt
                    /// </summary>
                    /// <param name="Password">用戶輸入的密碼</param>
                    /// <returns></returns>
                    public static byte[] HashAndSalt(string Password)
                    {
                           return CreateDbPassword(HashPassword(Password));
                    }
       
                    /// <summary>
                    /// 對用戶輸入的密碼加上密鑰key后進行SHA1散列
                    /// </summary>
                    /// <param name="Password">用戶輸入的密碼</param>
                    /// <returns>返回 160 位 SHA-1 散列后的的byte[](160位對應20個字節)</returns>
                    private static byte[] HashPassword( string Password )
                    {
                           //創建SHA1的對象實例sha1
                           SHA1 sha1 = SHA1.Create();
                           //計算輸入數據的哈希值
                           return sha1.ComputeHash( Encoding.Unicode.GetBytes( Password + key ) );
                    }
                   
                    /// <summary>
                    /// 比較數據庫中的密碼和所輸入的密碼是否相同
                    /// </summary>
                    /// <param name="storedPassword">數據庫中的密碼</param>
                    /// <param name="Password">用戶輸入的密碼</param>
                    /// <returns>true:相等/false:不等</returns>
                    public static bool ComparePasswords(byte[] storedPassword, string Password)
                    {
                           //首先將用戶輸入的密碼進行Hash散列
                           byte[] hashedPassword = HashPassword(Password);
       
                           if (storedPassword == null hashedPassword == null hashedPassword.Length != storedPassword.Length - saltLength)
                           {
                                  return false;
                           }
       
                           //獲取數據庫中的密碼的salt 值,數據庫中的密碼的后4個字節為salt 值
                           byte[] saltValue = new byte[saltLength];
                           int saltOffset = storedPassword.Length - saltLength;
                           for (int i = 0; i < saltLength; i++){
                                  saltValue[i] = storedPassword[saltOffset + i];
                           }
                          
                           //用戶輸入的密碼用戶輸入的密碼加上salt 值,進行salt
                           byte[] saltedPassword = CreateSaltedPassword(saltValue, hashedPassword);
                   
                           //比較數據庫中的密碼和經過salt的用戶輸入密碼是否相等
                           return CompareByteArray(storedPassword, saltedPassword);
                    }
       
                    /// <summary>
                    /// 比較兩個ByteArray,看是否相等
                    /// </summary>
                    /// <param name="array1"></param>
                    /// <param name="array2"></param>
                    /// <returns>true:相等/false:不等</returns>
                    private static bool CompareByteArray(byte[] array1, byte[] array2)
                    {
                           if (array1.Length != array2.Length)
                           {
                                  return false;
                           }
                           for (int i = 0; i < array1.Length; i++)
                           {
                                  if (array1[i] != array2[i])
                                  {
                                         return false;
                                  }
                           }
                           return true;
                    }
       
                    /// <summary>
                    /// 對要存儲的密碼進行salt運算
                    /// </summary>
                    /// <param name="unsaltedPassword">沒有進行過salt運算的hash散列密碼</param>
                    /// <returns>經過salt的密碼(經過salt的密碼長度為:20+4=24,存儲密碼的字段為Binary(24))</returns>
                    private static byte[] CreateDbPassword(byte[] unsaltedPassword)
                    {
                           //獲得 salt 值
                           byte[] saltValue = new byte[saltLength];
                           RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                           rng.GetBytes(saltValue);
                          
                           return CreateSaltedPassword(saltValue, unsaltedPassword);
                    }
                   
                    /// <summary>
                    /// 創建一個經過salt的密碼
                    /// </summary>
                    /// <param name="saltValue">salt 值</param>
                    /// <param name="unsaltedPassword">沒有進行過salt運算的hash散列密碼</param>
                    /// <returns>經過salt的密碼</returns>
                    private static byte[] CreateSaltedPassword(byte[] saltValue, byte[] unsaltedPassword)
                    {
                           //將salt值數組添加到hash散列數組后拼接成rawSalted數組中
                           byte[] rawSalted  = new byte[unsaltedPassword.Length + saltValue.Length];
                           unsaltedPassword.CopyTo(rawSalted,0);
                           saltValue.CopyTo(rawSalted,unsaltedPassword.Length);
                          
                           //將合并后的rawSalted數組再進行SHA1散列的到saltedPassword數組(長度為20字節)
                           SHA1 sha1 = SHA1.Create();
                           byte[] saltedPassword = sha1.ComputeHash(rawSalted);
       
                           //將salt值數組在添加到saltedPassword數組后拼接成dbPassword數組(長度為24字節)
                           byte[] dbPassword  = new byte[saltedPassword.Length + saltValue.Length];
                           saltedPassword.CopyTo(dbPassword,0);
                           saltValue.CopyTo(dbPassword,saltedPassword.Length);
       
                           return dbPassword;
                    }
       
             }
      }





      日韩精品一区二区三区高清