Reputation: 1754
I'm trying my best to decipher some Perl code and convert it into C# code so I can use it with a larger program. I've been able to get most of it converted, but am having trouble with the following method:
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);
}
It is called like:
$sid = 0;
$rand = pack("H*", 'feedfacedeadbeef1111222233334444');
$skey = dynk($rand, $sid, 2, 3) ^ dynk(substr($dbuf, 0, 16), $sid, -1, -4);
I understand most of it except for this section:
$_*$_[($_[1]>>$_-1&1)+2]
I'm not sure how $_ is being used in that context? If someone could explain that, I think I can get the rest.
Upvotes: 3
Views: 117
Reputation: 57640
pack
and unpack
take a pattern, and some data, and transform this data according to the pattern. For example, pack "H*", "466F6F"
treats the data as a hex string of arbitrary length, and decodes it to the bytes it represents. Here: Foo
. The unpack
function does the reverse, and extracts data from a binary representation to a certain format.
The "b*"
pattern stands produces a bit string – unpack "b*", "42"
is "0010110001001100"
.
The v
represents one little-endian 16-bit integer.
The Perl is rather obfuscated. Here is a rewrite that simplifies some aspects.
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);
}
This seems to be some sort of encryption or hashing. It mainly jumbles the first argument according to the following ones. The larger Each bit is used in turn as an index, thus only two extra parameters are used. The length of the first argument stays constant in this operation, but the output is at least two bytes long.$sid
is, the more extra parameters are used: at least one, at most 16.
If one of the extra arguments is zero, no rotation takes place during that loop iteration. Unititializes arguments are considered to be zero.
Upvotes: 5