Ali Al-Masry Ответов: 2

Ошибка расшифровки C++ AES: входные данные не являются полным блоком?


Вот метод шифрования на языке Си#:

string CryptographyKey = "BC234xs45nme7HU9";
        public byte[] Encrypt(byte[] IN)
        {
            byte[] OUT;
            using (Aes encryptor = Aes.Create())
            {
                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(CryptographyKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(IN, 0, IN.Length);
                        cs.Close();
                    }
                    OUT = ms.ToArray();
                }
            }
            return OUT;
        }


А вот и метод расшифровки в c++:

void Cryptograph::Decrypt(void* in, void* out, int Size)
{
    try
    {
        unsigned char* pIn = (unsigned char*)in;
        unsigned char* pOut = (unsigned char*)out;
        cli::array<unsigned char> ^Buffer;
        Buffer = gcnew cli::array<unsigned char>(Size);

        cli::array<unsigned char> ^OutBuffer;
        OutBuffer = gcnew cli::array<unsigned char>(Size);

        cli::array<unsigned char> ^Salt;
        Salt = gcnew cli::array<unsigned char>(13) { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 };
        for (int i = 0; i < Size; i++)
            Buffer[i] = pIn[i];

        Aes^ encryptor = Aes::Create();

        System::String^ CryptographyKey = "BC234xs45nme7HU9";
        Rfc2898DeriveBytes^ pdb = gcnew Rfc2898DeriveBytes(CryptographyKey, Salt);
        encryptor->Key = pdb->GetBytes(32);
        encryptor->IV = pdb->GetBytes(16);

        ICryptoTransform^ ICT = encryptor->CreateDecryptor();

        MemoryStream^ ms = gcnew MemoryStream();
        CryptoStream^ cs = gcnew CryptoStream(ms, ICT, CryptoStreamMode::Write);
        cs->Write(Buffer, 0, Size);

        OutBuffer = ms->ToArray();

        cs->Close();
        ms->Close();
        delete cs;
        for (int i = 0; i < Size; i++)
            pOut[i] = OutBuffer[i];
    }
    catch(Exception^ e) { throw gcnew Exception("Failed to create DES Symmetric CryptoStream with error: " + e->Message); }
}


Что я уже пробовал:

Но он продолжает выбрасывать исключение в cs->Close(); что говорит о том, что это не полный блок? Я использую 16-байтовый/ 128 - битный массив с размером блока, установленным на 128. Я не понимаю, что случилось?

Никаких выходных результатов при расшифровке только это сообщение об исключении... даже если я прокомментировал код закрытия потока, я получаю исключение при закрытии потока памяти, если его тоже прокомментировали, то OutBuffer всегда пуст, а длина потока памяти равна 0

2 Ответов

Рейтинг:
2

Ali Al-Masry

Ладно, проблема исправлена, я забыл зашифровать первый пакет, который был отправлен в приложение c++, теперь все идет хорошо

Я также отредактировал код, чтобы он был таким

unsigned char* Cryptograph::Decrypt(void* in, int Size)
{
	try
	{
		unsigned char* pIn = (unsigned char*)in;

		cli::array<unsigned char> ^Buffer;
		Buffer = gcnew cli::array<unsigned char>(Size);

		cli::array<unsigned char> ^OutBuffer;
		OutBuffer = gcnew cli::array<unsigned char>(Size);

		cli::array<unsigned char> ^Salt;
		Salt = gcnew cli::array<unsigned char>(13) { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 };
		for (int i = 0; i < Size; i++)
			Buffer[i] = pIn[i];

		Aes^ encryptor = Aes::Create();

		System::String^ CryptographyKey = "BC234xs45nme7HU9";
		Rfc2898DeriveBytes^ pdb = gcnew Rfc2898DeriveBytes(CryptographyKey, Salt);
		encryptor->Key = pdb->GetBytes(32);
		encryptor->IV = pdb->GetBytes(16);

		ICryptoTransform^ ICT = encryptor->CreateDecryptor();

		MemoryStream^ ms = gcnew MemoryStream();
		CryptoStream^ cs = gcnew CryptoStream(ms, ICT, CryptoStreamMode::Write);
		cs->Write(Buffer, 0, Size);
		cs->FlushFinalBlock();
		OutBuffer = ms->ToArray();

		cs->Close();
		ms->Close();
		delete cs;
		unsigned char* pOut = new unsigned char[OutBuffer->Length];
		for (int i = 0; i < OutBuffer->Length; i++)
			pOut[i] = OutBuffer[i];
		return pOut;
	}
	catch (System::Exception^ e) { throw gcnew System::Exception("Failed to create DES Symmetric CryptoStream with error: " + e->Message); }
}


Рейтинг:
0

OriginalGriff

Вызов Close должен вызвать FlushFinalBlock - но справочные источники показывают, что это не так
в частности, переопределите метод Close в классе Rfc2898DeriveBytes, поэтому, возможно, стоит заменить ваш вызов close:

using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
    cs.Write(IN, 0, IN.Length);
    cs.FlushFinalBlock();
}
Учитывая, что блок using закроет и утилизирует поток для вас.


Ali Al-Masry

можно ли использовать оператор using таким образом, который вы предоставили в c++?
я сталкиваюсь со своей проблемой в коде c++, а не C# one