Я пытаюсь заменить PasswordDerivedBytes на Rfc2898DerivedBytes, но у меня проблема с последним при получении результата в кодировке Unicode.
Возьмем, к примеру, этот код:
[TestMethod]
public void DerivedBytesTest()
{
string encrypted = "y4Ijqo9Ga/mHlFbLHDdDUkYZlyu7CHF4PVXGLnb8by7FAVtCgPLhFSiA9Et6hDac";
string key = "{00B3403A-3C29-4f26-A9CC-14C411EA8547}";
string salt = "gT5M07XB9hHl3l1s";
string expected = "4552065703414505";
string decrypted;
decrypted = Decrypt(encrypted, key, salt, true);
Assert.IsTrue(decrypted == expected); // Works
decrypted = Decrypt(encrypted, key, salt, false);
Assert.IsTrue(decrypted == expected); // Doesn't work, get wrong unicode characters in 24 character string
}
private string Decrypt(string encrypted, string key, string salt, bool legacy = false)
{
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] encryptedDataBytes = Convert.FromBase64String(encrypted);
byte[] saltBytes = encoding.GetBytes(salt);
RijndaelManaged encryption = new RijndaelManaged();
DeriveBytes secretKey;
if (legacy)
{
secretKey = new PasswordDeriveBytes(key, saltBytes) {IterationCount = 100};
encryption.Padding = PaddingMode.PKCS7;
}
else
{
secretKey = new Rfc2898DeriveBytes(key, saltBytes, 100);
encryption.Padding = PaddingMode.Zeros; // This is the only one that doesn't throw the "Padding is invalid and cannot be removed" exception, but gives me a non-ASCII result
}
ICryptoTransform decryptor = encryption.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16));
string decryptedText = "";
using (MemoryStream memoryStream = new MemoryStream(encryptedDataBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] bytes = new byte[encryptedDataBytes.Length];
int decryptedCount = cryptoStream.Read(bytes, 0, bytes.Length);
decryptedText = encoding.GetString(bytes, 0, decryptedCount);
if (!legacy)
{
// Something more to do with result?
}
}
}
return decryptedText;
}
Интересно, может ли кто-нибудь посоветовать, где я ошибаюсь?
1 ответ
PasswordDeriveBytes
- это плохо реализованное расширение PBKDF1, а Rfc2898DeriveBytes
- реализация PBKDF2. Оба получают ключ из пароля, но это два разных алгоритма, и поэтому они получают два разных результата. Поскольку они используют криптографически безопасные хэши, нет возможности конвертировать один в другой.
Если вы можете сэкономить несколько байтов хранилища, вы все равно можете получить ключ с помощью PKBDF1, а затем зашифровать этот ключ, используя результат PBKDF2. Если размер вывода идентичен, вы даже можете использовать для этого шифрование XOR (одноразовый блокнот), но AES, конечно, также будет работать. Итак, расшифровка выглядит следующим образом: вычислить результат PBKDF2, расшифровать ключ данных, использовать ключ данных для расшифровки зашифрованного текста.
В противном случае вам придется расшифровать, а затем повторно зашифровать результат.
Если вы хотите сравнить результат дешифрования, сравните полученные байты ; не преобразуйте его сначала в строку. Настоятельно рекомендуется использовать аутентифицированное шифрование или MAC, чтобы вместо этого можно было проверить тег аутентификации. Простое игнорирование исключений заполнения с помощью использования Zero Padding - не лучший вариант. Эти ошибки заполнения возникают из-за неправильного ключа .
Общие примечания:
PasswordDeriveBytes
не следует использовать для любого количества байтов> 20 байтов, поскольку расширение Mickeysoft для PBKDF1 ужасно небезопасно, даже если байты повторяются в выходных данных (!). Если вы сделаете то же самое для PBKDF2, тогда любой противник должен будет сделать половину работы, которую вы должны сделать, так что это тоже не очень хорошая идея.Количество итераций в вопросе очень мало, но, как вы, кажется, используете очень случайный UID вместо пароля, который должен быть в порядке.
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.