javaphpencryptionbouncycastlerijndael

What is the decryption key for java when key is integer in php


There is an existing PHP system (developed by another company) which have encryption code as follows.

$mopen = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', 'cfb', '');
mcrypt_generic_init($mopen, keygenerator(), $iv);
$cipherText = mcrypt_generic($mopen, $imageContent);

In the above code, the second line, the second parameter is the key."keygenerator()"return type is int between 10-99.

mcrypt_generic_init ( resource $td , string $key , string $iv ) : int

I have to decrypt the resulting files using java. I'm using bouncycastle library and I have to give the key as a byte array. If "keygenerator()" generate 32 as key .how can I give it in java as a hard-coded value. If I use the following code.

String key = "32";
cipher.init(cryptoType, new ParametersWithIV(new KeyParameter(key.getBytes()), iv.trim().getBytes()));

It gives me following error.

Exception in thread "main" java.lang.IllegalArgumentException: Key length not 128/160/192/224/256 bits.


Solution

  • MCRYPT_RIJNDAEL_256 supports 16, 24 and 32 bytes keys. If the key size is in between, padding is done with 0-values until the next valid key length is reached.
    If the key length is a two digits number, the next valid key size is 16 bytes, therefore padding is done with 14 0-values.
    The same applies to the IV, whose length must correspond to the block size (32 bytes for Rijndael-256). If it is shorter, it is also padded with 0-values (although a warning is usually displayed here).
    If the key is too long (longer than 32 bytes), it will be truncated. The same applies to the IV.

    The following PHP code demonstrates this:

    function encrypt($key, $iv){
        $mopen = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', 'cfb', '');
        mcrypt_generic_init($mopen, $key, $iv);
        $cipherText = mcrypt_generic($mopen, "The quick brown fox jumps over the lazy dog");
        print(base64_encode($cipherText) . "\n");
    }
    
    $key = 32; // 0-padded to 16 bytes
    $iv = 32;  // 0-padded to 32 bytes (Rijndael-256 blocksize), mostly a warning is displayed
    encrypt($key, $iv); // Dgfd2xT2NQ1ULob3mOX+JBPQo57JUIxabtt+TX8wnzYWhKtt/6ltY2Z/yA==
    
    $key = "32";
    $iv = "32";
    encrypt($key, $iv); // Dgfd2xT2NQ1ULob3mOX+JBPQo57JUIxabtt+TX8wnzYWhKtt/6ltY2Z/yA==
    
    $key = "32\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    $iv = "32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    encrypt($key, $iv); // Dgfd2xT2NQ1ULob3mOX+JBPQo57JUIxabtt+TX8wnzYWhKtt/6ltY2Z/yA==
    

    In the Java code the exact key and IV size must be specified. Note that CFB is a stream cipher mode, so no padding is used. PHP applies CFB-8 (CFB in 8-bit mode), which must be specified in the Java code accordingly. The following Java/BouncyCastle code decrypts the ciphertext:

    import org.bouncycastle.crypto.BufferedBlockCipher;
    import org.bouncycastle.crypto.CipherParameters;
    import org.bouncycastle.crypto.engines.RijndaelEngine;
    import org.bouncycastle.crypto.modes.CFBBlockCipher;
    import org.bouncycastle.crypto.params.KeyParameter;
    import org.bouncycastle.crypto.params.ParametersWithIV;
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    ...
    String ciphertextB64 = "Dgfd2xT2NQ1ULob3mOX+JBPQo57JUIxabtt+TX8wnzYWhKtt/6ltY2Z/yA==";
    byte[] ciphertext = Base64.getDecoder().decode(ciphertextB64);
    byte[] key = "32\0\0\0\0\0\0\0\0\0\0\0\0\0\0".getBytes(StandardCharsets.UTF_8);         
    byte[] iv = "32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0".getBytes(StandardCharsets.UTF_8);     
    
    BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(new CFBBlockCipher(new RijndaelEngine(256), 8)); // CFB in 8 bit mode
    CipherParameters cipherParams = new ParametersWithIV(new KeyParameter(key), iv);
    bufferedBlockCipher.init(false, cipherParams);        
    
    byte[] decryptedBuffer = new byte[bufferedBlockCipher.getOutputSize(ciphertext.length)];
    int processed = bufferedBlockCipher.processBytes(ciphertext, 0, ciphertext.length, decryptedBuffer, 0);
    processed += bufferedBlockCipher.doFinal(decryptedBuffer, processed);
    
    System.out.println(new String(decryptedBuffer, 0, processed, StandardCharsets.UTF_8)); // The quick brown fox jumps over the lazy dog