如何将此C#加密函数转换为Java?

SUT*_*SUT -1 java encryption rijndael cryptostream rfc2898

我需要将下面的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;

}
Run Code Online (Sandbox Code Playgroud)

[更新]

我需要使用此函数来加密新创建的用户的密码,加密的密码也应该由其他调用者(包括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);

}
Run Code Online (Sandbox Code Playgroud)

}

但是,密文的长度是48,但实际上在C#中,它看起来像这种格式

WHUNV5xrsfETEiCwcT0M731 + Ak1jibsWEodJSaBraP1cmmkS1TpGWqwt/6P/a7oy8Yq30ImZPbFF + Y0JNLa3Eu2UGuazZtuhEepUIIdaDEtA2FO0JYIj2A ==

共120个字符.

代码有问题吗?

Ran*_*ray 5

RFC2898是PBKDF2(基于密码的密钥派生函数)的正式名称.

这个问题似乎使用了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位.

NIST选择Rijndael算法作为高级加密算法.

因此,您可以在Java中使用AES算法.

  • 如果这听起来很粗鲁,我很抱歉,如果您对此没有全面的了解,请不要尝试构建加密系统.如果您正在处理敏感的客户信息,请花费大量的精力和时间来学习什么是加密算法,什么是IV,什么是块大小,为什么使用PBKDF2等.无论如何,首先测试是否`Rfc2898DeriveBytes`工作正常.此外,如果在Java中将IV限制为16,则必须使用128位的块大小.使用您提出的当前代码以及您面临的任何问题更新您的答案. (2认同)