【问题标题】:PHP: PEAR: Encrypting with Crypt_CBC, Decrypting with Perl's CBCPHP: PEAR: 用 Crypt_CBC 加密,用 Perl 的 CBC 解密
【发布时间】:2010-10-13 22:20:32
【问题描述】:

我必须完成的任务之一是从 PHP 端加密某些内容,然后使用 Perl 对其进行解密。

我发现似乎适合我需要的PEAR 模块是Crypt_CBC。但是,一定是我做错了什么或不明白,因为到目前为止我一直无法获得正确的结果。

下面的代码摘录专门用于测试目的,因为我想在将其应用到我的实际项目代码之前尝试一下。

首先,这是我的 PHP 代码,我用它加密传递给 $text 参数的任何内容(即 cryptTest.php?text=hello)

require_once('Crypt/CBC.php');  

$key = "8326554161EB30EFBC6BF34CC3C832E7CF8135C1999603D4022C031FAEE";  
$cipher = new Crypt_CBC($key, 'BLOWFISH');

$encrypted = $cipher->encrypt($text);  

if (PEAR::isError($encrypted)) {  
    echo $encrypted->getMessage();  
} else {  
    echo "ENCRYPTED STRING: " . $encrypted;  
}  

从那时起,我复制了从该脚本(在我的浏览器输出中)回显的所有内容,并将其粘贴到下面我的 PERL 脚本的 $encrypted 变量中:

use Crypt::CBC; 
$encrypted = "RandomIVá´bp3Ó¯làK”Á(Û";  
my $key = "8326554161EB30EFBC6BF34CC3C832E7CF8135C1999603D4022C031FAEE";  
my $vector = "\0\0\0\0\0\0\0\0";  

my $cipher = Crypt::CBC->new(  
                       {'key'             =>$key,  
                        'cipher'          => 'Blowfish',  
                        'iv'              => $vector,  
                        'prepend_iv'      => 0  
                       });  

my $plaintext = $cipher->decrypt($encrypted);

print $plaintext;

我一直在尝试很多事情,比如没有在 Perl 端指定 IV 等,但它一直给我错误。这种形式是我得到任何输出的唯一形式。

上面的执行结果,原始 $text = "hello" 是:Pñšîî7àÐŽZÊ&Rhello

我发现我的原始内容已正确解密,但并非没有在我想要的部分之前添加一堆废话字符。

谁能指出我做错了什么以及如何解决?

非常感谢。

【问题讨论】:

  • 哦,感谢 Manni 的编辑 :) 在这里格式化文本还是新手。

标签: php perl encryption


【解决方案1】:

我终于找到了解决问题的方法。

感谢你们两位,你们的回答确实有所帮助。我确实按照您的建议在 base64 中编码/解码,因此避免了任何纯文本编码问题。

为了使解密工作,我必须将 'header' => 'randomiv' 添加到我的 Perl 脚本的密码创建中,因为 PEAR 的 Crypt_CBC 类在加密时使用随机 IV。

我在Crypt::CBC's documentation 中找到了该特定参数。

另外,直接查看 CBC.php 的解密函数,我发现它为确定 IV 所做的工作:获取标头 ('RandomIV') 的长度,并将其用作偏移量,将加密字符串替换为blocksize 的值(默认为 8)。我还指定了 keysize(默认为 56)以进行良好的测量。

为了完整起见和参考,以下是我更新的两个测试脚本:

PHP (cryptTest.php):

require_once('Crypt/CBC.php');

$key = "8326554161EB30EFBC6BF34CC3C832E7CF8135C1999603D4022C031FAEE";  
$cipher = new Crypt_CBC($key, 'BLOWFISH');

$encrypted = $cipher->encrypt($text);

if (PEAR::isError($encrypted)) {  
    echo $encrypted->getMessage();  
} else {  
    echo "ENCRYPTED STRING: " . base64_encode($encrypted);  
}

PERL (decryptTest.pl)

use Crypt::CBC;  
use MIME::Base64;

my $encrypted = decode_base64("UmFuZG9tSVbrNE3ony00FlUbiprLn0fu");  
my $key = "8326554161EB30EFBC6BF34CC3C832E7CF8135C1999603D4022C031FAEE";  
my $header_spec = "randomiv";  
my $blocksize = 8;  
my $keysize = 56;  

my $iv_offset = length $header_spec;  
my $iv = substr $encrypted, $iv_offset, $blocksize;

my $cipher = Crypt::CBC->new(  
                {'key'        =>$key,  
                'cipher'        => 'Blowfish',  
                'iv'            => $iv,  
                'header'        => $header_spec,  
                'prepend_iv'    => $iv_offset,  
                'blocksize'  => $blocksize,  
                'keysize'      => $keysize   
                })  

my $plaintext = $cipher->decrypt($encrypted);

print $plaintext;

给你。再次,非常感谢!

马修

【讨论】:

    【解决方案2】:

    CBC 不是容错的;密文的问题会破坏整个块。因此,您能够通过一些额外的垃圾恢复纯文本这一事实表明问题出在填充上,而不是加密本身。

    分组密码适用于完整的块。如果最后一个块不完整,则以允许接收者确定什么是填充和什么是数据的方式对其进行填充。搜索 API 文档以了解如何处理填充。

    如果可能,将解密后的明文转换为十六进制并发布,以使不可打印的字节可见。这可能会揭示 PHP 端使用的填充方案。

    【讨论】:

      【解决方案3】:

      您不应该使用加密例程的普通输出来执行此操作。您可能会遇到各种编码问题。我建议你对你的加密字符串进行base64编码并复制粘贴,然后在解密之前对其进行base64解码。

      【讨论】:

        猜你喜欢
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 2016-07-25
        • 2019-11-17
        • 2017-09-28
        • 2015-09-25
        • 1970-01-01
        • 2014-02-06
        相关资源
        最近更新 更多