Плохая обивка PKCS7. Неверная длина 0. Python Шифрование до C# Расшифровка - PullRequest
1 голос
/ 12 февраля 2020

Я пытаюсь обмениваться данными между программой Xamarin / .Net / C# и программой python, используя AES CB C. Я могу зашифровать сообщение в. Net и успешно расшифровать это сообщение в python, но не наоборот. То есть, когда я сначала шифрую в python и пытаюсь расшифровать это сообщение в C#, я получаю исключение: «Плохое заполнение PKCS7. Недопустимая длина 0»

Вот мое шифрование python с использованием в Python:

salt = 16 * b'\0'
keyIV = PBKDF2(Config.SECRET, salt).read(48)
key = keyIV[:32]
iv = keyIV[-16:]
aes = AES.new(key, AES.MODE_CBC, iv)

# padding
length = 16 - (len(textToEncrypt) % 16)
print(len(textToEncrypt))
textToEncrypt += length * b'\0'
print(len(textToEncrypt))

encrypted = aes.encrypt(textToEncrypt)
encoded = base64.b64encode(encrypted)
return encoded

А вот расшифровка в C#:

if (textToDecrypt == null || textToDecrypt.Length == 0)
            return "";

        textToDecrypt = textToDecrypt.Replace(" ", "+");
        byte[] bytesToDecrypt = Convert.FromBase64String(textToDecrypt);
        string decryptedText;
        using (Aes aes = Aes.Create())
        {
            byte[] salt = new byte[16];
            Rfc2898DeriveBytes crypto = new Rfc2898DeriveBytes(Config.SECRET, salt);
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
            aes.Key = crypto.GetBytes(32);
            aes.IV = crypto.GetBytes(16);
            using (MemoryStream mStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cStream.Write(bytesToDecrypt, 0, bytesToDecrypt.Length);
                }
                decryptedText = Encoding.Unicode.GetString(mStream.ToArray());
            }
        }
        return decryptedText;

Ключ и iv совпадают между программами, но строка шифрования в python приходит намного короче, чем шифрование той же строки в C#. Спасибо за любую помощь.

1 Ответ

4 голосов
/ 13 февраля 2020
length = 16 - (len(textToEncrypt) % 16)
textToEncrypt += length * b'\0'

Это не то, как работает заполнение PKCS7.

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

PKCS7 делает это, заполняя байтами, значение которых равно количеству байтов заполнения. Таким образом, отступ будет одним из

01
02 02
03 03 03
04 04 04 04
...
16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16

. Почему отступ равен 16? Хорошо, если длина ваших данных точно кратна размеру блока (16 байт), и вы решили вообще не добавлять заполнение, тогда, когда вы пришли, чтобы удалить заполнение, вы можете обнаружить, что ваши данные закончились 01 или 02 02, et c, и вы удалите эти действительные байты данных, думая, что они дополняют. Поэтому в этом случае вам необходимо добавить полный блок заполнения.

Проблема с вашим кодом состоит в том, что он использует значение 00 для заполнения.


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

Я думаю, что вы, возможно, перепутали свои кодировки. Encoding.Unicode - это UTF16-LE, который использует 2 байта на символ. Было бы очень необычно использовать это из Python: более вероятно, что вы используете что-то вроде UTF-8, который использует 1 байт на символ для обычных западных символов. Трудно сказать наверняка, не зная, как вы превращаете вашу строку Python в строку байтов.


В AES IV должен быть random непредсказуемый (может быть опубликован c, но он не должен совпадать с предыдущим, зашифрованным вами). Обычно его генерируют случайным образом, а затем добавляют в начало вашего зашифрованного текста. Не извлекайте его из своего ключа.

...