-1

我需要将以下 C# 代码翻译成 Java,但是,我找不到任何与 C# 的 Rfc2898DerivedBytes 和 Rijndael 等效的 Java。

    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 个字符。

代码有问题吗?

4

1 回答 1

5

RFC2898 是 PBKDF2(Password Based Key Derivation Function)的正式名称。

这个问题似乎使用了SecretKeyFactoryPBKDF2 的类。

在 Java 中使用 PBKDF2 进行密码验证

如果你找不到任何你满意的实现,我建议你看看我的问题,我使用了 BouncyCastle 的一些类(用于 C#,但应该适用于 Java)并创建了算法。我不得不为 C# 创建这个,因为Rfc2898DeriveBytes.NET Compact Framework 没有。

这个问题肯定也对你有帮助!

您还可以在此处找到由偶然发现相同问题的人完成的实现。

还要回答你问题的第二部分,

Rijndael 与 AES 没有太大区别。引用此网页

也就是说,Rijndael 允许从 {128、160、192、224、256} 位的集合中独立选择密钥和块大小。(并且密钥大小实际上不必与块大小匹配)。但是,FIPS-197 指定块大小在 AES 中必须始终为 128 位,并且密钥大小可以是 128、192 或 256 位。

Rijndael 算法被 NIST 选为高级加密算法。

所以你可以在 Java 中使用 AES 算法

于 2012-07-28T04:38:04.740 回答