LonelyPilgrim has asked for the wisdom of the Perl Monks concerning the following question:
Hi again. Building, kind of, from my post the other day (I am moving in some form of logic here) — I am still fiddling with binary and bitwise operations. Here, I am trying to implement, or at least mimic, the JavaScript >> operator — signed/sign-propagating right bitwise shift. Perl's >> seems to be unsigned/zero-filling, behaving the same as the JavaScript >>>.
What I have below seems to give me what I want. It spits out the same results as the equivalent JavaScript — though my working knowledge of JavaScript is more that of a fiddler than a serious programmer. The below presumes (as I think the JavaScript operators do?) that I'm working with signed 32-bit integers; and for this instance I think that is probably fine. (What I'm trying to do with all this is implement Paj's JavaScript MD5 library in Perl, so my Perl script will encrypt my password appropriately and login to a website correctly.)
So, my questions:
#!/usr/bin/perl use strict; use warnings 'all'; use Config; my $longsize = $Config{longsize}; my $firstbit = ($longsize * 8) - 1; sub rshift { # Should be signed/sign-propagating right shift my ($x, $y) = @_; foreach (my $i = 0; $i < $y; $i++) { my $lbit = (($x & (1 << $firstbit)) != 0); $x = ($x >> 1) | ((1 << $firstbit) * $lbit); } return unpack("l>", pack("l>", $x)); } sub bin_test_print { printf("%032b = %d\n", $_[0], $_[0]); } my $x = 9; bin_test_print($x); $x = rshift($x, 2); bin_test_print($x); print "\n\n"; $x = -9; bin_test_print($x); $x = rshift($x, 2); bin_test_print($x); print "\n\n"; $x = 12345; bin_test_print($x); $x = rshift($x, 2); bin_test_print($x); print "\n\n"; $x = -12345; bin_test_print($x); $x = rshift($x, 2); bin_test_print($x);
UPDATE: Thanks, everybody, for all your help. Through repeatedly beating my head against this bitwise problem, and spending a whole lot of time dissecting code and playing with encryption routines -- I have figured out that, yes, I was, in fact, re-inventing the wheel. Not only did the Digest::MD5 package take care of what Paj's MD5 JavaScript module does, but I realized that the website I'm working with doesn't even use MD5 encryption for its login -- just simple Base64 encoding. The issue that was throwing me was that there were two passwords being sent with the form, an encrypted one (in fact just Base64) and a seemingly doubly-encrypted one -- which turned out, after painstakingly working through the bitwise math of Paj's whole module, figuring out exactly what he was doing to the bits at every step, merely to be the same thing -- the Base64 encoding of the password, only expanded to UTF16. D'oh! And once I realized this, I re-created it in Perl in five minutes with just the little bit of code below. But at least, now, and finally, I can say that I understand bitwise operations and binary representation of integers. Many thanks.
use strict; use warnings 'all'; use MIME::Base64; sub b64_password { return MIME::Base64::encode($_[0]); } sub b64_utf16_password { my @ascii = unpack("C*", $_[0]); my $utf16 = pack("v*", @ascii); my $base64_utf16 = MIME::Base64::encode($utf16); return $base64_utf16; }
|
|---|