Both codes use different AES variants and paddings. The mcrypt code applies AES-128 and Zero padding, the openssl code AES-256 and PKCS7 padding. To make sure that both ciphertexts match, both codes must use the same AES variant and padding.
mcrypt identifies the AES variant from the key size. Since $key is a 16 bytes key, AES-128 is used. openssl determines the AES variant based on the specification passed in the 2nd parameter. Keys that are too short are padded with 0 values to the required length, keys that are too long are truncated. Here, AES-256-CBC is specified, i. e. AES-256 is used. The 16 bytes key $key is therefore padded with 0 values and extended to a size of 32 bytes.
mcrypt implicitly uses Zero padding for encryption, which is not implicitly removed during decryption. PKCS7 padding is not supported. openssl implicitly applies PKCS7 padding for encryption, which is implicitly removed during decryption. Zero padding is not supported. If the openssl code should use Zero padding or the mcyrpt code PKCS7 padding, this must be implemented by yourself.
With regard to the migration from mcrypt to openssl, the openssl code is modified in the following to be functionally identical to the mcrypt code, i.e. AES-128 and Zero padding is used. With regard to the AES variant, only the specification AES-256-CBC must be changed to AES-128-CBC. Concerning padding, the default PKCS7 padding must be disabled using OPENSSL_ZERO_PADDING and Zero padding itself must be implemented (note that the OPENSSL_ZERO_PADDING flag only disables padding, but does not enable Zero padding; the name is badly chosen):
<?php
$str = "test";
$key = 'o6xSYYAVl2eapPI2';
$iv = 'fedcba9876543210';
function encrypt_openssl($str = NULL, $key, $iv) {
$encrypted = openssl_encrypt(
zeroPad($str, 16), // Zero pad plaintext
'AES-128-CBC', // Choose AES-128
$key,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, // Disable PKCS7 Padding
$iv);
return bin2hex(@$encrypted);
}
function zeroPad($text, $bs) {
$pad = $bs - strlen($text) % $bs;
return ($pad < 16) ? $text . str_repeat("\0", $pad) : $text;
}
echo 'Openssl:'.encrypt_openssl($str,$key,$iv); // Openssl:57c86f3089535b3acfbe65cecbb662b9
For a comparison with your result, note that you have confused the labels of the outputs, i.e. the openssl result is labeled Mcrypt and vice versa!
A final note: In general, PKCS7 padding is more reliable than Zero padding, as the former contains the information of the padding length. This is not the case with Zero padding, so when removing the padding (i.e. after decryption) it is not possible to distinguish between regular and padding bytes. There are also different Zero padding variants, e.g. one does not pad if the length of the plaintext already corresponds to an integer multiple of the blocksize (this variant uses mcrypt), the other one pads with a complete block in this case.