I would like to improve a certain WordPress plugin that uses the now obsolete "mcrypt". Instead, I want to use the OpenSSL library to encrypt the submitted data, but during the encryption process I have problems, namely: the openssl_encrypt function returns a different value than mcrypt_encrypt, the system I am connected to does not return my data with the correct value, and Its owner cannot send me a log of the content I uploaded to it :(
I've searched the entire internet but haven't found a solution yet. I suspect the problem is with the padding, but I can't find a solution. can you help?
The following is the obvious change inside my PHP objects $password, $salt and $iv
class EncryptDebug{ private $algo = 'sha1'; private $password = 'ab4232goodcf423484422c90c3e4aa7c'; private $salt = 'ascastas54490a31'; private $iv = '8947da32awl55kwj' private $lenght = 16; private function generate_key(){ return hash_pbkdf2( $this->algo , $this->password , $this->salt, 100, $this->lenght, true ); } public function encryptSSL($plaintext){ $key = $this->generate_key(); $ciphertext = base64_encode(openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $this->iv)); return str_replace('+', '%2B', $ciphertext); } public function encryptMCRYPT($plaintext){ $key = $this->generate_key(); $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $this->iv)); return str_replace('+', '%2B', $ciphertext); } }
Forgot to mention: OPENSSL_ZERO_PADDING returns error. Using OPENSSL_RAW_DATA I can get similar results to mcrypt_encrypt but with a different ending, for example:
OpenSSL: rPzVvF7gaPMA4ADAjHUW8Wy1ThTJG+VPdcz5iKAkAwrDTTFTcOpWgWOCh9l9JFZ8WcNzMJ868026TkUxcYJMrQ==
MCRYPT:rPzVvF7gaPMA4ADAjHUW8Wy1ThTJG+VPdcz5iKAkAwrDTTFTcOpWgWOCh9l9JFZ8UGVfF091Q9bY61mTRg+BSg==
In
encryptSSL()
, Base64 encoding is currently used twice, once explicitly and once implicitly by default. Therefore, one of the Base64 encodings, whether explicit or implicit, must be removed. The former is achieved by removing thebase64_encode()
call, the latter is achieved by setting theOPENSSL_RAW_DATA
flag.Additionally, mcrypt uses zero padding and PHP/OpenSSL uses PKCS#7 padding. Therefore, in order for
encryptSSL()
to give the same results asencryptMCRYPT()
, zero padding must be used. Since PHP/OpenSSL does not support zero padding, PKCS#7 padding must be disabled (using the OPENSSL_ZERO_PADDING flag) and zero padding must be implemented explicitly>.overall:
and:
With these changes, both functions give the same results.
Note that zero padding is less reliable than PKCS#7 padding.
safety:
Please note that static IVs and static salts are bugs. Instead, both will be randomly generated and passed to the decryption party along with the ciphertext, usually in concatenation (neither is secret).
Also, the number of iterations of PBKDF2 of 100 is usually too small.