PHP Converting mcrypt to openssl - php

I know 3DES and MD5 are insecure. I will work on replacing them once I have it working again,
I have a mobile app that is using 3DES with an MD5 of a key as a SECRET KEY to talk to a PHP Application.
Now this code worked perfectly on PHP 5.3 (this is an example I have generated)
mcrypt_decrypt(
MCRYPT_3DES,
md5(
utf8_encode(
"MobileAppSecureKey"
),
true
),
base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI="),
MCRYPT_MODE_CBC,
base64_decode("cTOCJ/iYL18=")
)
Now I have ported it over to use OpenSSL method my new code is
openssl_decrypt(
base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI="),
'DES-EDE3-CBC',
md5(
utf8_encode(
"MobileAppSecureKey"
),
true
),
0,
base64_decode("cTOCJ/iYL18=")
)
But the new code does not work, It gives the error error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length from openssl_error_string()
I'm unsure why it's complaining about final block length when this worked perfectly in mcrypt
The code used to generate the test data was from the mobile the mobile app is a Cordova app and uses the CryptoJS library
key = CryptoJS.MD5(key);
// copy 3DES subkey 1 to the last 64 bit to make a full 192-bit key
key.words[4] = key.words[0];
key.words[5] = key.words[1];
if(typeof(iv) === "undefined"){
iv = CryptoJS.lib.WordArray.random(8);
}
var encrypted = CryptoJS.TripleDES.encrypt(pt, key, {iv: iv});
return {"str":encrypted.toString(), "iv":CryptoJS.enc.Base64.stringify(iv)};
The Encrypted payload was
{"jsonrpc":"2.0","method":"events.enableParentGenres","params":[159],"id":1}
Modifications that have been tried,
As per yivi suggestion, options have been set to OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
As per Tuckbros suggestion, the message has been padded
$message_padded = base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI=");
$message_padded = str_pad($message_padded,
strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");
Both of these prevented the error about final block length however the encrypted payload when running through the code did not decrypt.

The parameters you are passing in openssl_decrypt seem to be wrong; you are passing the OPTIONS parameter as 0, which you have to set to OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING because you provide the function with raw data (base64_decode).
The key also needs to be converted to a 192 bits key, as in the javascript code:
$key = md5(utf8_encode("MobileAppSecureKey"), true);
//key.words[4] = key.words[0];
//key.words[5] = key.words[1];
for($i = 0; $i < 8; $i++) {
$key[$i + 16] = $key[$i];
}
Try this one out:
$key = md5(utf8_encode("MobileAppSecureKey"), true);
$data = base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI=");
for($i = 0; $i < 8; $i++) {
$key[$i + 16] = $key[$i];
}
$decoded = openssl_decrypt(
$data,
'DES-EDE3-CBC',
$key,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
base64_decode("cTOCJ/iYL18=")
);
echo "\$decoded = {$decoded}";
// Will output:
// $decoded = {"jsonrpc":"2.0","method":"events.enableParentGenres","params":[159],"id":1}

Related

Sagepay integration without mcrypt

I am looking to integrate with Sagepay/Opayo Form using their guidance here:
https://www.sagepay.co.uk/file/25041/download-document/FORM_Integration_and_Protocol_Guidelines_270815.pdf?token=Cfj49hcaD4kpE0zk7179ZLOaQx2RH_3oatPOrAV6MyM
Sagepay have now stopped supporting SDKs which means I've had to find a 2013 utility set from here:
https://github.com/ammaar23/sagepay-sdk-php/blob/master/lib/classes/util.php
I am trying to migrate away from mcrypt towards openssl_encrypt but cannot seem to replicate the desired result.
There are 2 functions in play:
static protected function addPKCS5Padding($input)
{
$blockSize = 16;
$padd = "";
// Pad input to an even block size boundary.
$length = $blockSize - (strlen($input) % $blockSize);
for ($i = 1; $i <= $length; $i++)
{
$padd .= chr($length);
}
return $input . $padd;
}
static public function encryptAes($string, $key)
{
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = self::addPKCS5Padding($string);
// AH updated as mcrypt is now deprecated! 2020
$cipher = 'AES-128-CBC';
$ivsize = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivsize);
$crypt = openssl_encrypt($string,$cipher,$key,0,$iv);
// Perform hex encoding and return.
return "#" . strtoupper(bin2hex($crypt));
}
You can see my attempts to implement openssl_encrypt but it isn't working. The key is 55a51621a6648525 and the input string is VendorTxCode=TxCode-1310917599-223087284&Amount=36.95&Currency=GBP&Description=description&CustomerName=Fname Surname&CustomerEMail=customer#example.com&BillingSurname=Surname&BillingFirstnames=Fname&BillingAddress1=BillAddress Line 1&BillingCity=BillCity&BillingPostCode=W1A 1BL&BillingCountry=GB&BillingPhone=447933000000&DeliveryFirstnames=Fname&DeliverySurname=Surname&DeliveryAddress1=BillAddress Line 1&DeliveryCity=BillCity&DeliveryPostCode=W1A 1BL&DeliveryCountry=GB&DeliveryPhone=447933000000&SuccessURL=https://example.com/success&FailureURL=https://example.com/failure
and the output result is:
#2DCD27338114D4C39A14A855702FBAB2EF40BCAC2D76A3ABC0F660A07E9C1C921C2C755BA9B59C39F882FBF6DFED114F23141D94E50A01A665B1E31A86C07CA1CD1BB8EF5B6CF2C23D495CD 79F9C0F678D61773E7A1AA30AA5B23D56503FC0B52AC0694A8C341263D2C5FE1BAD93BDB94726761E155E900448F644AF1F67BE1AC77E852B9D90809A44F258EE9478B6D8C1C4ED58759263E7DBF 8871C6592287C0358F36F4EEC326CEDDD440DA2FED8AB35F1B630A5C6FA671E4D78CC8CACECF9DFDC31D6C5EC8270FB21E297E2C2E14F99A04223EFFD4F00062D440E78A3D2C7140EC8F123D24 7B75E7482AE98858DA34D37EDE6D7C69AA74391F559305CF675ADB3615244A107ABBB6AF26E29A2FFA059B12688D90FE09E0DE069325BFF3587A695F5DA36E4B809B69CC9A37034F166B63B5A62 B986F4DA34E9AC9516AFDE70642EC7DAD1AEBA93A1F347D6AC7046E967DCBFE7ACFCEE5DAFC0B29F1765032B3060EBE565CBD57D092075D15CF12725199C6881605B2E0F105698CE3ADD04361C A9D620C187B90E3F9849445B5C3C0FDF1768BFFD61F97E51316826F4F10E0E3E668F0A9F5ED9CCDA6F2C7CC957F12DB48F9041482E3D035E7A91852C404BFA325FED947E71F57B871DFAC6AF4FF2 9F4513A4A80B2D7ECC9D19D47ED04FA99CDFC881DFA771E1EA4F3F9B2C5AC673EF3DA2699A309CC8522993A63CB8D45D3CDF09B1DFDC573CD19679B250AD6721450B5042F201670B464505DCAE F59E2C67ABACC9AE2EEE793CE191FEBF66B8FAF4204EFFB359246B9C99FB52805C46375FF35140F74707FBC73C7731A28A2C883A
How can I create the desired output from my input code because the output I generate starts with: 403444324634333730363535313636373136413432363737353332363133303644373736
openssl_encrypt applies PKCS7 padding by default, so the addPKCS5Padding method is no longer needed.
In the mcrypt_encrypt code iv = key is used, so you must not generate a random IV for code equivalence.
In openssl_encrypt the flag OPENSSL_RAW_DATA must be applied as 4th parameter, otherwise the data will be returned Base64 encoded.
With these changes, the openssl_encrypt code produces the same result as the mcrypt_encrypt code:
<?php
function encryptAes($string, $key)
{
//$string = self::addPKCS5Padding($string); // don't pad explicitly
$cipher = 'AES-128-CBC';
//$ivsize = openssl_cipher_iv_length($cipher);
//$iv = openssl_random_pseudo_bytes($ivsize); // mcrypt_encrypt code: iv = key
$crypt = openssl_encrypt($string,$cipher,$key,OPENSSL_RAW_DATA,$key); // use raw data
return "#" . strtoupper(bin2hex($crypt));
}
$plain = "VendorTxCode=TxCode-1310917599-223087284&Amount=36.95&Currency=GBP&Description=description&CustomerName=Fname Surname&CustomerEMail=customer#example.com&BillingSurname=Surname&BillingFirstnames=Fname&BillingAddress1=BillAddress Line 1&BillingCity=BillCity&BillingPostCode=W1A 1BL&BillingCountry=GB&BillingPhone=447933000000&DeliveryFirstnames=Fname&DeliverySurname=Surname&DeliveryAddress1=BillAddress Line 1&DeliveryCity=BillCity&DeliveryPostCode=W1A 1BL&DeliveryCountry=GB&DeliveryPhone=447933000000&SuccessURL=https://example.com/success&FailureURL=https://example.com/failure";
$key = "55a51621a6648525";
print(encryptAes($plain, $key));
?>
For the choice iv = key note also the answers to this question.
#Topaco answered beautifully. Here is an additional bit, ( not related to the question ), while doing Sagepay integration you will need the decrypt function too for verifying payment/callback. Here is the function you can use.
function decrypytAES($string, $key) {
$cipher = 'AES-128-CBC';
$strIn = hex2bin(substr($strIn, 1));
return openssl_decrypt($strIn, $cipher, $key, OPENSSL_RAW_DATA, $key);
}

How to decrypt a string encrypted by SQL Server's EncryptByPassPhrase() in PHP?

I have an encrypted string and its key, which is created with SQL Server using "EncryptByPassPhrase", how can i decrypt it in PHP?
I have read the documentation of "EncryptByPassPhrase" which states that this is Triple DES encryption of 128 Length. I tried 3DES decryption of PHP but it is not returning the expected output.
Encryption in MS SQL is done with
declare #encrypt varbinary(200)
select #encrypt = EncryptByPassPhrase('key', 'taskseq=10000&amt=200.5' )
select #encrypt
I am decrypting it in PHP as following:
function decryptECB($encrypted, $key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
// decrypting
$stringText = mcrypt_decrypt(MCRYPT_3DES, $key, $encrypted,
MCRYPT_MODE_ECB, $iv);
return $stringText;
}
I took the liberty of translating this Stack Overflow answer into PHP.
This is the result:
<?php
// SQL Server's DecryptByPassphrase translated into PHP.
function decrypt(string $data, string $password): ?string {
// SQL Server <2017 uses SHA1 for the key and the DES-EDE-CBC crypto algorithm
// whereas SQL Server >= 2017 uses SHA256 and AES-256-CBC.
// Version 1 is the SHA1 + DES-EDE-CBC version, Version 2 is the AES-256-CBC version.
// Version is stored in the first four bytes as a little endian int32.
$version_bytes = substr($data, 0, 4);
$version = unpack('V', $version_bytes)[1];
// Password must be converted to the UTF-16LE encoding.
$passwordUtf16 = mb_convert_encoding($password, 'UTF-16LE');
if ($version === 1) {
// Key is hashed using SHA1, The first 16 bytes of the hash are used.
$key = substr(hash('sha1', $passwordUtf16, true), 0, 16);
$method = 'des-ede-cbc';
$options = OPENSSL_RAW_DATA;
$iv = substr($data, 4, 8); // initialization vector of 8 bytes
$encrypted_data = substr($data, 12); // actual encrypted data
} else if ($version === 2) {
// Key is hashed using sha256. Key length is always 32 bytes.
$key = hash('sha256', $passwordUtf16, true);
$method = 'aes-256-cbc';
$options = OPENSSL_RAW_DATA;
$iv = substr($data, 4, 16); // iv of 16 bytes
$encrypted_data = substr($data, 20);
} else {
throw new \InvalidArgumentException('Invalid version');
}
$decrypted = openssl_decrypt($encrypted_data, $method, $key, $options, $iv);
if ($decrypted === false) {
return null;
}
// First 8 bytes contain the magic number 0xbaadf00d and the length
// of the decrypted data
$decrypted = substr($decrypted, 8);
// UTF-16 encoding should be converted to UTF-8. Note that
// there might be a better way to accomplish this.
$isUtf16 = strpos($decrypted, 0) !== false;
if ($isUtf16) {
return mb_convert_encoding($decrypted, 'UTF-8', 'UTF-16LE');
}
return $decrypted;
}
// A version 1 encrypted string. Taken directly from the Stack Overflow answer linked above
$s = '010000007854E155CEE338D5E34808BA95367D506B97C63FB5114DD4CE687FE457C1B5D5';
$password = 'banana';
$bin = hex2bin($s);
$d = decrypt($bin, $password);
var_dump($d); // string(6) "turkey"
// A version 2 encrypted string. Taken directly from the Stack Overflow answer linked above
$s = '02000000266AD4F387FA9474E825B013B0232E73A398A5F72B79BC90D63BD1E45AE3AA5518828D187125BECC285D55FA7CAFED61';
$password = 'Radames';
$bin = hex2bin($s);
$d = decrypt($bin, $password);
var_dump($d); // string(16) "LetTheSunShining"
Sidenote: mcrypt is deprecated as it has been abandoned for over a decade.
EncryptByPassPhrase() uses a proprietary format that don't seem to have readily available documentation. Best bet for decrypt is DecryptByPassPhrase().
The purpose of this proprietary format is to be used in the database layer of your application - not cross application / network / languages.
If you are dead set of using this format (which i would recommend not to), you would need to obtain the specification of this format, including what kind of key deviation functions are used to turn passwords into actual encryption keys etc.
When you have this specification, you would then have to implement this on your own.
Use the below in query
DECRYPTBYPASSPHRASE('key', [field] )
Reference

Decrypt Access token using PHP for C# Encryption

I have an API URL with specific access token which was encrypted with C#(Below Code) and I want to Decrypt it using PHP post request by passing access token to parameters. Can anyone help me out to solve this problem.
Thanks in Advance!!
C# Code for Encryption:
private String AES_encrypt(String Input)
{
var aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Padding = PaddingMode.PKCS7;
aes.Key =Convert.FromBase64String("QdZx1B0ZIcLK7DPNRK09wc/rjP4WnxtE");
aes.IV = Convert.FromBase64String("hBSE4tn6e/5c3YVKFZ54Iisi4MiDyCO0HJO+WZBeXoY=");
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
{
byte[] xXml = Encoding.UTF8.GetBytes(Input);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
String Output = Convert.ToBase64String(xBuff);
return Output;
}
So far I tried to decrypt it with the below code
function strippadding($string)
{
$slast = ord(substr($string, -1));
$slastc = chr($slast);
$pcheck = substr($string, -$slast);
if(preg_match("/$slastc{".$slast."}/", $string)){
$string = substr($string, 0, strlen($string)-$slast);
return $string;
} else {
return false;
}
}
function decrypt($string)
{
$key = base64_decode("DZR");
$iv = base64_decode("Shravan");
$string = base64_decode($string);
return strippadding(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_CBC, $iv));
}
Fill out the items below:
Use this key and iv that are below.
key = QdZx1B0ZIcLK7DPNRK09wc/rjP4WnxtE
iv= hBSE4tn6e/5c3YVKFZ54Iisi4MiDyCO0HJO+WZBeXoY=
Run some text through your AES_encrypt() function and whatever comes out paste on the next line.
encrypted text = put your encrypted text here.
$xXml = openssl_decrypt(
$Output, #openssl_decrypt works with base64 encoded data
'AES-256-CBC',
base64_decode("QdZx1B0ZIcLK7DPNRK09wc/rjP4WnxtE"), #key
OPENSSL_RAW_DATA,
base64_decode("hBSE4tn6e/5c3YVKFZ54Iisi4MiDyCO0HJO+WZBeXoY=") #IV
);
Now $xXml is the binary form of the input string in UTF-8 encoded.
And make sure openssl is included in your PHP build.
You have not provided me with any encrypted text to be able to test this with.
Here is what I think you need to do:
In your C# code you need to change the block size to 128 bits:
aes.BlockSize = 128;
In your C# code your IV needs to be 128 bits or 16 bytes long. It needs to equal your selected block size.
So for now this needs to be your IV:
IV = HWeR102dxMjRHZlxTqL2aA==
Your key is set for 256 bits: So here is a 256 bit key:
Key = aZUEBKSsYRKA6CGQbwFwvIS8rUnW7YA2hVMNHnnf844=
C# has functions that will automatically generate a cryptographically strong string for you of a certain length. I suggest you find these functions and learn how to use them so you can generate your own keys and IVs.
Now for the PHP portion.
You should use the OpenSSL library instead of the Mcrypt library. Mcrypt is deprecated and is no longer supported. So here is an OpenSSL solution.
Since the block size is now 128 bits and the key size is 256 bits it will now be compatible with the openssl library's AES-256-CBC function.
$key = 'aZUEBKSsYRKA6CGQbwFwvIS8rUnW7YA2hVMNHnnf844='; //256 bit key.
$iv = 'HWeR102dxMjRHZlxTqL2aA=='; //128 bit IV length. The same as the block size that is set in the C#.
function decrypt($string, $key, $iv){
$cipherText = base64_decode($string); //We are going to use raw data.
return openssl_decrypt($cipherText, 'AES-256-CBC', base64_decode($key), OPENSSL_RAW_DATA, base64_decode($iv));
//Note that I did not specify no padding in the function. By default it is PKCS#7 which is what is set in the C# code.
}
The best I can tell this should work for you. This assumption is predicated on the fact that your AES_encrypt() is working correctly and that you have OpenSSL on your machine. Which you probably do.
Hope it helps!

Decrypting PHP openssl_ecrypt with NodeJS crypto errors

We have a legacy PHP system that encrypted some data via openssl_encrypt. The PHP code is pretty straight forward. (All values are randomly generated for this example, but are the same format and lengths as the real values and reproduce the same errors).
$in = '12345';
$method = 'AES-256-CBC';
$key = '5fjfwc7kp84z5yet358t';
$options = 0;
$iv = '8x69nt6qnptg3x4j';
openssl_encrypt($in, $method, $key, $options, $iv);
Decrypting via PHP is also pretty straight forward.
$in = 'yy03+cUpsq5uGWclBLtwIA==';
$method = 'AES-256-CBC';
$key = '5fjfwc7kp84z5yet358t';
$options = 0;
$iv = '8x69nt6qnptg3x4j';
openssl_decrypt($in, $method, $key, $options, $iv);
However, when trying to port it over to Node crypto I keep getting errors on key length, iv length, and numerous other errors as I try different approaches.
const input = Buffer.from('yy03+cUpsq5uGWclBLtwIA==');
const iv = Buffer.from('8x69nt6qnptg3x4j');
const key = Buffer.from('5fjfwc7kp84z5yet358t');
let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv, 0);
let clearText = decipher.update(input, 'base64', 'utf8');
clearText += decipher.final('utf8');
I've probably tried half a dozen or more examples in NodeJS and all produce errors and fail to decrypt entirely.
Current error is "Invalid key length" which remains the error even if I restrict it to 16 characters.
Padding and base64 processing was the solution. Working code looks closer to this:
const keyStr = '5fjfwc7kp84z5yet358t';
const diff = Math.abs(keyStr.length - 32);
const padding = Buffer.alloc(diff, 0x00);
const input = Buffer.from('yy03+cUpsq5uGWclBLtwIA==', 'base64');
const iv = Buffer.from('8x69nt6qnptg3x4j');
let key = Buffer.from('5fjfwc7kp84z5yet358t');
key = Buffer.concat([key, padding]);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv, 0);
let clearText = decipher.update(input, 'base64', 'utf8');
clearText += decipher.final('utf8');

MCrypt rijndael-128 to OpenSSL aes-128-ecb conversion

Since Mcrypt is deprecated, I want to use OpenSSL instead in my code since we already using php 7.0.17 in our server and there's no tell when they upgrade it.
Some third party API (hosted on PHP 5.x probably and using mcrypt), is taking encrypted data. They've provided methods which they are using to encrypt/decrypt strings.
Here are they
$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c' ;
public function encrypt128($str)
{
$block = mcrypt_get_block_size("rijndael_128", "ecb");
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB));
}
public function decrypt128($str)
{
$str = base64_decode($str);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB);
$len = strlen($str);
$pad = ord($str[$len - 1]);
return substr($str, 0, strlen($str) - $pad);
}
using these methods string small1 if encrypted becomes v7IXp5vVaFVXXlt/MN8BVw==
We want to use openssl_encrypt in our side such that if we encrypt same string with OpenSSL it must give same results as Mcrypt. I've researched that mcrypt using rijndael-128 Mode ecb should be compatible with OpenSSL aes-128-ecb.
For last few hours, I've been trying to make my own method to encrypt strings serving same result by using OpenSSL. So far I've come to this
public function sslEncrypt128($str)
{
$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c';
return base64_encode(openssl_encrypt($str, 'aes-128-ecb', $secret, OPENSSL_RAW_DATA));
}
But it produces different string SxJ3+EdaeItZx3/EwGTUbw== for same as above input. I don't know if it is flag's problem or padding's, any pointers will be welcome.
I've added the code here to test online https://3v4l.org/v2J2N
Thanks in advance.
Here is what worked for me:
<?php
$str = 'Content';
if (strlen($str) % 16) {
$str = str_pad($str, strlen($str) + 16 - strlen($str) % 16, "\0");
}
$key = 'KEY';
if (strlen($key) % 16) {
$key = str_pad($key, strlen($key) + 16 - strlen($key) % 16, "\0");
}
$res1 = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
echo strToHex($res1) . ' | mcrypt_encrypt';
echo "<hr>";
echo strToHex(openssl_decrypt($res1, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';
echo "<hr>";
$res2 = openssl_encrypt($str, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
echo strToHex($res2) . ' | openssl_encrypt';
echo "<hr>";
echo strToHex(openssl_decrypt($res2, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';
function strToHex($string) {
$hex = '';
for ($i = 0; $i < strlen($string); $i++) {
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0' . $hexCode, -2);
}
return strToUpper($hex);
}
In your specific example I've found that by changing aes-128-ecb to aes-256-ecb, it produces the same output as the legacy mcrypt_encrypt.
Most likely the key was expected to be used as hex (it already is in hex format) not as a string to be converted to hex.
mcrypt:
mcrypt does not support standard PKCS#7 (née PKCS#5) padding, only non-standard null padding but the padding is being explicitly added prior to mcrypt.
The encryption v7IXp5vVaFVXXlt/MN8BVw== is the correct encryption based on PKCS#7 padding. ECB mode and the key as a string.
See: mcrypt - AES CALCULATOR.
In hex, notice the data padding is clearly visible:
key: 6130613765373939376236643566636435356634623563333236313162383763
data: 736D616C6C310A0A0A0A0A0A0A0A0A0A
encrypted: BFB217A79BD56855575E5B7F30DF0157
In Base64:
encrypted: v7IXp5vVaFVXXlt/MN8BVw==
OpenSSL:
Notice the key is 256-bits but the OpenSSL call with "aes-128-ecb" seems to imply a 128-but key. So the keys don't match.
See: OpenSSL - AES CALCULATOR
In hex, notice the data padding is clearly visible:
key: 61306137653739393762366435666364
data: 736D616C6C310A0A0A0A0A0A0A0A0A0A
encrypted: 4B1277F8475A788B59C77FC4C064D46F
In Base64:
encrypted: SxJ3+EdaeItZx3/EwGTUbw==

Categories