2009-11-05 105 views
21

我想在C#中對密碼進行簡單的加密和解密。如何將密碼以加密格式保存在數據庫中,並通過解密以原始格式進行檢索,有人願意幫助您獲取示例代碼。.NET中的密碼加密/解密代碼

+18

是否有任何特殊原因需要檢索?大多數時候你可以簡單地使用散列函數來存儲它。然後,當他們輸入密碼時,您將他們的條目進行散列並進行比較 – Cogwheel 2009-11-05 05:41:54

回答

14

你在這裏。我發現它在互聯網上的某個地方。適合我。

/// <summary> 
    /// Encrypts a given password and returns the encrypted data 
    /// as a base64 string. 
    /// </summary> 
    /// <param name="plainText">An unencrypted string that needs 
    /// to be secured.</param> 
    /// <returns>A base64 encoded string that represents the encrypted 
    /// binary data. 
    /// </returns> 
    /// <remarks>This solution is not really secure as we are 
    /// keeping strings in memory. If runtime protection is essential, 
    /// <see cref="SecureString"/> should be used.</remarks> 
    /// <exception cref="ArgumentNullException">If <paramref name="plainText"/> 
    /// is a null reference.</exception> 
    public string Encrypt(string plainText) 
    { 
     if (plainText == null) throw new ArgumentNullException("plainText"); 

     //encrypt data 
     var data = Encoding.Unicode.GetBytes(plainText); 
     byte[] encrypted = ProtectedData.Protect(data, null, Scope); 

     //return as base64 string 
     return Convert.ToBase64String(encrypted); 
    } 

    /// <summary> 
    /// Decrypts a given string. 
    /// </summary> 
    /// <param name="cipher">A base64 encoded string that was created 
    /// through the <see cref="Encrypt(string)"/> or 
    /// <see cref="Encrypt(SecureString)"/> extension methods.</param> 
    /// <returns>The decrypted string.</returns> 
    /// <remarks>Keep in mind that the decrypted string remains in memory 
    /// and makes your application vulnerable per se. If runtime protection 
    /// is essential, <see cref="SecureString"/> should be used.</remarks> 
    /// <exception cref="ArgumentNullException">If <paramref name="cipher"/> 
    /// is a null reference.</exception> 
    public string Decrypt(string cipher) 
    { 
     if (cipher == null) throw new ArgumentNullException("cipher"); 

     //parse base64 string 
     byte[] data = Convert.FromBase64String(cipher); 

     //decrypt data 
     byte[] decrypted = ProtectedData.Unprotect(data, null, Scope); 
     return Encoding.Unicode.GetString(decrypted); 
    } 
+0

很好的答案,我沒有理解保護方法的範圍部分。我谷歌它,我發現你可以使用DataProtection.CurrentUser。這可以嗎?還是會在解密時帶來問題?你能解釋你做什麼來創建你的範圍類。謝謝。 – euther 2011-01-14 14:27:54

+6

也許我錯了,但它看起來像這種解決方案不能跨用戶/機器移植,因此不適合存儲加密數據。從文檔中:「DPAPI將關鍵數據存儲在用戶配置文件中」。如果您使用此方法來加密和存儲數據,那麼如果您重新構建服務器,則無法從其他計算機檢索和解密數據,或者無法使用天堂。 – Brett 2011-08-25 14:21:38

+1

Visual Studio不能識別「範圍」? – 2013-06-08 14:26:03

12

編輯:這是一個非常古老的答案。 2011年,SHA1已被棄用,現在在實踐中已被打破。 https://shattered.io/改爲使用更新的標準(例如SHA256,SHA512等)。

如果你的答案在我的意見,問題是「否」,這是我使用:

public static byte[] HashPassword(string password) 
    { 
     var provider = new SHA1CryptoServiceProvider(); 
     var encoding = new UnicodeEncoding(); 
     return provider.ComputeHash(encoding.GetBytes(password)); 
    } 
+2

SHA1已被破壞,如下所示:http://okami-infosec.blogspot.com/2007/01/hash-sha-1-compromised.html – 2009-11-05 06:50:39

+0

我不相信任何SHA-2家族已被妥協,你可能想要使用其中的一個:http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-2_family – 2009-11-05 06:52:11

+0

但是,這取決於你會如何安全或多麼偏執。在大學我非常偏執。 – 2009-11-05 06:53:06

0

一個加密的最簡單的方法(如果你絕對必須做一個了自己,因爲.NET有這種令人敬畏的加密庫已經[正如我之前的Cogwheel所提供])是將輸入字符串的每個字符的ASCII值與已知的「鍵」值進行異或運算。我相信C#中的異或功能是使用^鍵實現的。

然後,您可以將值從XOR的結果轉換回ASCII字符,並將它們存儲在數據庫中。這不是非常安全,但它是最簡單的加密方法之一。

此外,如果使用訪問數據庫,我發現在打開數據庫本身時,將某些字符放在字符串前會使整​​個字段無法讀取。但即使對於惡意用戶而言,該字段仍然可以被您的應用程序讀取。但是誰又使用訪問權呢?

+0

我知道,對吧? *無辜地看看*(其實,我正在編寫一個建議,以擺脫我繼承的系統,並進入21世紀) – Cogwheel 2009-11-05 05:55:16

+5

上帝幫助我們所有人:( – zebrabox 2009-11-05 17:43:37

+0

我感到他的痛苦。我知道的唯一原因關於訪問是因爲我正在處理一個使用舊訪問數據庫的項目,當時它已經被升級,但這並沒有阻止客戶請求舊版本的新功能。 – Jrud 2009-11-05 19:30:40

3

這個問題會回答如何加密/解密: Encrypt and decrypt a string

您沒有指定一個數據庫,但是你會想基於64位編碼它,使用Convert.toBase64String。 舉一個例子,你可以使用: http://www.opinionatedgeek.com/Blog/blogentry=000361/BlogEntry.aspx

因此,或者將其保存在VARCHAR或CLOB,這取決於你加密的消息是多久,但密碼爲varchar應該工作。

上面的例子也以base64解碼後覆蓋解密

UPDATE:

實際上你可能不需要使用base64編碼,但我發現它的幫助,如果我想打印它,或通過網絡發送它。如果消息足夠長,我發現先壓縮它然後加密是有幫助的,因爲當消息已經是二進制形式時,使用暴力更加困難,所以很難判斷何時成功破解加密。

+0

除了可移植性,使用base-64而不是二進制(如果db支持它)有什麼實質性的好處嗎? – Cogwheel 2009-11-05 05:59:30

+0

沒有好處,其他而不是事實上它更容易存儲,作爲一個字符串對待,如果你需要移動它,我發現它更容易。我不是使用blob的粉絲,主要是因爲我花了這麼長時間在mysql他們真的沒有支持,所以我只是這麼想。另外,如果你想打印出加密的消息,那麼它就是可打印的方式,這可以很方便,只是爲了看看發生了什麼。 – 2009-11-05 06:14:14

+0

好點...我在調試過程中將散列轉換爲字符串一次,並比較了最終的漢字>< – Cogwheel 2009-11-05 06:31:55

0

您可以使用託管的.Net密碼術庫,然後將加密的字符串保存到數據庫中。如果要驗證密碼,可以將存儲的數據庫字符串與用戶輸入的哈希值進行比較。在這裏看到更多的信息SHA512Managed

using System.Security.Cryptography;

public static string EncryptSHA512Managed(string password) 
    { 
     UnicodeEncoding uEncode = new UnicodeEncoding(); 
     byte[] bytPassword = uEncode.GetBytes(password); 
     SHA512Managed sha = new SHA512Managed(); 
     byte[] hash = sha.ComputeHash(bytPassword); 
     return Convert.ToBase64String(hash); 
    } 
+4

1)錯誤的方法名稱,因爲你散列和不加密。 2)不要使用快速散列來散列密碼。一次SHA-2迭代不夠好。使用scrypt,bcrypt或PBKDF2。這也不是問題的答案,因爲OP需要可逆性。 – CodesInChaos 2013-01-10 14:26:37

3

我使用RC2CryptoServiceProvider。

public static string EncryptText(string openText) 
    { 
     RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider(); 
     ICryptoTransform encryptor = rc2CSP.CreateEncryptor(Convert.FromBase64String(c_key), Convert.FromBase64String(c_iv)); 
     using (MemoryStream msEncrypt = new MemoryStream()) 
     { 
      using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) 
      { 
       byte[] toEncrypt = Encoding.Unicode.GetBytes(openText); 

       csEncrypt.Write(toEncrypt, 0, toEncrypt.Length); 
       csEncrypt.FlushFinalBlock(); 

       byte[] encrypted = msEncrypt.ToArray(); 

       return Convert.ToBase64String(encrypted); 
      } 
     } 
    } 

    public static string DecryptText(string encryptedText) 
    { 
     RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider(); 
     ICryptoTransform decryptor = rc2CSP.CreateDecryptor(Convert.FromBase64String(c_key), Convert.FromBase64String(c_iv)); 
     using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(encryptedText))) 
     { 
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) 
      { 
       List<Byte> bytes = new List<byte>(); 
       int b; 
       do 
       { 
        b = csDecrypt.ReadByte(); 
        if (b != -1) 
        { 
         bytes.Add(Convert.ToByte(b)); 
        } 

       } 
       while (b != -1); 

       return Encoding.Unicode.GetString(bytes.ToArray()); 
      } 
     } 
    } 
+0

爲了防止你想知道使用隨機有效的數據c_iv和c_key,在RC2CryptoServiceProvider實例中有一個屬性'Key'和'IV'。 – 2012-11-14 19:03:39

+5

你的IV使用不正確。對於每種加密,IV的全部要點是不同的。不要使用常量IV。 – CodesInChaos 2013-01-10 14:29:45

0
string clearText = txtPassword.Text; 
     string EncryptionKey = "MAKV2SPBNI99212"; 
     byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); 
     using (Aes encryptor = Aes.Create()) 
     { 
      Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
      encryptor.Key = pdb.GetBytes(32); 
      encryptor.IV = pdb.GetBytes(16); 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) 
       { 
        cs.Write(clearBytes, 0, clearBytes.Length); 
        cs.Close(); 
       } 
       clearText = Convert.ToBase64String(ms.ToArray()); 
      } 
     } 
0

首先創建一個類,如:

public class Encryption 
    { 
     public static string Encrypt(string clearText) 
     { 
      string EncryptionKey = "MAKV2SPBNI99212"; 
      byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); 
      using (Aes encryptor = Aes.Create()) 
      { 
       Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
       encryptor.Key = pdb.GetBytes(32); 
       encryptor.IV = pdb.GetBytes(16); 
       using (MemoryStream ms = new MemoryStream()) 
       { 
        using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) 
        { 
         cs.Write(clearBytes, 0, clearBytes.Length); 
         cs.Close(); 
        } 
        clearText = Convert.ToBase64String(ms.ToArray()); 
       } 
      } 
      return clearText; 
     } 

     public static string Decrypt(string cipherText) 
     { 
      string EncryptionKey = "MAKV2SPBNI99212"; 
      byte[] cipherBytes = Convert.FromBase64String(cipherText); 
      using (Aes encryptor = Aes.Create()) 
      { 
       Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }); 
       encryptor.Key = pdb.GetBytes(32); 
       encryptor.IV = pdb.GetBytes(16); 
       using (MemoryStream ms = new MemoryStream()) 
       { 
        using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)) 
        { 
         cs.Write(cipherBytes, 0, cipherBytes.Length); 
         cs.Close(); 
        } 
        cipherText = Encoding.Unicode.GetString(ms.ToArray()); 
       } 
      } 
      return cipherText; 
     } 
    } 

**在控制器**

這個加密類添加引用:

using testdemo.Models 

public ActionResult Index() { 
      return View(); 
     } 
     [HttpPost] 
     public ActionResult Index(string text) 
     { 
      if (Request["txtEncrypt"] != null) 
      { 
       string getEncryptionCode = Request["txtEncrypt"]; 
       string DecryptCode = Encryption.Decrypt(HttpUtility.UrlDecode(getEncryptionCode)); 
       ViewBag.GetDecryptCode = DecryptCode; 
       return View(); 
      } 
      else { 
       string getDecryptCode = Request["txtDecrypt"]; 
       string EncryptionCode = HttpUtility.UrlEncode(Encryption.Encrypt(getDecryptCode)); 
       ViewBag.GetEncryptionCode = EncryptionCode; 
       return View(); 
      } 

     } 

在View

<h2>Decryption Code</h2> 
@using (Html.BeginForm()) 
{ 
    <table class="table-bordered table"> 
     <tr> 
      <th>Encryption Code</th> 
      <td><input type="text" id="txtEncrypt" name="txtEncrypt" placeholder="Enter Encryption Code" /></td> 
     </tr> 
     <tr> 
      <td colspan="2"> 
       <span style="color:red">@ViewBag.GetDecryptCode</span> 
      </td> 
     </tr> 
     <tr> 
       <td colspan="2"> 
        <input type="submit" id="btnEncrypt" name="btnEncrypt"value="Decrypt to Encrypt code" /> 
       </td> 
      </tr> 
    </table> 
} 
    <br /> 
    <br /> 
    <br /> 
    <h2>Encryption Code</h2> 
@using (Html.BeginForm()) 
{ 
    <table class="table-bordered table"> 
     <tr> 
      <th>Decryption Code</th> 
      <td><input type="text" id="txtDecrypt" name="txtDecrypt" placeholder="Enter Decryption Code" /></td> 
     </tr> 

     <tr> 
      <td colspan="2"> 
       <span style="color:red">@ViewBag.GetEncryptionCode</span> 
      </td> 
     </tr> 
     <tr> 
      <td colspan="2"> 
       <input type="submit" id="btnDecryt" name="btnDecryt" value="Encrypt to Decrypt code" /> 
      </td> 
     </tr> 
    </table> 
}