0

I have encrypted the string in PHP using AES-256-ECB.

$sString   = "test"
$sEncryptionMethod = "AES-256-ECB";
$sEncryptionKey = "mysecretkey";

openssl_encrypt($sString, $sEncryptionMethod, $sEncryptionKey)

I would like to decrypt the same using Java/Scala?

 String secret = "mysecretkey";
 SecretKeySpec skeySpec = new SecretKeySpec(encKey.getBytes("UTF-8"), "AES");
 byte[] decodedValue = Base64.getDecoder.decode(token);

 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
 int decryptMode = Cipher.DECRYPT_MODE;
 cipher.init(decryptMode, skeySpec);
 new String(cipher.doFinal(decodedValue));

I am seeing the following error? how can we decrypt the same using Java? Note: (decryption in PHP is working as expected) but I want to do this in Java

Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
vkt
  • 1,401
  • 2
  • 20
  • 46
  • Does this answer your question? [Given final block not properly padded](https://stackoverflow.com/questions/8049872/given-final-block-not-properly-padded) – Spectric Oct 05 '20 at 03:08
  • no, I can not change the existing algorithm. – vkt Oct 05 '20 at 03:14

1 Answers1

6

The key has to be exactly 256 bit long. Clearly the PHP side is doing some unspecified magic voodoo to "mysecretkey" to obtain a 256 bit key. Java does not, as a rule, engage in 'the user does not appear to know what they are doing, eh, I'll take a wild stab in the dark', like PHP does, which is the problem here.

Figure out how "mysecretkey" is turned into a 256-bit key, and replicate that in java.

NB: ECB is extremely insecure. It sounds like you don't know enough about encryption to have any hope of producing an application that is actually hard to trivially break.

NB2: Note that the PHP documentation itself strongly suggests that 'key' should be some cryptographically derived secure source of 256 bits. The fact that openssl_encrypt actually gives you an answer when you provide a broken key is somewhat eyebrow raising. See the various comments at the PHP manual on openssl_encrypt which clearly highlight some weirdness is going on there but none are clear enough to actually explain what PHP is doing here.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Thanks for the explanation, I don't know much about PHP and my trying to decode as the original encryption is done on PHP side. – vkt Oct 05 '20 at 04:21
  • 1
    You cannot blame this one on PHP. [It's openssl that pads the key with zeros](https://stackoverflow.com/questions/39908767/openssl-pads-keys-in-aes-encryption). I suppose the authors of the openssl extension missed the opportunity to offer a sane API for a library that's hard to use correctly, but still. – Peter Oct 05 '20 at 05:33
  • 1
    "the PHP side is doing some unspecified magic voodoo" - PHP is doing NO magic but simply fills up a key with (hex) x00's to the desired length. When using AES-256 OPENSSL needs a key of 256/8 = 32 bytes length. As "mysecretkey" is 11 byte long simply add 32-11 = 21 x00's to the key on Java side and the decryption will work. **Security warning** do not use **UNSECURE** ECB-mode. – Michael Fehr Oct 05 '20 at 06:25
  • 1
    @MichaelFehr - True, but padding with 0-values (just like cutting off too long keys) is some kind of magic (though a simple one): Invalid keys are _silently_ converted into valid keys using _arbitrary_ rules. – Topaco Oct 05 '20 at 07:45
  • So the remedy is simply to use `$sEncryptionKey = "mysecretkey\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"` so that it has a length of 32 bytes ? – Henno Brandsma Oct 05 '20 at 08:06
  • Well, apparently PHP will take care of that for you; you'd have to add those zeroes on the java side, it's not needed on the PHP side, but a great idea to make the code more self-documenting. So.. `String pass = "mysecretkey\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";` (32 chars, so 21 zeroes). – rzwitserloot Oct 05 '20 at 13:49