Я пытаюсь написать клиентское программное обеспечение, которое выполняет шифрование AES и дешифрование сообщений на устройство с помощью C #.
Используя класс AES из System.Security.Cryptography, нет проблем с отправкой зашифрованных сообщений на устройство. Устройство успешно их расшифровывает.
Проблема возникает при расшифровке сообщений, полученных с устройства. Получаем сообщение: «Заполнение недействительно и не может быть удалено».
Я искал в Интернете и пробовал три разных подхода, но все имели одну и ту же ошибку - см. Ниже. Я также попробовал три подхода, не задавая свойство KeySize.
В дополнение к клиенту, написанному на C #, был также написан клиент на Python, где все работает нормально - с использованием библиотеки python aes. Итак, получив версию на Python, я смог сравнить длину полученного cipherText, который составляет 32 байта и представляет собой массив байтов. 15 байт - заполнение. Я очень ценю помощь.
Option 1
byte[] messageBuffer = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = encryptionKey; //used by device to encrypt. encryptionKey is a 16 byte array
aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
//aesAlg.Padding = PaddingMode.PKCS7; // this makes no difference
byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
try
{
messageBuffer = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length); //****fails here ********************
}
catch (Exception ex)
{
....;
}
}
Option 2
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = encryptionKey; //used by device to encrypt. encryptionKey is a 16 byte array
aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
//aesAlg.Padding = PaddingMode.PKCS7; // this makes no difference
byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
try
{
var zx = csDecrypt.Read(messageBuffer, 0, cipherText.Length); //****fails here ********************
}
catch (Exception ex)
{
....;
}
}
}
}
Option 3
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = encryptionKey; //used by device to encrypt. encryptionKey is a 16 byte array
aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
//aesAlg.Padding = PaddingMode.PKCS7; // this makes no difference
byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (var msDecrypt = new MemoryStream(cipherText))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
try
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
var pt = srDecrypt.ReadToEnd(); //****fails here ********************
messageBuffer = Utils.GetBytes(pt); //convert to bytes
}
catch (Exception ex)
{
....;
}
}
}
}
}
2 ответа
Ошибки заполнения ожидаются для всего, где был поврежден ключ или сообщение. Для небольших сообщений размером меньше одного блока также может быть некорректная обработка IV. Поскольку устройство, похоже, использует C #, это наиболее вероятная причина.
Гораздо менее вероятно, но возможно, что используется заполнение ISO 10126. Сообщения с дополнением PKCS # 7 могут быть отменены с помощью процедуры отмены дополнения ISO 10126. Однако обратное неверно, поскольку PKCS # 7 полагается на правильность всех значений в заполнении, а не только на последнее. В заполнении ISO 10126 только последний байт указывает количество используемых байтов заполнения; остальные байты могут иметь любое значение.
Вы, конечно, всегда можете посмотреть сами. Просто укажите «без заполнения» и распечатайте сообщение в шестнадцатеричном формате. Если сообщение является полным мусором, либо сообщение, либо, что более вероятно, неверный ключ. Если все в порядке, значит, вы сможете отличить метод заполнения от последних байтов; в статье Википедии о заполнении перечислены все распространенные схемы.
Я решил эту проблему очень просто, в подпрограмме дешифрования, явно установив для режима заполнения значение none:
aesAlg.Padding = PaddingMode.None;
В исходных подпрограммах Python режим заполнения не использовался. Я предположил, что неправильно, если не указать режим заполнения, режим заполнения будет отсутствовать. (Если вам интересно, подпрограммы encrytpion были написаны только на python. Подпрограммы расшифровки были написаны на Python и C #)
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.