1) Часть Java-дешифрования задается как
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(KEY.toCharArray(), SALT.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
return new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt.getBytes("UTF-8"))));
, где strToDecrypt
- это зашифрованные данные в кодировке Base64 (заданные возвращаемым значением части шифрования), которые отклоняются от части шифрования только в двух последних строках.
Примечание: На практике IV следует генерировать случайным образом (например, Генерация случайного IV для AES в Java ). Но я предполагаю, что это понятно, и 0-последовательность предназначена только для тестирования.
2) Относительно получения ключа PBKDF2WithHmacSHA256
решение C # зависит от вашей версии .NET-фреймворка. Для V4.7.2 и выше ключ может быть получен с помощью:
// .NET Framework 4.7.2 +
byte[] secretKey = null;
using (Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(KEY, Encoding.UTF8.GetBytes(SALT), 65536, HashAlgorithmName.SHA256))
{
secretKey = rfc2898.GetBytes(32);
}
Примечание: В предыдущих реализациях (до v4.7.2) Rfc2898DeriveBytes
использовалось SHA1
(жестко запрограммировано) вместо SHA256
, и, таким образом, нет ctor, ожидающего 4 параметра. Более того, класс Rfc2898DeriveBytes
требует, чтобы длина соли составляла не менее 8 байтов, в противном случае выдается System.ArgumentException: Salt is not at least eight bytes
.
Альтернатива:
// .NET Framework 4.5 +
byte[] secretKey = null;
KeyDerivationPrf keyDerivationPrf = KeyDerivationPrf.HMACSHA256;
secretKey = KeyDerivation.Pbkdf2(KEY, Encoding.UTF8.GetBytes(SALT), keyDerivationPrf, 65536, 32);
Последний работает для V4.6.1 и выше, но вам нужен класс Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivation
, который
Вы можете найти, например, на https://www.nuget.org/packages/Microsoft.AspNetCore.Cryptography.KeyDerivation/. Для установки вы можете
используйте, например, Консоль диспетчера пакетов (Инструменты - Диспетчер пакетов NuGet - Консоль диспетчера пакетов). Просто введите соответствующую команду, как описано в ссылке.
Может быть, вы получите IDE-ошибку CS0012
. В этом случае вы должны добавить <Reference Include="netstandard" />
к ссылочному разделу вашего csproj
-файла (см. Также https://github.com/dotnet/standard/issues/542). KeyDerivationPrf
-класс не ограничивает длину соли.
Есть и другие возможности (например, Bouncy Castle), которые я не пробовал, но, возможно, они являются лучшими альтернативами для вас. Эта тема также обсуждается в Rfc2898 / PBKDF2 с SHA256 в качестве дайджеста в c # .
3) Пример метода C # -encryption:
public string Encrypt(string plainText)
{
// PBKDF2WithHmacSHA256 Key derivation
// ...
using (RijndaelManaged cipher = new RijndaelManaged())
{
cipher.Key = secretKey;
cipher.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cipher.Mode = CipherMode.CBC;
cipher.Padding = PaddingMode.PKCS7;
byte[] encryptedData;
using (ICryptoTransform encryptor = cipher.CreateEncryptor())
{
using (System.IO.MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(plainText);
}
encryptedData = memoryStream.ToArray();
}
}
}
return Convert.ToBase64String(encryptedData);
}
}
где plainText
- строка, содержащая ваш простой текст (соответствующий strToEncrypt
). Зашифрованные данные кодируются в base64 и возвращаются в виде строки (аналог вашего Java-метода).
Контрольный пример:
String KEY = "The Password";
String SALT = "The Salt";
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
дает
Plain text: This is a plain text that needs to be encrypted
Key (hex): 2D7664713D701C58FC506F93CEA3194671AD3B5C034255A4AC04AF46EADC89BC
Base64 encoded
encrypted data: ksUYjmbP9ga39LXr3wXQ34Bp32UlloYPxg3WWuW0iovWbg/GxHJrIuF3jrDvjr/Q
4) Пример метода C # -decryption:
public string Decrypt(string encryptedText)
{
// PBKDF2WithHmacSHA256 Key derivation
// ...
using (RijndaelManaged cipher = new RijndaelManaged())
{
cipher.Key = secretKey;
cipher.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cipher.Mode = CipherMode.CBC;
cipher.Padding = PaddingMode.PKCS7;
string decryptedText;
using (ICryptoTransform decryptor = cipher.CreateDecryptor())
{
using (System.IO.MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(encryptedText)))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader streamReader = new StreamReader(cryptoStream))
{
decryptedText = streamReader.ReadToEnd();
}
}
}
}
return decryptedText;
}
}
где encryptedText
- возвращаемое значение части шифрования (зашифрованные данные, которые закодированы в base64, соответствуют strToDecrypt
). Метод возвращает расшифрованный текст (аналог Java-метода).