【问题标题】:C# AES Encryption in CFB Where Plaintext Length Equals Encrypted LengthCFB 中的 C# AES 加密,其中明文长度等于加密长度
【发布时间】:2012-03-21 10:29:07
【问题描述】:

我有一个现有的数据格式,其中部分数据以 CFB 模式下的 AES 加密。明文数据长度和加密数据长度相同。

在 C# 中,我所采取的几乎每个角度似乎都期望加密长度是块大小的倍数......所以我在尝试解密数据时遇到异常。

在研究解决方案时,我使用了 Crypto++ 并编写了一个快速的 C++ 应用程序,它成功地解密了数据,所以我很确定我使用了正确的算法、密钥和 IV。这很好用,但如果可能的话,我想将所有内容都保留在 C# 中。有什么建议吗?

下面的工作 C++ 代码:

//define key
unsigned char key[16];
//populate key
//...


//define iv
unsigned char iv[16];
//populate iv
//...

std::ifstream inFile;

//open file
inFile.open("file.aes",ios::binary );

//get file size
inFile.seekg(0,ios::end);
int fileSize = (int) inFile.tellg();
inFile.seekg(offset, ios::beg);

//read/close file
char* inBytes = new char[fileSize];
inFile.read(inBytes,fileSize);
inFile.close();

//configure decryption
CFB_Mode<AES>::Decryption cfbDecryption(key, 16, iv);

//populate output bytes
char* outBytes = new char[fileSize];
cfbDecryption.ProcessData((byte*) outBytes,(byte*) inBytes,fileSize);

//open/write/close output file
std::ofstream outFile;
outFile.open("out.dec");
outFile.write(outBytes,fileSize);
outFile.close();

delete[] inBytes;

【问题讨论】:

  • 你能发布你尝试过的C#代码和你得到的异常吗?
  • 你检查this问题的答案了吗?
  • @GregS 说 q & a 可以使用一些爱,如果我没记错的话,它基本上是实现
  • @GregS 呃,那下面说不支持 CFB 的那部分呢?
  • @owlstead:我已经编辑了这个问题并包含了一个返回这个答案的链接。

标签: c# c++ encryption aes


【解决方案1】:

这是一个示例,展示了如何使用 RijndaelManaged 类来实现 8 位反馈 CFB 加密。 AesManaged 不支持 CFB,因为我相信官方 NIST AES 不支持它。通过注意到 AES 只是 Rijndael 限制为 128 位块大小和 128、192 和 256 位密钥大小,您可以使用 RijndaelManaged 类来获得您的 CFB 功能。注意:我不是 C# 或 .NET 专家,因此欢迎改进。

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace AesCFB8Mode
{
    class AESCFB8Example
    {
        static void Example()
        {
            //
            // Encrypt a small sample of data
            //
            String Plain = "The quick brown fox";
            byte[] plainBytes = Encoding.UTF8.GetBytes(Plain);
            Console.WriteLine("plaintext length is " + plainBytes.Length);
            Console.WriteLine("Plaintext is " + BitConverter.ToString(plainBytes));

            byte [] savedKey = new byte[16];
            byte [] savedIV = new byte[16];
            byte[] cipherBytes;
            using (RijndaelManaged Aes128 = new RijndaelManaged())
            {
                //
                // Specify a blocksize of 128, and a key size of 128, which make this
                // instance of RijndaelManaged an instance of AES 128.
                //
                Aes128.BlockSize = 128;
                Aes128.KeySize = 128;

                //
                // Specify CFB8 mode
                //
                Aes128.Mode = CipherMode.CFB;
                Aes128.FeedbackSize = 8;
                Aes128.Padding = PaddingMode.None;
                //
                // Generate and save random key and IV.
                //
                Aes128.GenerateKey();
                Aes128.GenerateIV();

                Aes128.Key.CopyTo(savedKey, 0);
                Aes128.IV.CopyTo(savedIV, 0);

                using (var encryptor = Aes128.CreateEncryptor())
                using (var msEncrypt = new MemoryStream())
                using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                using (var bw = new BinaryWriter(csEncrypt, Encoding.UTF8))
                {
                    bw.Write(plainBytes);
                    bw.Close();

                    cipherBytes = msEncrypt.ToArray();
                    Console.WriteLine("Cipher length is " + cipherBytes.Length);
                    Console.WriteLine("Cipher text is " + BitConverter.ToString(cipherBytes));
                }
            }

            //
            // Now decrypt the cipher back to plaintext
            //

            using (RijndaelManaged Aes128 = new RijndaelManaged())
            {
                Aes128.BlockSize = 128;
                Aes128.KeySize = 128;
                Aes128.Mode = CipherMode.CFB;
                Aes128.FeedbackSize = 8;
                Aes128.Padding = PaddingMode.None;

                Aes128.Key = savedKey;
                Aes128.IV = savedIV;

                using (var decryptor = Aes128.CreateDecryptor())
                using (var msEncrypt = new MemoryStream(cipherBytes))
                using (var csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read))
                using (var br = new BinaryReader(csEncrypt, Encoding.UTF8))
                {
                    //csEncrypt.FlushFinalBlock();
                    plainBytes = br.ReadBytes(cipherBytes.Length);

                    Console.WriteLine("Decrypted plain length is " + plainBytes.Length);
                    Console.WriteLine("Decrypted plain text bytes is " + BitConverter.ToString(plainBytes));
                    Console.WriteLine("Decrypted plain text is " + Encoding.UTF8.GetString(plainBytes));
                }
            }
        }

        static void Main(string[] args)
        {
            Example();
        }
    }
}

【讨论】:

  • 感谢您的回复...我尝试使用您提供的代码的解密部分。虽然它能够在不引发异常的情况下解密数据,但它没有为我加密的内容返回正确的明文。
  • @pwhe23:很好的编辑,感谢您改进答案。
【解决方案2】:

我重新尝试使用 cryptlib 并解决了我的问题...代码如下:

using cryptlib;

byte[] key = new byte[16] {...key bytes here...};

byte[] iv =  new byte[16] {...iv bytes here...};

byte[] enc;  //ciphertext bytes (i populated them from a filestream)

crypt.Init();
int cryptContext = crypt.CreateContext(crypt.UNUSED, crypt.ALGO_AES);
crypt.SetAttribute(cryptContext, crypt.CTXINFO_MODE, crypt.MODE_CFB);
crypt.SetAttributeString(cryptContext, crypt.CTXINFO_KEY, key, 0, 16);
crypt.SetAttributeString(cryptContext, crypt.CTXINFO_IV, iv, 0, 16);
crypt.Decrypt(cryptContext, enc);   //ciphertext bytes replaced with plaintext bytes
crypt.DestroyContext(cryptContext);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    相关资源
    最近更新 更多