PHP преобразование mcrypt в openssl - PullRequest
0 голосов
/ 01 марта 2019

Я знаю, что 3DES и MD5 небезопасны.Я буду работать над их заменой, как только она снова заработает,

У меня есть мобильное приложение, использующее 3DES с ключом MD5 в качестве секретного ключа для связи с приложением PHP.

Теперь этот код отлично работает на PHP 5.3 (это пример, который я сгенерировал)

mcrypt_decrypt(
    MCRYPT_3DES, 
    md5(
        utf8_encode(
            "MobileAppSecureKey"
        ),
        true
    ), 
    base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI="), 
    MCRYPT_MODE_CBC, 
    base64_decode("cTOCJ/iYL18=")
)

Теперь я перенес его для использования метода OpenSSL, мой новый код

openssl_decrypt(
    base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI="), 
    'DES-EDE3-CBC', 
    md5(
        utf8_encode(
            "MobileAppSecureKey"
        ),
        true
    ), 
    0, 
    base64_decode("cTOCJ/iYL18=")
)

Но новый код не работает, выдает ошибку error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length из openssl_error_string()

Я не уверен, почему он жалуется на конечную длину блока, когда это прекрасно работает в mcrypt

Код, использованный для генерации тестовых данных, был получен с мобильного устройства. Мобильное приложение является приложением Cordova и использует библиотеку CryptoJS

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)};

Зашифрованная полезная нагрузка была

{"jsonrpc":"2.0","method":"events.enableParentGenres","params":[159],"id":1}

Модификации, которые были опробованы,

Согласно yivi , опции были установлены на OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING

Согласно Tuckbros предложение, сообщение было дополнено

$message_padded = base64_decode("bkCfcseIt/TPsgNCdyX9fv2/4MjOJdaPXakNNbxQT3n6tXHa5bDoXojQ3g7jPLCu+wjwD0guQzw3hCFUSVx47PmDNHASk7g/kJ4K4tX0VGI=");
$message_padded = str_pad($message_padded,
        strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");

Оба этипредотвратил ошибку об окончательной длине блока, однако зашифрованная полезная нагрузка при выполнении кода не расшифровывалась.

1 Ответ

0 голосов
/ 07 марта 2019

Параметры, которые вы передаете openssl_decrypt, кажутся неправильными;вы передаете параметр OPTIONS как 0, который необходимо установить на OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, поскольку вы предоставляете функции необработанные данные (base64_decode).

Ключ также необходимо преобразовать включ 192 бит, как в коде javascript:

$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];
}

Попробуйте это:

$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}
...