[英]C# AES and RSA File Encryption - How to use IV?
I'm writing a program at the moment that works under the following scenario:我正在编写一个程序,它可以在以下情况下工作:
As far as I understand, that protocol is fitting for my use case.据我了解,该协议适合我的用例。
The issue I'm having is coding it up in C#.我遇到的问题是用 C# 编码。 I ran into needing an Initialization Vector(IV) for my AES encryption, I tried to encrypt this along with the AES key by using the public RSA key on both.
我遇到了 AES 加密需要初始化向量 (IV) 的情况,我尝试通过在两者上使用公共 RSA 密钥来将其与 AES 密钥一起加密。 But the 512(2 * 256) size is larger than RSA is happy to encrypt.
但是 512(2 * 256) 大小比 RSA 乐于加密的要大。 So I figured out since I created the Initialization Vector randomly each time just like the AES Key, I can add the IV to the front of the AES ciphertext.
所以我想,既然我每次都像 AES 密钥一样随机创建初始化向量,我可以将 IV 添加到 AES 密文的前面。 However, I'm not sure where the code to do this would be inserted in my functions
但是,我不确定在我的函数中执行此操作的代码的位置
Any help in the right direction to the "protocol" or other ways to write the IV to the ciphertext would be great.任何对“协议”或其他将 IV 写入密文的方法的正确方向的帮助都会很棒。 Thank you in advance.
先感谢您。
static public Tuple<byte[], byte[]> EncryptAES(byte[] toEncryptAES, RSAParameters RSAPublicKey)
{
byte[] encryptedAES = null;
byte[] encryptedRSA = null;
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Mode = CipherMode.CBC;
AES.GenerateIV();
AES.GenerateKey();
encryptedRSA = RSAEncrypt(AES.Key, RSAPublicKey);
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
ms.Write(AES.IV, 0, AES.KeySize); //DOESNT WORK HERE
//Can't use CS to write it to the stream else it will encrypt along with file
cs.Write(toEncryptAES, 0, toEncryptAES.Length);
cs.Close();
}
encryptedAES = ms.ToArray();
}
}
return new Tuple<byte[], byte[]>(encryptedAES, encryptedRSA);
}
static public byte[] DecryptAES(byte[] toDecryptAES, byte[] AESKeyAndIV, RSAParameters RSAPrivateKey)
{
byte[] AESKey = RSADecrypt(AESKeyAndIV, RSAPrivateKey);
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Key = AESKey;
ms.Read(AES.IV, 0, AES.KeySize); //Not sure if can read MS here
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
//Would I need to move 0 to 256?
cs.Write(toDecryptAES, 0, toDecryptAES.Length);
cs.Close();
}
return ms.ToArray();
}
}
}
You where quite close, write out the IV before you create the CryptoStream您非常接近,请在创建 CryptoStream 之前写出 IV
static public Tuple<byte[], byte[]> EncryptAES(byte[] toEncryptAES, RSAParameters RSAPublicKey)
{
byte[] encryptedAES = null;
byte[] encryptedRSA = null;
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Mode = CipherMode.CBC;
AES.GenerateIV();
AES.GenerateKey();
encryptedRSA = RSAEncrypt(AES.Key, RSAPublicKey);
ms.Write(AES.IV, 0, AES.KeySize); //Move the write here.
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(toEncryptAES, 0, toEncryptAES.Length);
cs.Close();
}
encryptedAES = ms.ToArray();
}
}
return new Tuple<byte[], byte[]>(encryptedAES, encryptedRSA);
}
For the decrypt, make sure you loop over the read till you have fully read the byte[] for the IV, Stream.Read
is not guaranteed to read all the bytes you asked it to read.对于解密,请确保循环读取直到您完全读取了 IV 的 byte[],
Stream.Read
不能保证读取您要求它读取的所有字节。 I usually make a static method ReadFully
to ensure all bytes are read.我通常会创建一个静态方法
ReadFully
来确保读取所有字节。
private static byte[] ReadFully(Stream stream, int length)
{
int offset = 0;
byte[] buffer = new byte[length];
while(offset < length)
{
offset += stream.Read(buffer, offset, length - offset);
}
return buffer;
}
Then just use that method to read in the IV.然后只需使用该方法读取IV。 You also want to use
cs.Read
not cs.Write
to read out the encrypted data and put the stream in to read mode, however it is easier to just use .CopyTo
and copy the data to a new MemoryStream.您还想使用
cs.Read
而不是cs.Write
来读出加密数据并将流置于读取模式,但是使用.CopyTo
并将数据复制到新的 MemoryStream 会更容易。
static public byte[] DecryptAES(byte[] toDecryptAES, byte[] AESKeyAndIV, RSAParameters RSAPrivateKey)
{
byte[] AESKey = RSADecrypt(AESKeyAndIV, RSAPrivateKey);
using (MemoryStream source = new MemoryStream(toDecryptAES))
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Key = AESKey;
var iv = ReadFully(source, AES.KeySize);
AES.IV = iv;
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(source, AES.CreateDecryptor(), CryptoStreamMode.Read))
{
using(var dest = new MemoryStream())
{
cs.CopyTo(dest);
return dest.ToArray();
}
}
}
}
}
For other readers, note that RSAEncrypt
and RSADecrypt
are wrappers for calls to the RSACryptoServiceProvider
.对于其他读者,请注意
RSAEncrypt
和RSADecrypt
是调用RSACryptoServiceProvider
包装器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.