Bad PKCS7 Ошибка заполнения: неверная длина 106
Я пытаюсь зашифровать и расшифровать с помощью следующих функций, однако это приводит к ошибке ошибочного заполнения.
Если я установлю PaddingMode
в None
он возвращает некоторые альфа-символы и случайные символы в журнале.
Возможно, я что-то упускаю из-за установки правильной структуры, которая выглядит следующим образом:
- Шифр Рейндаэль (AES)
- Размер блока 128 бит (16 байт)
- Клавиша режима CBC (цепочка блоков шифрования)
- MD5 хэш-пароль
- IV То же, что и ключ
- Кодировка данных Base64 символов
- Кодировка UTF-8
Любая помощь в исправлении этой ошибки и любая помощь в обеспечении вышеуказанной структуры будет принята с благодарностью! Спасибо
ошибка
CryptographicException: Bad PKCS7 padding. Invalid length 106.
Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:363)
Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:515)
Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/Mono.Security.Cryptography/SymmetricTransform.cs:554)
System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Security.Cryptography/RijndaelManagedTransform.cs:94)
APIConnector.Decrypt (System.String toDecrypt) (at Assets/APIConnector.cs:85)
Мой код
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using System.IO;
public class APIConnector : MonoBehaviour {
// Use this for initialization
void Start () {
Debug.Log ("Starting API connector");
}
// Update is called once per frame
void Update () {
}
static string data;
string firstName="";
string password="";
void OnGUI() {
firstName = GUILayout.TextField (firstName, GUILayout.Width(300));
password = GUILayout.TextField (password, GUILayout.Width(300));
if (GUILayout.Button ("Submit"))
submit ();
}
//Our functions
void submit(){
Debug.Log ("Name is: " + firstName + " encrypted is: " + Encrypt(firstName));
Debug.Log ("Name is: " + firstName + " decrypted is: " + Decrypt(firstName));
}
public static string Encrypt (string toEncrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes ("SecretPassphrase");
// 256-AES key
int numBytes = System.Text.Encoding.UTF8.GetBytes(toEncrypt).Length;
Debug.Log ("Bytes: " + numBytes);
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes (toEncrypt);
RijndaelManaged rDel = new RijndaelManaged ();
rDel.Key = keyArray;
rDel.BlockSize = 128;
rDel.Mode = CipherMode.CBC;
// http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx
rDel.Padding = PaddingMode.PKCS7;
// better lang support
ICryptoTransform cTransform = rDel.CreateEncryptor ();
byte[] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String (resultArray, 0, resultArray.Length);
}
public static string Decrypt (string toDecrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes ("SecretPassphrase");
// AES-256 key
byte[] encryptedData = System.Convert.FromBase64String(toDecrypt);
//byte[] toEncryptArray = Convert.FromBase64String (toDecrypt);
RijndaelManaged rDel = new RijndaelManaged ();
rDel.Key = keyArray;
rDel.BlockSize = 128;
rDel.Mode = CipherMode.CBC;
rDel.IV = rDel.Key;
// http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx
rDel.Padding = PaddingMode.PKCS7;
// better lang support
ICryptoTransform cTransform = rDel.CreateDecryptor ();
byte[] resultArray = cTransform.TransformFinalBlock (encryptedData, 0, encryptedData.Length);
return UTF8Encoding.UTF8.GetString (resultArray);
}
}
1 ответ
Вы, кажется, не устанавливаете IV при шифровании, поэтому случайный IV будет использоваться автоматически. Поскольку вы устанавливаете IV при расшифровке (и он не будет таким же, как при шифровании), первый выходной блок будет поврежден. Если сообщение достаточно короткое (< 1 блок), заполнение также будет повреждено, что может привести к этой ошибке.
Как обычно, я отмечу, что среди других возможных проблем, использование того же IV в качестве ключа является плохой практикой, как и использование Encoding.UTF8.GetBytes()
для получения ключа.