Как мне перевести эту функцию шифрования 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.

Другие вопросы по тегам