2009-11-05 111 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> 
}