C# .NET 中的密码加密/解密代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1678555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Password encryption/decryption code in .NET
提问by kart
I want simple encryption and decryption of password in C#. How to save the password in encrypted format in database and retrieve as original format by decryption?
我想要在 C# 中对密码进行简单的加密和解密。如何将密码以加密格式保存在数据库中并通过解密恢复为原始格式?
采纳答案by this. __curious_geek
Here you go. I found it somewhere on the internet. Works well for me.
干得好。我在互联网上的某个地方找到了它。对我来说效果很好。
/// <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);
}
回答by Cogwheel
EDIT: this is a very old answer. SHA1 was deprecated in 2011 and has now been broken in practice. https://shattered.io/Use a newer standard instead (e.g. SHA256, SHA512, etc).
编辑:这是一个非常古老的答案。SHA1 于 2011 年被弃用,现在已在实践中被破坏。https://shattered.io/改用更新的标准(例如 SHA256、SHA512 等)。
If your answer to the question in my comment is "No", here's what I use:
如果您在我的评论中对问题的回答是“否”,这就是我使用的:
public static byte[] HashPassword(string password)
{
var provider = new SHA1CryptoServiceProvider();
var encoding = new UnicodeEncoding();
return provider.ComputeHash(encoding.GetBytes(password));
}
回答by Jrud
One of the simplest methods of encryption (if you absolutely MUST make one up yourself since .NET has such awesome encryption libraries already [as provided by Cogwheel just before me]) is to XOR the ASCII value of each character of the input string against a known "key" value. XOR functionality in C# is accomplished using the ^ key I believe.
最简单的加密方法之一(如果您绝对必须自己编写一个,因为 .NET 已经拥有如此出色的加密库 [由我之前的 Cogwheel 提供])是将输入字符串的每个字符的 ASCII 值与已知的“键”值。我相信 C# 中的 XOR 功能是使用 ^ 键完成的。
Then you can convert the values back from the result of the XOR to ASCII Chars, and store them in the database. This is not highly secure, but it is one of the easiest encryption methods.
然后,您可以将值从 XOR 的结果转换回 ASCII 字符,并将它们存储在数据库中。这不是高度安全的,但它是最简单的加密方法之一。
Also, if using an access database, I've found that some characters when put in front of a string make the entire field unreadable when opening the database itself. But the field is still readable by your app even though it is blank to a malicious user. But who uses access anymore anyway right?
此外,如果使用访问数据库,我发现当打开数据库本身时,某些字符放在字符串前面会使整个字段不可读。但是,即使对于恶意用户来说该字段是空白的,您的应用程序仍然可以读取该字段。但是谁再使用访问权限呢?
回答by James Black
This question will answer how to encrypt/decrypt: Encrypt and decrypt a string in C#?
这个问题将回答如何加密/解密: 在 C# 中加密和解密字符串?
You didn't specify a database, but you will want to base-64 encode it, using Convert.toBase64String. For an example you can use: http://www.opinionatedgeek.com/Blog/blogentry=000361/BlogEntry.aspx
您没有指定数据库,但您希望使用 Convert.toBase64String 对其进行 base-64 编码。例如,您可以使用:http: //www.opinionatedgeek.com/Blog/blogentry=000361/BlogEntry.aspx
You'll then either save it in a varchar or a blob, depending on how long your encrypted message is, but for a password varchar should work.
然后,您可以将其保存在 varchar 或 blob 中,具体取决于加密消息的长度,但对于密码 varchar 应该可以工作。
The examples above will also cover decryption after decoding the base64.
上面的示例还将涵盖解码 base64 后的解密。
UPDATE:
更新:
In actuality you may not need to use base64 encoding, but I found it helpful, in case I wanted to print it, or send it over the web. If the message is long enough it's best to compress it first, then encrypt, as it is harder to use brute-force when the message was already in a binary form, so it would be hard to tell when you successfully broke the encryption.
实际上,您可能不需要使用 base64 编码,但我发现它很有帮助,以防我想打印它或通过网络发送它。如果消息足够长,最好先对其进行压缩,然后再加密,因为当消息已经是二进制形式时很难使用暴力破解,因此很难判断何时成功破解加密。
回答by Case
You can use the managed .Net cryptography library, then save the encrypted string into the database. When you want to verify the password you can compare the stored database string with the hashed value of the user input. See here for more info about SHA512Managed
您可以使用托管的 .Net 加密库,然后将加密的字符串保存到数据库中。当您想验证密码时,您可以将存储的数据库字符串与用户输入的散列值进行比较。有关SHA512Managed 的更多信息,请参见此处
using System.Security.Cryptography;
使用 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);
}
回答by Pavel Belousov
I use RC2CryptoServiceProvider.
我使用 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());
}
}
}
回答by Jeet Poria
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());
}
}
回答by star test
First create a class like:
首先创建一个类,如:
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;
}
}
**In Controller **
**在控制器中**
add reference for this encryption class:
添加此加密类的参考:
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();
}
}
In 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>
}
回答by Jason Coyne
Do not encrypt/decrypt passwords, that is a significant security vulnerability. HASH passwords, using a strong hash algorithm such as PBKDF2, bcrypt, scrypts, or Argon.
不要加密/解密密码,这是一个重大的安全漏洞。HASH 密码,使用强哈希算法,例如 PBKDF2、bcrypt、scrypts 或 Argon。
When the user sets their password, hash it, and store the hash (and salt).
当用户设置他们的密码时,对其进行散列,并存储散列(和盐)。
When the user logs in, re-hash their provided password, and compare it to the hash in the database.
当用户登录时,重新散列他们提供的密码,并将其与数据库中的散列进行比较。