问题
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.
回答1:
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}
来源:https://stackoverflow.com/questions/54947975/php-converting-mcrypt-to-openssl