需要帮助"打包"for perl和php

Car*_*ten 3 php perl pack

我的任务是将perl制作的crypt函数转换为php代码.一切正常,除了这个:

Perl的:

$wert = Encode::encode( "utf8", $wert );
$len=length $wert;
$pad = ($len % 16)?"0".chr(16 - ($len % 16)):"10";
$fuell = pack( "H*", $pad x (16 - $len % 16));
Run Code Online (Sandbox Code Playgroud)

PHP:

$wert = utf8_encode($wert);
$len = mb_strlen($wert);
$pad = ( $len%16 ) ? '0'.chr(16 - ($len%16)) : '10';
$fuell = pack("H*", str_repeat($pad, (16 - $len % 16)));
Run Code Online (Sandbox Code Playgroud)

php版本适用于某些字符串.但是当我有'2010-01-01T00:00:00.000'这样的东西时,perl版本没有任何错误,php版本打印"PHP Warning:pack():Type H:非法十六进制数字".

如果有人能够发现php版本中的错误,我将非常感激.

编辑:

这是我要转换成php的完整功能.它是由一家公司的程序员制作的,它不再适用于我们,所以我无法真正说明原意是什么.

sub crypt
{
    my $self = shift;
    my ($wert,$pw)= @_;
    $wert = Encode::encode( "utf8", $wert );
    $pw = Encode::encode( "utf8", $pw );
    $len=length $wert;
    $pad = ($len % 16)?"0".chr(16 - ($len % 16)):"10";
    $fuell = pack( "H*", $pad  x (16 - $len % 16));
    $wert=$wert.$fuell;
    $lenpw=length $pw;
    $fuell = ($lenpw % 16)? pack ("H*", "00" x (16 - $lenpw % 16)):"";
    $pw=$pw.$fuell;
    $cipher = new Crypt::Rijndael $pw, Crypt::Rijndael::MODE_CBC;
    $cipher->set_iv($pw);
    $crypted = encode_base64($cipher->encrypt($wert),"");

    return $crypted;
}
Run Code Online (Sandbox Code Playgroud)

bis*_*ish 7

看起来错误实际上在两个版本中.格式代码H查找十六进制数字,并且如PHP错误中所述,它没有找到(合法的)数字.罪魁祸首似乎是这个表达:

chr(16 - ($len % 16))
Run Code Online (Sandbox Code Playgroud)

Perl版本没有抱怨,因为Perl的pack版本将转换字符,无论它是否是十六进制数字(可能不是你想要的).本文档介绍了有关实际发生的情况的详细信息.

要防止出错,请尝试以下方法:

sprintf('%x', 16 - ($len % 16))
Run Code Online (Sandbox Code Playgroud)

注意:虽然这应该可以解决您遇到的错误,但我不知道它是否是可接受的解决方案,因为我不知道Perl代码原始作者的确切意图.

  • +1表示无效字符来自对`chr`的调用,虽然我不确定`sprintf`会做他正在尝试做的事情,因为正如你所说,我们不知道Perl代码作者的意图. (2认同)

Ada*_*ire 6

似乎Perl实现pack()容忍输入字符串中的无效十六进制数字,而PHP版本显然不是.

考虑:

print pack("H*", "ZZ");
Run Code Online (Sandbox Code Playgroud)

这打印3在Perl中(由于某种原因),但会导致您在PHP中提到的错误.

我不确定Perl正在使用这些'数字'做什么,但它肯定与PHP不一样.

编辑:看起来,Perl实际上会将十六进制数字域"滚动"到字符集中.那是:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ  #-- Give this to Perl...
0123456789ABCDEF0123456789ABCDEF0123  #-- .. and it's treated as this hex digit
Run Code Online (Sandbox Code Playgroud)

因此,"ZZ"与"33"相同,这就是它打印的原因3.请注意,根据文档,此行为未明确定义.因此,Perl中的原始实现可以被认为是错误的,因为它依赖于没有明确定义的行为.