C# rijndael, преобразование набора символов вызывает проблемы
Я работаю над реализацией AES-256-CBC (показанной ниже), она будет использоваться в настройке клиент-база данных. Ключ хранится локально, и цель этой схемы состоит в том, чтобы сделать некоторые значения нечитаемыми, если утечка содержимого базы данных.
Поскольку IV имеет фиксированную длину, я планировал сделать зашифрованный текст зашифрованным сообщением с префиксом вектора инициализации (IV+C), а процедура дешифрования взять зашифрованный текст, отдельно сохранить IV и C и обработать C с помощью сохраненный вектор инициализации.
После нескольких неудачных попыток проверки этого метода я закомментировал часть шифрования, чтобы увидеть, что происходит. Оказывается, что либо IV, либо зашифрованный текст имеют неправильную длину, даже если эта длина фиксирована. Сначала я предположил, что вектор инициализации Rijndael с 16 байтами должен был помочь, поэтому я конвертировал все в UTF8, но он все еще не работает, как предполагалось. Хуже того: зашифрованный текст пропускает первый символ случайным образом (что для меня большая проблема, чем постоянная ошибка).
У меня нет идей, что мне здесь не хватает? (примечание: ящики сообщений предназначены для отладки)
public string Encrypt(string input)
{
string cipher = null;
RijndaelManaged Crypto = new RijndaelManaged();
Random r = new Random();
Crypto.KeySize = 256;
Crypto.BlockSize = 128;
Crypto.Mode = CipherMode.CBC;
Crypto.Padding = PaddingMode.PKCS7;
byte[] message = Encoding.UTF8.GetBytes(@input);
byte[] pubkey = Encoding.UTF8.GetBytes(@public_key.PadRight(16, '#').Substring(0, 16));
byte[] iv = new byte[16];
r.NextBytes(iv);
Crypto.Key = pubkey;
Crypto.IV = iv;
try
{
ICryptoTransform Encrypt = Crypto.CreateEncryptor();
cipher = @Encoding.UTF8.GetString(iv) + @Encoding.UTF8.GetString(message);//@Encoding.UTF8.GetString(iv) + @Encoding.UTF8.GetString(Encrypt.TransformFinalBlock(message, 0, message.Length));
if (debug)
MessageBox.Show("ENC\r\ninput (" + input.Length + "): " + @input + "\r\nmessage (" + message.Length + "): " + @System.Text.Encoding.UTF8.GetString(message) + "\r\npubkey (" + pubkey.Length + "):" + @System.Text.Encoding.UTF8.GetString(pubkey) + "\r\ninitialization vector (" + iv.Length + "): " + @System.Text.Encoding.UTF8.GetString(iv) + "\r\ncipher (" + cipher.Length + "): " + @cipher);
}
catch (CryptographicException e)
{
MessageBox.Show("ENC\r\ninput (" + input.Length + "): " + @input + "\r\nmessage (" + message.Length + "): " + @System.Text.Encoding.UTF8.GetString(message) + "\r\npubkey (" + pubkey.Length + "):" + @System.Text.Encoding.UTF8.GetString(pubkey) + "\r\ninitialization vector (" + iv.Length + "): " + @System.Text.Encoding.UTF8.GetString(iv) + "\r\ncipher (" + cipher.Length + "): " + @cipher + "\r\n\r\nException:\r\n" + e.ToString());
cipher = "ENCRYPTION ERROR";
}
return cipher;
}
public string Decrypt(string input)
{
string message = "";
byte[] iv = Encoding.UTF8.GetBytes(@input.Substring(0, 15)); // ლ(ಠ益ಠლ)
byte[] cipherdata = Encoding.UTF8.GetBytes(@input.Substring(16, input.Length - 16)); // ಥ‸ಥ
byte[] pubkey = Encoding.UTF8.GetBytes(public_key.PadRight(16, '#').Substring(0, 16));
RijndaelManaged Crypto = new RijndaelManaged();
Crypto.Key = pubkey;
Crypto.Mode = CipherMode.CBC;
Crypto.Padding = PaddingMode.PKCS7;
Crypto.KeySize = 256;
Crypto.BlockSize = 128;
try
{
ICryptoTransform Decrypt = Crypto.CreateDecryptor();
Decrypt.TransformFinalBlock(cipherdata, 0, cipherdata.Length);
message = System.Text.Encoding.UTF8.GetString(cipherdata);
if (debug)
MessageBox.Show("DEC\r\ninput (" + input.Length + "): " + @input + "\r\ncipherdata (" + cipherdata.Length + "): " + @Encoding.UTF8.GetString(cipherdata) + "\r\ninitialization vector (" + iv.Length + "): " + @Encoding.UTF8.GetString(iv) + "\r\npubkey (" + pubkey.Length + "): " + @Encoding.UTF8.GetString(pubkey) + "\r\nMessage (" + message.Length + "): " + message);
}
catch (CryptographicException e)
{
MessageBox.Show("DEC\r\ninput (" + input.Length + "): " + @input + "\r\ncipherdata (" + cipherdata.Length + "): " + @Encoding.UTF8.GetString(cipherdata) + "\r\ninitialization vector (" + iv.Length + "): " + @Encoding.UTF8.GetString(iv) + "\r\npubkey (" + pubkey.Length + "): " + @Encoding.UTF8.GetString(pubkey) + "\r\nMessage (" + message.Length + "): " + message + "\r\n\r\nException:\r\n" + e.ToString());
message = "DECRYPTION ERROR";
}
return message;
}
1 ответ
Конкатенация случайных байтовых последовательностей, как если бы они были строками, при использовании кодировки переменной длины, такой как UTF8, является плохой идеей.
Вы должны объединить байтовый массив IV и выходной буфер зашифрованного текста, чтобы создать байтовый массив, затем Convert.ToBase64String
создать переносимое строковое представление.