我正在尽力破译一些Perl代码并将其转换为C#代码,以便我可以将它与更大的程序一起使用。我已经能够将其中的大部分转换,但是我遇到了以下方法的问题:
sub dynk {
my ($t, $s, $v, $r) = (unpack("b*", $_[0]), unpack("b*", pack("v",$_[1])));
$v^=$t=substr($t,$r=$_*$_[($_[1]>>$_-1&1)+2]).substr($t,0,$r)^$s for (1..16);
pack("b*", $v);
}
它被称为:
$sid = 0;
$rand = pack("H*", 'feedfacedeadbeef1111222233334444');
$skey = dynk($rand, $sid, 2, 3) ^ dynk(substr($dbuf, 0, 16), $sid, -1, -4);
除了这一部分,我理解其中的大部分内容:
$_*$_[($_[1]>>$_-1&1)+2]
我不确定在这种情况下如何使用$ _?如果有人可以解释,我想我可以得到其余的。
答案 0 :(得分:5)
pack
和unpack
采用模式和一些数据,并根据模式转换此数据。例如,pack "H*", "466F6F"
将数据视为任意长度的十六进制字符串,并将其解码为它所代表的字节。在这里:Foo
。 unpack
函数执行相反的操作,并将二进制表示中的数据提取为特定格式。
"b*"
模式生成位字符串 - unpack "b*", "42"
为"0010110001001100"
。
v
表示一个小端16位整数。
Perl相当混淆。这是一个简化某些方面的重写。
sub dynk {
# Extract arguments: A salt, another parameter, and then two ints that determine rotation.
my ($initial, $sid, $rot_a, $rot_b) = @_;
# Unpack the initial value to a bitstring
my $temp = unpack("b*", $initial);
# Unpack the 16-bit number $sid to a bitstring
my $sid_bits = unpack("b*", pack("v", $sid));
my $v; # an accumulator
# Loop through the 16 bits of our $sid
for my $bit_number (1..16) {
# Pick the $bit_number-th bit from the $sid as an index for the data
my $bit_value = substr($sid_bits, $bit_number-1, 1);
# calculate rotation from one data argument
my $rotation = $bit_number * ( $bit_value ? $rot_b : $rot_a );
# Rotate the $temp bitstring by $rotation bits
$temp = substr($temp, $rotation) . substr($temp, 0, $rotation);
# XOR the $temp with $sid_bits
$temp = $temp ^ $sid_bits;
# ... and XOR with the $v accumulator
$v = $v ^ $temp;
}
# Pack the bitstring back to binary data, return.
return pack("b*", $v);
}
这似乎是某种加密或散列。它主要根据以下几个论点混淆了第一个论点。 每个位依次用作索引,因此只使用两个额外的参数。第一个参数的长度在此操作中保持不变,但输出至少为两个字节。$sid
越大,使用的额外参数越多:至少一个,最多16个。
如果其中一个额外参数为零,则在该循环迭代期间不会发生旋转。单位化参数被认为是零。