Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#AES和RSA文件加密-如何使用IV?_C#_Encryption_Cryptography_Aes_Rsa - Fatal编程技术网

C#AES和RSA文件加密-如何使用IV?

C#AES和RSA文件加密-如何使用IV?,c#,encryption,cryptography,aes,rsa,C#,Encryption,Cryptography,Aes,Rsa,目前我正在编写一个程序,该程序在以下场景下工作: 我有一些机密日志文件需要备份到服务器上 我有一个每天生成这些日志文件的程序 这些日志文件很少需要打开 我只有一个RSA公钥/私钥对 该程序只有RSA公钥 每次程序生成这些机密文件时,我都会生成一个随机AES密钥 程序使用此AES密钥加密日志文件 然后我使用RSA公钥加密AES密钥 然后,我将AES加密文件和RSA加密AES密钥备份到服务器 据我所知,该协议适合我的用例 我遇到的问题是用C语言编码。我遇到需要一个初始化向量(IV)来进行AES加

目前我正在编写一个程序,该程序在以下场景下工作:

  • 我有一些机密日志文件需要备份到服务器上
  • 我有一个每天生成这些日志文件的程序
  • 这些日志文件很少需要打开
  • 我只有一个RSA公钥/私钥对
  • 该程序只有RSA公钥
  • 每次程序生成这些机密文件时,我都会生成一个随机AES密钥
  • 程序使用此AES密钥加密日志文件
  • 然后我使用RSA公钥加密AES密钥
  • 然后,我将AES加密文件和RSA加密AES密钥备份到服务器
据我所知,该协议适合我的用例

我遇到的问题是用C语言编码。我遇到需要一个初始化向量(IV)来进行AES加密的情况,我试图通过在这两种加密上使用公共RSA密钥来加密它和AES密钥。但是512(2*256)的大小比RSA乐于加密的要大。所以我发现,由于我每次都随机创建初始化向量,就像AES密钥一样,我可以将IV添加到AES密文的前面。但是,我不确定在我的函数中插入执行此操作的代码的位置

任何对“协议”正确方向的帮助,或其他将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);

                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();
            }
        }
    }
static public Tuple EncryptAES(字节[]到加密,rsa参数rsa公钥)
{
字节[]encryptedAES=null;
字节[]encryptedRSA=null;
使用(MemoryStream ms=new MemoryStream())
{
使用(RijndaelManaged AES=new RijndaelManaged())
{
AES.KeySize=256;
AES.BlockSize=128;
AES.Mode=CipherMode.CBC;
AES.GenerateIV();
AES.GenerateKey();
encryptedRSA=rsacyncrypt(AES.Key,RSAPublicKey);
使用(var cs=new CryptoStream(ms,AES.CreateEncryptor(),CryptoStreamMode.Write))
{
ms.Write(AES.IV,0,AES.KeySize);//在这里不起作用
//无法使用CS将其写入流,否则它将与文件一起加密
cs.Write(toEncryptAES,0,toEncryptAES.Length);
cs.Close();
}
encryptedAES=ms.ToArray();
}
}
返回新元组(encryptedAES、encryptedRSA);
}
静态公共字节[]解密(字节[]到解密,字节[]AESKEANDIV,RSAPERVATEKEY)
{
字节[]AESKey=RSA解密(AESKeyAndIV,RSAPrivateKey);
使用(MemoryStream ms=new MemoryStream())
{
使用(RijndaelManaged AES=new RijndaelManaged())
{
AES.KeySize=256;
AES.BlockSize=128;
AES.Key=AESKey;
ms.Read(AES.IV,0,AES.KeySize);//不确定是否可以在此处读取ms
AES.Mode=CipherMode.CBC;
使用(var cs=new CryptoStream(ms,AES.CreateDecryptor(),CryptoStreamMode.Write))
{
//我需要将0移动到256吗?
cs.Write(toDecryptAES,0,toDecryptAES.Length);
cs.Close();
}
返回ToArray女士();
}
}
}

如果离你很近,在创建加密流之前写出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);
}
然后使用该方法在IV中读取。您还需要使用
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();
                }
            }
        }
    }
}

对于其他读者,请注意,
rsacrypt
RSADecrypt
是调用
rsacryptserviceprovider

“但是512(2*256)的大小大于RSA乐于加密的大小。”这表明有两件事是不好的:(1)您的IV长度为256位,不应该是这样的,因为您将块大小设置为128位,这也是IV大小。(2) 这表明您使用的RSA密钥的大小小于768位。你今天应该使用至少2048位的RSA密钥。啊,你说得对。我认为IV等于键大小,而不是块大小。当然是块大小。我来解决那个问题。RSA密钥,RSA不喜欢加密任何小于其密钥大小的东西,对吗?我想我做了一个4096 RSA密钥,所以我会在使用它之前检查并验证它。谢谢你的帮助,这两个部分都非常重要。哇,这是我希望得到的最好的答案。非常感谢你!读取流的写入模式很好,犯了愚蠢的错误。
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();
                }
            }
        }
    }
}