Я пытаюсь расшифровать строку, зашифрованную в C# (.Net), используя тот же ключ, но получаю Excpetion, как показано ниже.
Код C#
//Decrypting a string
String key = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//Encrypting a string
public static string passwordEncrypt(string inText, string key)
{
byte[] bytesBuff = Encoding.Unicode.GetBytes(inText);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes crypto = new Rfc2898DeriveBytes(key, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
aes.Key = crypto.GetBytes(32);
aes.IV = crypto.GetBytes(16);
using (MemoryStream mStream = new MemoryStream())
{
using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cStream.Write(bytesBuff, 0, bytesBuff.Length);
cStream.Close();
}
inText = Convert.ToBase64String(mStream.ToArray());
}
}
return inText;
}
Код Java
final static String key = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final static byte[] ivBytes = new byte[] { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
public static String decryptData(String base64Text) {
String plainText = "";
try {
byte[] keyBytes = key.getBytes("UTF-8");
try {
// byte[] cipherData = decrypt(ivBytes, keyBytes,
// Base64.decode(base64Text.getBytes("UTF-8"), Base64.DEFAULT));
byte[] cipherData = decrypt(ivBytes, keyBytes,
Base64.getDecoder().decode(base64Text.getBytes("UTF-8")));
plainText = new String(cipherData, "UTF-8");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return plainText;
}
Я получаю исключение:
java.security.InvalidKeyException: Invalid AES key length: 36 bytes
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:87)
at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:95)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:591)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:346)
at javax.crypto.Cipher.implInit(Cipher.java:809)
at javax.crypto.Cipher.chooseProvider(Cipher.java:867)
at javax.crypto.Cipher.init(Cipher.java:1399)
at javax.crypto.Cipher.init(Cipher.java:1330)
at com.trinity.report.loginAuth.AES256Cipher.encrypt(AES256Cipher.java:27)
at com.trinity.report.loginAuth.AES256Cipher.encryptData(AES256Cipher.java:52)
at com.trinity.report.loginAuth.AES256Cipher.main(AES256Cipher.java:107)
Тот же ключ используется для шифрования.
Sample Key: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
Encrypted String: zSdnqGp9B1BjMsvzvAeYvEidAgUrI%2ByrOGf%2BGVn9tzo%3D
Plain Text: testthree
Пожалуйста помоги. Заранее спасибо.
В коде .NET вы берете свой ключ и преобразуете его через Rfc2898DeriveBytes
, чтобы получить ключ (32 байта) и IV. Но в коде Java вы используете свой ключ и iV напрямую (а первый имеет неправильную длину). Начните без Rfc2898DeriveBytes
, просто установите фиксированный ключ нужной длины в обоих случаях.
В отношении кода C# (который отличается от кода расшифровки Java): установка значения IV, полученного из пароля, не кажется хорошей идеей, поскольку оно будет одинаковым каждый раз для одного и того же пароля. См. Комментарий к AES-CBC с возобновленным IV здесь.
Rfc2898DeriveBytes
реализует PBKDF2, используя HMACSHA1 по умолчанию. В Java это соответствует PBKDF2WithHmacSHA1
, см. здесь. При этом ключ и IV должны быть производными от пароля (key
) и соли (0x49, 0x76 ...). Обратите внимание, что статическая соль (как в коде C#) небезопасна.
Ну, AES поддерживает 128, 192 и 256-битные ключи, который составляет 16, 24 или 32 байта. Ваш ключ имеет длину 36 байтов, поэтому он недействителен. Цитата из введения Технические характеристики: «Этот стандарт определяет алгоритм Rijndael, симметричный блочный шифр, который может обрабатывать блоки данных длиной 128 бит, с использованием ключей шифрования длиной 128, 192 и 256 бит.» (выделено мной)