PHP将mcrypt转换为openssl

我知道3DES和MD5是不安全的.一旦我再次使用它,我会努力更换它们,

我有一个移动应用程序,它使用3DES和一个密钥的MD5作为SECRET KEY来与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=")
)

但是新代码不起作用,它给出了错误错误:0606506D:数字包络例程:EVP_DecryptFinal_ex:来自openssl_error_string()的错误的最终块长度

我不确定为什么它会在mcrypt中完美地工作时抱怨最终的块长度

用于生成测试数据的代码来自移动设备,移动应用程序是Cordova应用程序并使用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)};

加密的有效载荷是

{"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");

这两个都阻止了关于最终块长度的错误,但是在运行代码时加密的有效负载没有解密.

解决方法:

你在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}
上一篇:javascript – CryptoJS使用密码加密AES,但PHP解密需要密钥


下一篇:javascript – 解密Crypto-JS提供数字十六进制输出而不是原始明文字符串