需要有关“打包”的帮助对于 perl 和 php

发布于 2024-08-11 18:20:05 字数 1339 浏览 5 评论 0原文

我的任务是将某人用 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));

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)));

php 版本对于某些字符串工作正常。但是当我有类似 '2010-01-01T00:00:00.000' 的内容时,perl 版本可以正常工作,没有任何错误,并且 php 版本会打印“PHP 警告:pack():类型 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;
}

I've the task to convert a crypt function someone made in perl into php code. Everything works okay except this:

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));

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)));

The php version works okay for some strings. But when I have something like '2010-01-01T00:00:00.000' the perl version works without any error and the php version prints "PHP Warning: pack(): Type H: illegal hex digit".

I'm very grateful if someone can spot the error in the php version.

Edit:

This is the complete function I've to convert into php. It was made by a programmer of a company which doesn't work for us anymore so I can't really tell what the original intention was.

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;
}

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

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

发布评论

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

评论(2

半步萧音过轻尘 2024-08-18 18:20:05

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

chr(16 - ($len % 16))

Perl 版本没有抱怨,因为 Perl 版本的 pack 会转换字符,无论它是否是十六进制数字(这可能不是您想要的)。 文档更详细地介绍了实际发生的情况。

为了防止出现错误,请尝试以下操作:

sprintf('%x', 16 - ($len % 16))

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

It looks like the error is actually in both versions. The format code H looks for a hex digit, and as noted in the PHP error, it isn't finding (a legal) one. The culprit appears to be this expression:

chr(16 - ($len % 16))

The Perl version isn't complaining because Perl's version of pack will convert the character regardless of whether or not it is a hex digit (which may not be what you want). The documentation goes into more detail about what actually happens.

To prevent the error, try this instead:

sprintf('%x', 16 - ($len % 16))

Note: While this should fix the error you are getting, I don't know if it's an acceptable solution because I don't know the exact intent of the original author of the Perl code.

寄离 2024-08-18 18:20:05

看来 pack() 的 Perl 实现能够容忍输入字符串中的无效十六进制数字,而 PHP 版本则绝对不能。

考虑一下:

print pack("H*", "ZZ");

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

我不确定 Perl 到底用这些“数字”做什么,但它绝对和 PHP 不一样。

编辑:看起来,Perl 实际上会将十六进制数字域向前“滚动”到字符集中。也就是说:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ  #-- Give this to Perl...
0123456789ABCDEF0123456789ABCDEF0123  #-- .. and it's treated as this hex digit

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

It seems that the Perl implementation of pack() is tolerant of invalid hex digits in the input string, and the PHP version is decidedly not.

Consider:

print pack("H*", "ZZ");

This prints 3 in Perl (for some reason), but results in the error you mentioned in PHP.

I'm not sure exactly what Perl is doing with these 'digits', but it's definitely not the same as PHP.

EDIT: It looks like, Perl actually will "roll" the hex digit domain forward into the character set. That is:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ  #-- Give this to Perl...
0123456789ABCDEF0123456789ABCDEF0123  #-- .. and it's treated as this hex digit

Thus, "ZZ" is the same as "33", which is why it prints 3. Note that this behavior is not well-defined according to the documentation. Thus the original implementation in Perl can be considered buggy, since it relies on behavior that isn't well-defined.

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