Как мне перевести эту функцию шифрования C# на Java?
Мне нужно перевести приведенные ниже коды C# на Java, однако я не смог найти ни одного Java-эквивалента Rfc2898DerivedBytes и Rijndael из C#.
private static string Encrypt(string sData, string sEncryptionKey)
{
string str = null;
string str2;
try
{
Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(sEncryptionKey, 8);
Rijndael rijndael = Rijndael.Create();
rijndael.IV = bytes.GetBytes(rijndael.BlockSize / 8);
rijndael.Key = bytes.GetBytes(rijndael.KeySize / 8);
byte[] buffer = Encoding.Unicode.GetBytes(sData);
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
{
stream.Write(bytes.Salt, 0, bytes.Salt.Length);
stream2.Write(buffer, 0, buffer.Length);
stream2.Close();
str = Convert.ToBase64String(stream.ToArray());
str2 = str;
}
}
}
catch (Exception exception)
{
System.out.println(exception.getMessage());
}
return str2;
}
[Обновить]
Мне нужно использовать эту функцию для шифрования пароля для нового созданного пользователя, и зашифрованный пароль также должен быть правильно расшифрован другим пользователем, в том числе C#.
Я следую за документами, которые перечислены в комментариях и ответах, и стараюсь написать ниже просто образец для быстрой проверки.
public class testEncrypt {
public static void main(String[] args) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
char[] password = "passkey".toCharArray();
SecureRandom random = new SecureRandom();
byte[] salt = new byte[8];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec(password, salt, 1000, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal("301a7fed-54e4-4ae2-9b4d-6db057f75c91".getBytes("UTF-8"));
System.out.println(ciphertext.length);
}
}
Тем не менее, длина зашифрованного текста составляет 48, но на самом деле в C# это выглядит как этот формат
WHUNV5xrsfETEiCwcT0M731+Ak1jibsWEodJSaBraP1cmmkS1TpGWqwt/6p/a7oy8Yq30ImZPbFF+Y0JNLa3Eu2UGuazZtuhEepUIIdaDEtA2FO0JYIj2A==
всего 120 символов.
Что-то не так с кодом?
1 ответ
RFC2898 является официальным названием для PBKDF2 (функция определения ключа на основе пароля).
Этот вопрос, кажется, использует SecretKeyFactory
класс для PBKDF2.
Проверка пароля с помощью PBKDF2 в Java
Если вы не можете найти какую-либо реализацию, которая вас устраивает, я предлагаю вам взглянуть на мой вопрос, где я использовал несколько классов из BouncyCastle (для C#, но должен работать для Java) и создал алгоритм. Я должен был создать это для C#, потому что не было Rfc2898DeriveBytes
для.NET Compact Framework.
Этот вопрос, безусловно, тоже должен вам помочь!
Здесь вы также можете найти реализацию, которая была сделана кем-то, кто натолкнулся на вашу проблему.
Также, чтобы ответить на вторую часть вашего вопроса,
Рейндаэль не сильно отличается от AES. Цитировать эту веб-страницу
А именно, Rijndael позволяет выбирать размер ключа и блока независимо от набора { 128, 160, 192, 224, 256 } битов. (И размер ключа на самом деле не должен соответствовать размеру блока). Однако FIPS-197 указывает, что размер блока всегда должен быть 128 бит в AES, и что размер ключа может быть 128, 192 или 256 бит.
Алгоритм Rijndael был выбран NIST в качестве алгоритма расширенного шифрования.
Таким образом, вы можете использовать алгоритм AES в Java.