使用 Perl CBC 加密并使用 PHP mcrypt 解密

发布于 2024-08-28 19:16:16 字数 1053 浏览 8 评论 0原文

我有一个用 Perl Crypt::CBC (Rijndael,cbc) 加密的加密字符串。原始明文使用 Crypt::CBC 的 encrypt_hex() 方法进行加密。

$encrypted_string = '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d';

我有使用过的 32 个字符的密钥。

mcrypt 已成功编译为 PHP,但我在尝试解密 PHP 中的字符串时遇到了很大的困难。我总是收到乱码。

如果我解压('H*',$encrypted_string),我会看到'RandomIV'后面跟着看起来像二进制的内容。

我似乎无法正确提取 IV 并分离实际的加密消息。我知道我没有提供我的信息,但我不知道还能从哪里开始。

$cipher = 'rijndael-256';
$cipher_mode = 'cbc';

$td = mcrypt_module_open($cipher, '', $cipher_mode, '');

$key = '32 characters'; // Does this need to converted to something else before being passed?
$iv = ??  // Not sure how to extract this from $encrypted_string.
$token = ?? // Should be a sub-string of $encrypted_string, correct?

mcrypt_generic_init($td, $key, $iv);
$clear = rtrim(mdecrypt_generic($td, $token), '');
mcrypt_generic_deinit($td); 
mcrypt_module_close($td);

echo $clear;

任何帮助、正确方向的指示,将不胜感激。如果我需要提供更多信息,请告诉我。

I have an encrypted string that was encrypted with Perl Crypt::CBC (Rijndael,cbc). The original plaintext was encrypted with encrypt_hex() method of Crypt::CBC.

$encrypted_string = '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d';

I have the 32 character key that was used.

mcrypt is successfully compiled into PHP, but I'm having a very hard time trying to decrypt the string in PHP. I keep getting gibberish back.

If I unpack('H*', $encrypted_string), I see 'RandomIV' followed by what looks like binary.

I can't seem to correctly extract the IV and separate the actual encrypted message. I know I'm not providing my information, but I'm not sure where else to start.

$cipher = 'rijndael-256';
$cipher_mode = 'cbc';

$td = mcrypt_module_open($cipher, '', $cipher_mode, '');

$key = '32 characters'; // Does this need to converted to something else before being passed?
$iv = ??  // Not sure how to extract this from $encrypted_string.
$token = ?? // Should be a sub-string of $encrypted_string, correct?

mcrypt_generic_init($td, $key, $iv);
$clear = rtrim(mdecrypt_generic($td, $token), '');
mcrypt_generic_deinit($td); 
mcrypt_module_close($td);

echo $clear;

Any help, pointers in the right direction, would be greatly appreciated. Let me know if I need to provide more information.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

离笑几人歌 2024-09-04 19:16:16

我认为要使用的 IV 是由 CBC::Crypt 随机生成的。如果我是对的并且正确地阅读了文档,那么它就是解压字符串的前 32 个字节。

用好钥匙试试这个:

$cipher = 'rijndael-256';
$cipher_mode = 'cbc';

$td = mcrypt_module_open($cipher, '', $cipher_mode, '');

$key = '32 characters'; // Does this need to converted to something else before being passed?

$unpacked = pack('H*', '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d');


$iv = substr($unpacked, 0, 32);
$token = substr($unpacked, 32);

mcrypt_generic_init($td, $key, $iv);
$clear = rtrim(mdecrypt_generic($td, $token), '');
mcrypt_generic_deinit($td); 
mcrypt_module_close($td);

echo $clear;

I think the IV to use is just generated randomly by CBC::Crypt. If I'm right and reading the doc correctly, it's the 32 first bytes of the unpacked string.

Try this with the good key :

$cipher = 'rijndael-256';
$cipher_mode = 'cbc';

$td = mcrypt_module_open($cipher, '', $cipher_mode, '');

$key = '32 characters'; // Does this need to converted to something else before being passed?

$unpacked = pack('H*', '52616e646f6d49567b2c89810ceddbe8d182c23ba5f6562a418e318b803a370ea25a6a8cbfe82bc6362f790821dce8441a790a7d25d3d9ea29f86e6685d0796d');


$iv = substr($unpacked, 0, 32);
$token = substr($unpacked, 32);

mcrypt_generic_init($td, $key, $iv);
$clear = rtrim(mdecrypt_generic($td, $token), '');
mcrypt_generic_deinit($td); 
mcrypt_module_close($td);

echo $clear;
疏忽 2024-09-04 19:16:16

这个答案适用于 Crypt::CBC 的加盐模式,而不是 randomIV 模式,但这是我在搜索解决方案时最终找到的页面,因此其他解决方案也可能如此。

当使用此 perl 代码时:(

  my $cipher = Crypt::CBC->new(
                -key    =>  $password,
                -cipher => 'Rijndael',
                -salt => 1,
                -header => 'salt',
              ) || die "Couldn't create CBC object";
  $string = $cipher->encrypt_hex($input);

或者甚至没有默认情况下具有这些值的盐和标头)
Perl 将创建一个符合 OpenSSL 的哈希值。
我没有找到任何知道如何读取此内容的 PHP 方法,因此这是我自己在 CBC.pm 中找到的 PHP 版本的解码。
我提取密钥和 iv,然后让 mcrypt 完成工作。

function cred_decrypt($input, $password)
{
  /************************* Inspired by Crypt/CBC.pm *******************************/
  $input = pack('H*', $input);
  if (substr($input, 0, 8) != 'Salted__') {
    die("Invalid hash header, expected 'Salted__', found '".substr($input, 0, 8)."'");
  }
  $salt   = substr($input, 8, 8);
  $input  = substr($input, 16);

  $key_len  = 32;
  $iv_len   = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

  $data = '';
  $d    = '';
  while (strlen($data) < $key_len+$iv_len) {
    $d = md5($d . $password . $salt, TRUE);
    $data .= $d;
  }
  $key  = substr($data, 0, $key_len);
  $iv   = substr($data, $key_len, $iv_len);
  /**********************************************************************************/

  return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_CBC, $iv), "\0\n\3");
}

注意:在我的情况下需要 rtrim,它可能会吃掉结尾换行符(如果有)。

This answer is for the salted mode of Crypt::CBC, not the randomIV mode, but this is the page I ended up on when searching for a solution so other might also.

When using this perl code:

  my $cipher = Crypt::CBC->new(
                -key    =>  $password,
                -cipher => 'Rijndael',
                -salt => 1,
                -header => 'salt',
              ) || die "Couldn't create CBC object";
  $string = $cipher->encrypt_hex($input);

(or even without salt and header which have these values by default)
Perl will create a hash that is meant to be OpenSSL compliant.
I did not find any PHP method that knows how to read this, so here is my own PHP version of the decoding found in CBC.pm.
I extract key and iv, and then I let mcrypt finish the job.

function cred_decrypt($input, $password)
{
  /************************* Inspired by Crypt/CBC.pm *******************************/
  $input = pack('H*', $input);
  if (substr($input, 0, 8) != 'Salted__') {
    die("Invalid hash header, expected 'Salted__', found '".substr($input, 0, 8)."'");
  }
  $salt   = substr($input, 8, 8);
  $input  = substr($input, 16);

  $key_len  = 32;
  $iv_len   = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

  $data = '';
  $d    = '';
  while (strlen($data) < $key_len+$iv_len) {
    $d = md5($d . $password . $salt, TRUE);
    $data .= $d;
  }
  $key  = substr($data, 0, $key_len);
  $iv   = substr($data, $key_len, $iv_len);
  /**********************************************************************************/

  return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $input, MCRYPT_MODE_CBC, $iv), "\0\n\3");
}

Note : the rtrim was needed in my case, it might eat ending newlines if any.

ら栖息 2024-09-04 19:16:16

那也没用。我有一种感觉,Perl 的 CBC::Crypt 的功能与 PHP 的 mcrypt 函数有很大不同。我一直试图在我的 PHP 目录中找到 mcrypt 函数的源代码来比较它们,但还没有成功。

That didn't work either. I have a feeling that Perl's CBC::Crypt does things a lot differently than PHP's mcrypt functions. I've been trying to find the source code for the mcrypt functions in my PHP directory to compare them, but no luck yet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文