Php 使用MCrypt解密密文(3DES CBC模式)

Php 使用MCrypt解密密文(3DES CBC模式),php,mcrypt,3des,Php,Mcrypt,3des,我有一个密文,在3DES CBC模式下加密,我解密它有点困难。我有以下信息(不是实际值): 我的解密函数基于中的PHP类。看起来是这样的: <?php function decrypt($key,$iv,$token) { $td = mcrypt_module_open('tripledes', '', 'cbc', ''); $iv = substr($iv, 0, mcrypt_enc_get_iv_size($td)); $expected_key_

我有一个密文,在3DES CBC模式下加密,我解密它有点困难。我有以下信息(不是实际值):


我的解密函数基于中的PHP类。看起来是这样的:

<?php
function decrypt($key,$iv,$token) {
    $td = mcrypt_module_open('tripledes', '', 'cbc', ''); 
    $iv = substr($iv, 0, mcrypt_enc_get_iv_size($td)); 
    $expected_key_size = mcrypt_enc_get_key_size($td); 

    $key = substr(md5($key), 0, $expected_key_size); 
    mcrypt_generic_init($td, $key, $iv);

    $decrypted_string = trim(mdecrypt_generic($td, base64_decode($token)));

    mcrypt_generic_deinit($td); 
    mcrypt_module_close($td); 

    return $decrypted_string;
}
?>

但是,我不确定如何将这三个键输入到算法中。我试着像这样将它们链接在一起:$key1.$key2.$key3,并以相反的顺序,但没有用

如果您有任何帮助,我们将不胜感激。

//三个16字符长的密钥$expected\u key\u大小为24,3*8。这些键很可能是十六进制格式

function foo($hex) {
    $rv = '';
    foreach(str_split($hex, 2) as $b) {
        $rv .= chr(hexdec($b));
    }
    return $rv;
}

// Three 16 character long keys
$key1 = '1234567890123456';
$key2 = '6543210987654321';
$key3 = '6549873210456123';

$key = foo($key1.$key2.$key3);
//三个16字符长的密钥$预期密钥大小为24,3*8。这些键很可能是十六进制格式

function foo($hex) {
    $rv = '';
    foreach(str_split($hex, 2) as $b) {
        $rv .= chr(hexdec($b));
    }
    return $rv;
}

// Three 16 character long keys
$key1 = '1234567890123456';
$key2 = '6543210987654321';
$key3 = '6549873210456123';

$key = foo($key1.$key2.$key3);

最后我发现了函数的问题。它是将密钥、IVEC和令牌从十六进制转换成十六进制、删除解密密钥的MD5散列以及删除结果纯文本的Base64解码的组合

生成纯文本的填充字符有点奇怪,但rtrim()将其去掉。还值得注意的是,加密最初是在JSP中使用一些标准Java库完成的,因此这对于其他使用Java加密的人来说可能很有用→ PHP解密

感谢您的帮助VolkerK,以下是我最终使用的函数(包括我在下面没有添加的十六进制函数):


最后我发现了函数的问题。它是将密钥、IVEC和令牌从十六进制转换成十六进制、删除解密密钥的MD5散列以及删除结果纯文本的Base64解码的组合

生成纯文本的填充字符有点奇怪,但rtrim()将其去掉。还值得注意的是,加密最初是在JSP中使用一些标准Java库完成的,因此这对于其他使用Java加密的人来说可能很有用→ PHP解密

感谢您的帮助VolkerK,以下是我最终使用的函数(包括我在下面没有添加的十六进制函数):


预期的密钥长度为24,预期的初始化向量长度为8,因此这些密钥必须以十六进制编码。我现在在解密前对密钥使用下面的VolkerK函数,但它仍然不能产生预期的明文。您确定“2ad82e09e3b4e7c491e4bb9fb7c606e1”是令牌的base64编码版本吗?令牌与此非常类似,是的。看起来也是十六进制格式的。我尝试了base64编码令牌,将其从十六进制转换为十六进制,然后将其从十六进制转换为base64编码,但没有乐趣。您能否提供加密/编码令牌、一组密钥和相应的解密令牌?预期密钥长度为24,预期初始化向量长度为8,因此密钥必须以十六进制编码。我现在在解密前对密钥使用下面的VolkerK函数,但它仍然不能产生预期的明文。您确定“2ad82e09e3b4e7c491e4bb9fb7c606e1”是令牌的base64编码版本吗?令牌与此非常类似,是的。看起来也是十六进制格式的。我尝试了base64编码令牌,将其从十六进制转换为十六进制,然后将其从十六进制转换为base64编码,但没有乐趣。您能提供加密/编码令牌、一组密钥和相应的解密令牌吗?
$algorithm = 'tripledes';
$key   = 'F123ACA...'; // Some hex key
$ivec  = 'FE12FA1...'; // Some hex ivec
$token = 'F2ACE12...'; // Some hex token
$mode  = 'cbc';

$key    = foo($key);
$ivec   = foo($ivec);
$token  = foo($token);

function decrypt($key,$iv,$algorithm,$mode,$token) {
    $td = mcrypt_module_open($algorithm, '', $mode, '') ; 
    $iv = substr($iv, 0, mcrypt_enc_get_iv_size($td));

    $expected_key_size = mcrypt_enc_get_key_size($td); 
    $key = substr($key, 0, $expected_key_size); 

    mcrypt_generic_init($td, $key, $iv);

    $response = rtrim(mdecrypt_generic($td, $token), '');

    mcrypt_generic_deinit($td); 
    mcrypt_module_close($td); 

    return $response;
}

$plaintext = decrypt($key,$ivec,$algorithm,$mode,$token);