C# .NET 中的对称加密/解密
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2150703/
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
Symmetric encrypt/decrypt in .NET
提问by Craig Schwarze
I am after a symmetric encryption/decryption routine in C#. I know there have been a few questions on this topic before, but most of the answers seem to be about the philosophy of encryption rather than giving actual code.
我正在使用 C# 中的对称加密/解密例程。我知道之前有一些关于这个主题的问题,但大多数答案似乎是关于加密的哲学而不是提供实际代码。
Update:I'd really like to see some code, rather than just links. Many thanks!
更新:我真的很想看到一些代码,而不仅仅是链接。非常感谢!
采纳答案by orip
Look at the example code at the bottom of this page.
查看本页底部的示例代码。
Copy-pasting it here:
复制粘贴到这里:
int Rfc2898KeygenIterations= 100;
int AesKeySizeInBits = 128;
String Password = "VerySecret!";
byte[] Salt = new byte[16];
System.Random rnd = new System.Random();
rnd.NextBytes(Salt);
byte[] rawPlaintext = System.Text.Encoding.Unicode.GetBytes("This is all clear now!");
byte[] cipherText= null;
byte[] plainText= null;
using (Aes aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = AesKeySizeInBits;
int KeyStrengthInBytes= aes.KeySize/8;
System.Security.Cryptography.Rfc2898DeriveBytes rfc2898 =
new System.Security.Cryptography.Rfc2898DeriveBytes(Password, Salt, Rfc2898KeygenIterations);
aes.Key = rfc2898.GetBytes(KeyStrengthInBytes);
aes.IV = rfc2898.GetBytes(KeyStrengthInBytes);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(rawPlaintext, 0, rawPlaintext.Length);
}
cipherText= ms.ToArray();
}
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherText, 0, cipherText.Length);
}
plainText = ms.ToArray();
}
}
string s = System.Text.Encoding.Unicode.GetString(plainText);
Console.WriteLine(s);
回答by jason saldo
回答by pm100
what u want are cryptoserviceproviders in the class library
你想要的是类库中的cryptoserviceproviders
like this one for AES
喜欢这个 AES
回答by Eric Lippert
Convert your text, key and initialization vector to bytes first using the encoding of your choice. Then use the triple DES provider, as demonstrated here:
首先使用您选择的编码将您的文本、键和初始化向量转换为字节。然后使用三重 DES 提供程序,如下所示:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.tripledes.aspx
http://msdn.microsoft.com/en-us/library/system.security.cryptography.tripledes.aspx
Or the one for AES, if you think triple DES is too old-school, or whatever.
或者是 AES 的,如果你认为三重 DES 太老派了,或者其他什么。
Out of curiosity, how are you planning on communicating the secret key?
出于好奇,您打算如何传达秘密密钥?
回答by blowdart
Well for starters keys are not strings, keys are binary blobs. PlainText is the same, it's not actually text, again it's a binary blob.
对于初学者来说,键不是字符串,键是二进制 blob。PlainText 是一样的,它实际上不是文本,它也是一个二进制 blob。
Now of course you can convert strings to byte arrays using Encoding.UTF8.GetBytes(message)
, however when converting keys back and forth it's a little more complicated, you usually use Convert.ToBase64String
and Convert.FromBase64String
.
现在当然您可以使用 将字符串转换为字节数组Encoding.UTF8.GetBytes(message)
,但是在来回转换键时会稍微复杂一些,您通常使用Convert.ToBase64String
和Convert.FromBase64String
。
Don't forget that block ciphers also need one more thing, the Initialization Vector, so really your method signatures should be
不要忘记分组密码还需要一件事,初始化向量,所以你的方法签名应该是
byte[] Encrypt(byte[] plainText, byte[] key, byte[] iv)
byte[] Decrypt(byte[] cipherText, byte[] key, byte[] iv)
The key and IVs must be cryptographically secure random numbers, don't just type them and don't use C#'s Random function. The size of the key and the IV depend on the cipher algorithm used, and can be accessed by the properties on the classes.
密钥和 IV必须是加密安全的随机数,不要只是键入它们,也不要使用 C# 的 Random 函数。密钥和 IV 的大小取决于使用的密码算法,并且可以通过类的属性访问。
To generate a CSRPNG you do something like
要生成 CSRPNG,您可以执行以下操作
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] key = new byte[algorithm.KeySizeValue / 8];
rng.GetBytes(key);
byte[] iv = new byte[algorithm.BlockSizeValue / 8];
rng.GetBytes(iv);
You can also use the Rfc2898DeriveBytes class to derive a key and IV from a password and a salt, but again the salt should be a cryptographically secure random number. You should also note when you create a symmetric algorithm a secure key and IV is generated for you.
您还可以使用 Rfc2898DeriveBytes 类从密码和盐派生密钥和 IV,但盐也应该是加密安全的随机数。您还应该注意,当您创建对称算法时,会为您生成一个安全密钥和 IV。
This way you can then choose the correct encoding for your text, be it UTF8, ASCII or whatever. The links have enough samples so cutting and pasting in here is rather pointless.
这样你就可以为你的文本选择正确的编码,无论是 UTF8、ASCII 还是其他。链接有足够的样本,所以在这里剪切和粘贴是毫无意义的。
回答by Jan
Here's a simple solution that I found on a VB.NET forum and converted to C#. It certainly helped me understand the topic better.
这是我在 VB.NET 论坛上找到并转换为 C# 的简单解决方案。它确实帮助我更好地理解了这个话题。
// Shamelessly lifted from http://discuss.itacumens.com/index.php?topic=62872.0,
// then converted to C# (http://www.developerfusion.com/tools/convert/vb-to-csharp/) and
// changed where necessary.
public class Encryptor
{
private static SymmetricAlgorithm _cryptoService = new TripleDESCryptoServiceProvider();
// maybe use AesCryptoServiceProvider instead?
// vector and key have to match between encryption and decryption
public static string Encrypt(string text, byte[] key, byte[] vector)
{
return Transform(text, _cryptoService.CreateEncryptor(key, vector));
}
// vector and key have to match between encryption and decryption
public static string Decrypt(string text, byte[] key, byte[] vector)
{
return Transform(text, _cryptoService.CreateDecryptor(key, vector));
}
private static string Transform(string text, ICryptoTransform cryptoTransform)
{
MemoryStream stream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(stream, cryptoTransform, CryptoStreamMode.Write);
byte[] input = Encoding.Default.GetBytes(text);
cryptoStream.Write(input, 0, input.Length);
cryptoStream.FlushFinalBlock();
return Encoding.Default.GetString(stream.ToArray());
}
}