0
votes

I have a reference of PHP code that does Rijndael encryption. I want convert it to java code, I tried few examples but none of them worked for me. Here is the php code:

$initialisationVector = hash("sha256", utf8_encode($myiv), TRUE);
$key = hash("sha256", utf8_encode($mykey), TRUE);
$encryptedValue = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$encryptKey, utf8_encode($mydata), MCRYPT_MODE_CBC, $initialisationVector));

Here is my java code that throws: Key length not 128/160/192/224/256 bits

public static String encrypt() throws Exception{
    String myiv = "somevalue";
    String mykey = "somevalue";
    String mydata = "somevalue";
    String new_text = "";

    RijndaelEngine rijndael = new RijndaelEngine(256);
    CBCBlockCipher cbc_rijndael = new CBCBlockCipher(rijndael);
    ZeroBytePadding c = new ZeroBytePadding();
    PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(cbc_rijndael, c);

    byte[] iv_byte = sha256(myiv);

    byte[] givenKey = sha256(mykey);

    CipherParameters keyWithIV = new ParametersWithIV(new KeyParameter(givenKey), iv_byte);

    pbbc.init(true, keyWithIV);
    byte[] plaintext = mydata.getBytes(Charset.forName("UTF-8"));
    byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)];
    int offset = 0;
    offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset);
    offset += pbbc.doFinal(ciphertext, offset);
    new_text = new String(new Base64().encode(ciphertext), Charset.forName("UTF-8"));
    System.out.println(new_text);
    return new_text;
}

public static byte[] sha256(String input) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    byte[] messageDigest = md.digest(input.getBytes(Charset.forName("UTF-8")));
    return messageDigest;
}

I am not really good with cryptography. Thanks in advance!

1
Your java sha256 method is very wrong. It should not return a hex string (which is also incorrectly generated), it should return byte[]. input.getBytes() should be input.getBytes(Charset.forName("UTF-8"))President James K. Polk
You need to debug. That means examining the values sent to and returned from the encryption function and verifying them. Also the question needs a minimal reproducible example complete with test values in and output in hex where appropriate.zaph
Updated sha256 function, now it throws Key length not 128/160/192/224/256 bitsmeet
sha256(appId) provides a 256-bit key, just use it. final int keysize = 256; byte[] keyData = new byte[keysize]; System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length)); are not needed.zaph
Looks like it generated the encryption, but it doesn't match with the one generated by PHP block, the one from Java code is also longer in length.meet

1 Answers

3
votes

The error message is clear: "initialisation vector must be the same length as block size". You are specifiying a 256-bit (32-byte) block size, verify that iv_byte is 32-bytes.

There are a few problems:

  1. For the IV get the bytes from the hash, pass the bytes to the encryption function, BigInteger has no place in that.

  2. sha256(appId) provides a 256-bit key, just use it.

The following are not needed, the result of sha256 is 256-bits:

final int keysize = 256;
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
  1. sha256(appId) provides a 256-bit key, just use it.

The following are not needed:

final int keysize = 256; 
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
  1. mcrypt "MCRYPT_RIJNDAEL_256" is specifying a 256-bit block size which means it is not AES, "MCRYPT_RIJNDAEL_128" is AES which should be used.

  2. mcrypt uses non-standard null padding, that needs to be accommodated.

  3. Using a SHA-256 hash is not sufficiently secure, use a password derivation function such as PBKDF2.