2

I am trying to Use the Padding Mode: Zeros in AES-256-ECB encryption

but when i use OPENSSL_ZERO_PADDING it does not return anything.

this is the code :

$plaintext = "The quick brown fox jumps over the lazy dog";
$key = 'd61d2cd58d01b234e1800938erf8467k';
$chiperRaw = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_ZERO_PADDING);
$ciphertext = trim(base64_encode($chiperRaw));
echo($ciphertext);  

But when i use OPENSSL_RAW_DATA instead of OPENSSL_ZERO_PADDING it returns the encrypted string

Why isnt the OPENSSL_ZERO_PADDING working ? how can i fix this ?

Sam
  • 161
  • 1
  • 11
  • Seems that `openssl_encrypt` is returning false. Maybe worth checking https://stackoverflow.com/questions/41181905/mcrypt-encrypt-to-openssl-encrypt-and-openssl-zero-padding-problems – Nigel Ren Jul 04 '21 at 11:49
  • @NigelRen Does `$options=0` in `openssl_encrypt($plaintext, $cipher, $key, $options=0)` Means the padding mode will be Zeros? – Sam Jul 04 '21 at 12:01
  • Found something at https://www.php.net/manual/en/function.openssl-encrypt.php#117208 which might help explain it. – Nigel Ren Jul 04 '21 at 12:02

1 Answers1

1

What do you know, I'm Sam too!

It looks like OPENSSL_NO_PADDING won't work if the input data is not a multiple of the blocksize. You can fix this by padding the plaintext yourself:

$cipher = 'AES-256-ECB';

$key = 'd61d2cd58d01b234e1800938erf8467k';

$plaintext = "The quick brown fox jumps over the lazy dog";

if (strlen($plaintext) % 8) {
    $plaintext = str_pad($plaintext, strlen($plaintext) + 8 - strlen($plaintext) % 8, "\0");
}

$chiperRaw = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_NO_PADDING);

$ciphertext = trim(base64_encode($chiperRaw));

echo($ciphertext);

This will get your what you're looking for, but I think the best option for you (if you're not absolutely required to pad the string), is to use the 5th parameter of openssl_encrypt and pass an IV like the following (note the switch back to OPENSSL_RAW_DATA):

$cipher = 'AES-256-ECB';

$key = 'd61d2cd58d01b234e1800938erf8467k';

$iv_size = openssl_cipher_iv_length( $cipher );

$iv = openssl_random_pseudo_bytes( $iv_size );

$plaintext = "The quick brown fox jumps over the lazy dog";

$chiperRaw = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA, $iv);

$ciphertext = trim(base64_encode($chiperRaw));

echo($ciphertext);

There's great summary of why you should use an iv here: What is an openssl iv, and why do I need a key and an iv?

Samuel Cook
  • 16,620
  • 7
  • 50
  • 62
  • Actually i needed to have zero padding without $iv I will give option 1 a shot – Sam Jul 04 '21 at 12:09
  • 1
    A few small notes: 1. `OPENSSL_NO_PADDING` is defined for asymmetric encryption, `OPENSSL_ZERO_PADDING` for symmetric. Therefore `OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING` should be set in the 1st code snippet (in this example `OPENSSL_NO_PADDING` has the same effect though, but sets `OPENSSL_RAW_DATA` _silently_ and in general possibly unintentionally). 2. In the 1st code snippet it must be padded to the AES block size (i.e. 16 instead of 8 bytes). 3. ECB did not use an IV (which is why it is insecure). Therefore, in the 2nd code snippet, a different mode must be applied. – Topaco Jul 04 '21 at 17:09