2

我有一些已使用 Perl 的Crypt::CBC模块加密的密文,我希望在其他地方解密。

密文是使用Crypt::CBC构造函数的“简单”版本生成的,即:

use Crypt::CBC;
$cipher = Crypt::CBC->new( -key    => 'my secret key',
                           -cipher => 'Blowfish'
                          );

通过阅读 MAN 页面,这种构造方法将采用简单的字符串密钥和随机盐来生成用于加密的 IV 和文字密钥,并在盐中嵌入标头。

“salt”——将密码短语与一个 8 字节的随机值结合起来,从提供的密码短语中生成分组密码密钥和 IV。盐将被附加到数据流的开头,允许解密重新生成密钥和 IV 给定正确的密码。此方法与当前版本的 OpenSSL 兼容。

我现在需要在另一个平台上解密密文,该平台只支持给定密文、文字密钥和 IV 的 CBC 解密。为了尝试生成文字键 IV & salt,我使用 Crypt::CBC 生成如下值:

my $crypt = new Crypt::CBC(-key => 'my secret key', -cipher => 'Blowfish');
my $out = $crypt->decrypt($ciphertext);
my $literal_key = $crypt->key();
my $iv = $crypt->iv();
my $salt = $crypt->salt();

这里的解密是正确的,但是我一直无法使用生成的文字密钥 & IV 来解密密码;这会产生垃圾:

my $crypt2 = new Crypt::CBC(
    -literal_key => 1,
    -key => $literal_key,
    -cipher => 'Blowfish',
    -iv => $iv,
    -header => 'none');
my $rubbish - $crypt2->decrypt($ciphertext);

我无法提供文字键并使用加盐标题,因此我对下一步行动感到迷茫。

我怎样才能解密这个文本?

编辑:目标系统没有运行 Perl,但我已经能够生成与上面 $rubbish 中相同的值,所以我确定它使用相同的算法(CBC、Blowfish)来破译。

4

3 回答 3

1

这可能有效。您的密钥长度必须正好为 56 个字节,而 iv 长度必须正好为 8 个字节:

#!/usr/bin/perl

use strict;
use warnings;

use Crypt::CBC;

my $key = "x" x 56;
my $iv  = "x" x 8;

my $plaintext  = "this is just some normal text\n";
my $ciphertext = Crypt::CBC->new(
    -cipher      => 'Blowfish',
    -header      => 'none',
    -literal_key => 1,
    -key         => $key,
    -iv          => $iv,
)->encrypt($plaintext);

print Crypt::CBC->new(
    -cipher      => 'Blowfish',
    -header      => 'none',
    -literal_key => 1,
    -key         => $key,
    -iv          => $iv,
)->decrypt($ciphertext);
于 2011-07-04T05:15:27.347 回答
1

要解密流,首先需要删除 Crypt::CBC 的“salt”模式添加的标头。标头由 8 个字符Salted__和后跟 8 个字节的盐数据组成。

在 perl 中,应该这样做:

my $crypt2 = new Crypt::CBC(
    -literal_key => 1,
    -key => $literal_key,
    -cipher => 'Blowfish',
    -iv => $iv,
    -header => 'none');
my $cleartext = $crypt2->decrypt(substr($ciphertext, 16));
于 2011-07-06T13:19:54.430 回答
1

如果有人需要 PHP 中的 _salted_key_and_iv 函数 - 这里是:

function _salted_key_and_iv ($pass, $salt) {
        if(strlen($salt) != 8) {
            die("Salt must be 8 bytes long");
        }

        $key_len = 56;
        $iv_len  = 8;

        $desired_len = $key_len+$iv_len;

        $data  = '';
        $d = '';

        while (strlen($data) < $desired_len) {
            $d = pack("H*", md5($d . $pass . $salt));
            $data .= "$d";
        }

        return $data;
}
于 2012-02-02T13:15:29.673 回答