Question

I need to translate the below C# codes into Java, however, I could not find any Java equivalent to the Rfc2898DerivedBytes and Rijndael of 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;

}

[Update]

I need to use this function to encrypt the password for new created user, and the encrypted password should also be correctly decrypted by other invoker including C#.

I follow the documents which list in the comments and answer, and try to write below simply sample for quickly verification.

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);

}

}

However, the length of the ciphertext is 48, but actually in C#, it looks like this format

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

total 120 characters.

Is there something wrong with the code?

Was it helpful?

Solution

RFC2898 is the official name for PBKDF2 (Password Based Key Derivation Function).

This question seems to use the SecretKeyFactory class for PBKDF2.

Password Verification with PBKDF2 in Java

If you cannot find any implementation that you are satisfied with, I suggest you take a look at my question where I used a few classes from BouncyCastle (for C#, but should work for Java) and created the algorithm. I had to create this for C# because there was no Rfc2898DeriveBytes for the .NET Compact Framework.

This question should definitely help you too!

You can also find an implementation here that was done by someone who stumbled across your same problem.

Also to answer the second part of your question,

Rijndael doesn't differ much from AES. To quote this webpage

Namely, Rijndael allows for both key and block sizes to be chosen independently from the set of { 128, 160, 192, 224, 256 } bits. (And the key size does not in fact have to match the block size). However, FIPS-197 specifies that the block size must always be 128 bits in AES, and that the key size may be either 128, 192, or 256 bits.

Rijndael algorithm was chosen by the NIST to be the Advanced Encryption algorithm.

So you can use the AES algorithm in Java.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top