Вы не показываете, как используете свой класс Encryptor
, поэтому ваш вопрос не включает Минимальный, Полный и Проверяемый пример . Мне удалось воспроизвести проблему с помощью следующего тестового жгута:
public static void Test()
{
var key = "my key";
var plainText = "hello";
var encryptor = new Encryptor();
encryptor.setDecryptedText(plainText);
encryptor.setKey(key);
var encrypted = encryptor.getEncrypted();
Console.WriteLine(encrypted);
var deecryptor = new Encryptor();
deecryptor.setEncryptedText(encrypted);
deecryptor.setKey(key);
var decrypted = deecryptor.getDecrypted();
Console.WriteLine(decrypted);
Assert.IsTrue(plainText == decrypted);
}
Демонстрационная скрипка # 1 здесь .
Учитывая, что в вашем коде есть 2 проблемы, обе из них на самом деле находятся в шифровании, а не в дешифровании.
Сначала , в Encrypt(string plainText, byte[] Key, byte[] IV)
вы пишете в StreamWriter sw
, затем очищаете CryptoStream
и возвращаете содержимое MemoryStream
- но вы никогда не очищаете и не удаляете sw
, поэтому его буферизованное содержимое никогда не пересылается в основной поток (ы).
Чтобы это исправить, ваш код должен выглядеть примерно так:
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(Encoding.UTF8.GetBytes(plainText));
}
}
encrypted = ms.ToArray();
}
Теперь getDecrypted()
больше не возвращает результат null
- вместо этого он возвращает неверный результат "System.Byte[]"
, как показано в демонстрационной скрипте # 2 здесь .
Во-вторых , снова в Encrypt(...)
, вы эффективно кодируете свой plainText
дважды в этой строке:
sw.Write(Encoding.UTF8.GetBytes(plainText));
Encoding.UTF8.GetBytes(plainText)
преобразует простой текст в байтовый массив, но StreamWriter
также предназначен для выполнения этой работы, преобразования строк в байты и передачи их в базовый поток. Таким образом, поскольку вы не передаете строку в Write()
, вызывается перегрузка StreamWriter.Write(Object)
:
Записывает текстовое представление объекта в текстовую строку или поток, вызывая метод ToString()
для этого объекта.
Таким образом, в действительности шифруется значение ToString()
байтового массива, равное "System.Byte[]"
.
Чтобы это исправить, просто удалите вызов Encoding.UTF8.GetBytes(plainText)
и напишите строку напрямую. Таким образом, ваш метод Encrypt()
должен выглядеть следующим образом:
static String Encrypt(string plainText, byte[] Key, byte[] IV)
{
string encrypted;
using (var aes = new RijndaelManaged())
{
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
aes.KeySize = 256;
ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write, true))
{
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
}
// Calling GetBuffer() avoids the extra allocation of ToArray().
encrypted = Convert.ToBase64String(ms.GetBuffer(), 0, checked((int)ms.Length));
}
aes.Clear();
}
return encrypted;
}
Демонстрационная скрипка # 3 здесь , которая теперь успешно проходит.
Отказ от ответственности: в этом ответе не предпринимается попытка проверить ваш код на предмет соответствия рекомендациям по безопасности, таким как безопасная установка соли и IV .