Шифрование C# AES в CFB, где длина открытого текста равна длине зашифрованного

У меня есть существующий формат данных, части которого зашифрованы в том, что выглядит как AES в режиме CFB. Длина данных открытого текста и длина зашифрованных данных совпадают.

В С# почти каждый угол, который я использовал, кажется, ожидает, что зашифрованная длина будет кратной размеру блока... поэтому я получаю исключение, пытаясь расшифровать данные.

При поиске решений я использовал Crypto++ и написал быстрое приложение на C++, которое успешно расшифровывает данные, поэтому я почти уверен, что использую правильный алгоритм, ключ и IV. Это отлично работает, но я бы хотел, чтобы все было внутри С#, если это вообще возможно. Какие-либо предложения?

Рабочий код 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;

person magnvs    schedule 02.03.2012    source источник
comment
Можете ли вы опубликовать код С#, который вы пробовали, и исключение, которое вы получаете?   -  person Xint0    schedule 03.03.2012
comment
Вы проверили ответы на этот вопрос? ?   -  person President James K. Polk    schedule 03.03.2012
comment
@GregS, что вопросы и ответы могли бы использовать немного любви, это в основном реализация, если я не ошибаюсь   -  person Maarten Bodewes    schedule 03.03.2012
comment
@GregS А как насчет той части внизу, где написано, что CFB не поддерживается?   -  person Maarten Bodewes    schedule 03.03.2012
comment
@owlstead: я отредактировал этот вопрос и включил ссылку на этот ответ.   -  person President James K. Polk    schedule 04.03.2012
comment
@GregS о, круто, у тебя уже должно быть 10 тысяч :)   -  person Maarten Bodewes    schedule 04.03.2012
comment
всем спасибо. я бы попытался предоставить точный код, который я использовал, но с тех пор он был искажен до неузнаваемости после того, как я попытался использовать сторонние библиотеки, такие как cryptlib и bouncycastle. могу сказать, что решение было основано на этом сообщении.   -  person magnvs    schedule 05.03.2012


Ответы (2)


Вот пример, показывающий, как использовать класс 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();
        }
    }
}
person President James K. Polk    schedule 03.03.2012
comment
спасибо за ответ ... я попытался использовать часть кода для расшифровки, которую вы предоставили. хотя он смог расшифровать данные без исключения, он не вернул правильный открытый текст для того, что я зашифровал. - person magnvs; 05.03.2012
comment
@ pwhe23: Хорошее редактирование, спасибо за улучшение ответа. - person President James K. Polk; 05.12.2019

Я снова попытался использовать 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);
person magnvs    schedule 13.03.2012