title: How can JAVA decrypt data which was base64 encoded and RIJNDAEL_256 encryped by PHP?
body: <p>I need to migrate data from a PHP to a JAVA application.</p>
  
  <p>The data has been encrypted using this <strong>PHP</strong> function:</p>
  
  <pre><code>function encrypt($text, $encryptionKey) {
    return utf8_encode(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $encryptionKey, $text, MCRYPT_MODE_CBC, "\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\0\0")));
  }
  </code></pre>
  
  <p>... and it can be decrypted successfully using this function:</p>
  
  <pre><code>function decrypt($text, $encryptionKey) {
    return utf8_decode(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $encryptionKey, base64_decode($text), MCRYPT_MODE_CBC, "\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\0\0")));
  }
  </code></pre>
  
  <p>It is stored in MySql-InnoDB with <code>collation=latin1_swedish_ci</code> in a table with <code>charset=utf8</code> in a VARCHAR(255) column.</p>
  
  <hr>
  
  <p>In <strong>JAVA</strong> the data is retrieved through a JPA-repository using Hibernate and then presented to this
  method based on <a href="https://stackoverflow.com/questions/57965316/rijndael-256-encryption-with-java-bouncy-castle">Rijndael 256 encryption with Java &amp; Bouncy Castle
  </a>:</p>
  
  <pre><code>protected String decryptRijndael256_(String encryptedBase64Text) {
    byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64Text.getBytes(StandardCharsets.UTF_8));
    byte[] key = encryptionKey.getBytes(StandardCharsets.UTF_8);
  
    RijndaelEngine rijndaelEngine = new RijndaelEngine(256);
    KeyParameter keyParam = new KeyParameter(key);
    rijndaelEngine.init(false, keyParam);
    PaddedBufferedBlockCipher bufferedBlock = new PaddedBufferedBlockCipher(rijndaelEngine, new ZeroBytePadding());
  
    byte[] decryptedBytes = new byte[bufferedBlock.getOutputSize(encryptedBytes.length)];
    int processed = bufferedBlock.processBytes(encryptedBytes, 0, encryptedBytes.length, decryptedBytes, 0);
    processed += bufferedBlock.doFinal(decryptedBytes, processed);
    decryptedBytes = Arrays.copyOfRange(decryptedBytes, 0, processed);
  
    return new String(decryptedBytes, StandardCharsets.UTF_8);
  }
  </code></pre>
  
  <p>While this works in most cases where the encrypted text looks like this:</p>
  
  <p><code>5VTv/x2f41Aj2iES7B9lRUi8Q9gH3MYnSR3xc4X1di4=</code> => <code>account.name@gmail.com</code></p>
  
  <p>... it fails if the text is long and looks like this:</p>
  
  <p><code>p77KGdWlexQXLGPZzkAqk2OK6oC9r7TDfMfaDhofu0et7RaPcA0hUCq0mBnY4oakjZpIrBeMadwhYonVKwJlGw==</code> => <code>very.long.account.name@gmail.c���ե{.c��@*�c�ꀽ���|���G</code></p>
  
  <hr>
  
  <p>So it is mostly decoded correctly, but the last block seems to be the problem. I suspect the problem lies either with character encoding or with the <code>MCRYPT_MODE_CBC</code> and its IV (\0\0...). </p>
  
  <p>I have not found any way to add the mode and IV to the java implementation.</p>
  
  <p>As for the Base64 encryption. I tried about any possible method from <code>java.util.Base64</code>, <code>org.apache.commons.codec.binary.Base64</code> and <code>org.bouncycastle.util.encoders.Base64</code>. </p>
  
  <p>The result is either as above or:</p>
  
  <pre><code>org.bouncycastle.crypto.DataLengthException: last block incomplete in decryption
      at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.doFinal(Unknown Source)
  </code></pre>
  
  <p>My guess is that the problem has to do with how PHP does the padding.</p>
  
  <hr>
  
  <p><strong>Question:</strong></p>
  
  <p>What is so different between how PHP and JAVA handle this decryption? How can I decode all values correctly?</p>
  
  <hr>
  
  <p>(PHP: 5.6.40, JAVA: 11.0.7_10 Amazon Corretto)</p>