Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

RC4 is pissing me off.

Status
Not open for further replies.

Supra

Programmer
Dec 6, 2000
422
US
Alright, so I'm just trying to get a working version of RC4 encryption for use on my website. I wanted to use Crypt::RC4, but my host is GoDaddy and it's not supported. So I've been ruthlessly scrawling the internet looking for ways, and I came across 3. One was a rip of the Crypt::RC4 module and the other 2 were some sort of homebrew scripts. Anyway, neither of them work. I have a Javascript port of the RC4 algorithm, and my input key and encrypted data are decrypted flawlessly every time. However in all of these Perl versions, the decrypted key is garbled gibberish. Here's the most recent code I found:
Code:
	sub encrypt {
		my ($pwd, $data) = @_;

		@key;
		@box;
		$cipher = '';

		$pwd_length = length($pwd);
		$data_length = length($data);

		for ($i = 0; $i < 256; $i++)
		{
			$key[$i] = ord($pwd[$i % $pwd_length]);
			$box[$i] = $i;
		}
		for ($j = $i = 0; $i < 256; $i++)
		{
			$j = ($j + $box[$i] + $key[$i]) % 256;
			$tmp = $box[$i];
			$box[$i] = $box[$j];
			$box[$j] = $tmp;
		}
		for ($a = $j = $i = 0; $i < $data_length; $i++)
		{
			$a = ($a + 1) % 256;
			$j = ($j + $box[$a]) % 256;
			$tmp = $box[$a];
			$box[$a] = $box[$j];
			$box[$j] = $tmp;
			$k = $box[(($box[$a] + $box[$j]) % 256)];
			$cipher .= chr(ord($data[$i]) ^ $k);
		}
	return $cipher;
	}

	sub decrypt {
		my ($pwd, $data) = @_;
	return encrypt($pwd, $data);
	}
With my key and data, it returns:
Code:
Þ‰A£7]:ŠgWn’mÇ£ðÌë—E+M2'–_ž¨ÌumŸ¹ÅAz¥Ë0ü"‹4˜-»bžÀKO‹ qP’ ÃXJHä£ 9{ŠÍžÈ}hò,ôœ£å“T¹E5¢z†BlÊ}^‚>ºDgW¸Ø`®L½LI»Å5ïáXÛ3•\ÛË­›õ?
What the heck am I supposed to do with that? I've been working on this for HOURS and I haven't found a viable solution. I am really frustrated, so any help you can offer would really make my day.
 
Crypt::RC4 is pure perl, so can't you just copy it to your scripts directory and [tt]use lib[/tt]?

Yours,

fish

[&quot;]As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life was going to be spent in finding mistakes in my own programs.[&quot;]
--Maurice Wilkes, 1949
 
This version of your code will produce the test output for the strings suggested by Wikipedia.
Your error is to call [tt]$data[$i][/tt] as an element of string [tt]$data[/tt], but this is not allowed by perl: you must split the string into an array before doing so.
Code:
sub encrypt{
  use integer;
  my($pwd,$data)=@_;
  my@pwd=split(//,$pwd);
  my@data=split(//,$data);
  my(@key,@box);
  my$cipher='';
  my$pwd_length=length($pwd);
  my$data_length=length($data);
  for($i=0;$i<256;$i++){
    $key[$i]=ord($pwd[$i%$pwd_length]);
    $box[$i]=$i;
  }
  for($j=$i=0;$i<256;$i++){
    $j=($j+$box[$i]+$key[$i])&0xff;
    ($box[$i],$box[$j])=($box[$j],$box[$i]);
  }
  for($a=$j=$i=0;$i<$data_length;$i++){ 
    $a=($a+1)&0xff;
    $j=($j+$box[$a])&0xff;
    ($box[$a],$box[$j])=($box[$j],$box[$a]);
    $k=$box[($box[$a]+$box[$j])&0xff];
    $cipher.=chr(ord($data[$i])^$k);
  }
  return $cipher;
}
print map{uc(sprintf('%x',$_))}unpack("C*",encrypt('Key','Plaintext'));
print"\n";
print map{uc(sprintf('%x',$_))}unpack("C*",encrypt('Wiki','pedia'));
print"\n";
print map{uc(sprintf('%x',$_))}unpack("C*",encrypt('Secret','Attack at dawn'));

Franco
: Online tools for structural design
: Magnetic brakes for fun rides
: Air bearing pads
 
fishiface:

I used the Crypt::RC4 code already. Someone else had already stripped it from the module, so I used their code. It produced the same garbled text as above.

prex1:

Thanks a lot for explaining why it didn't work. That's invaluable to me because I'd rather learn than copy & paste. Unfortunately though, it returned the same garbled text as previous. I tried various things but to no avail.

Perhaps it would help to note that my key is Hex. I did try using $key = unpack("C*",$key) but I'm a little intermediate with Perl so I'm not sure if that's even correct. Anyway thanks a lot for your time guys. I really do appreciate it. I guess I need to figure this one out myself ;\
 
Ok I lied. I need help. I found some shorter, seemingly cleaner code.
Code:
sub RC4 {
	my $x = 0;
	my $y = 0;
	
	my $key = shift;
	my @k = unpack( 'C*', $key );
	my @s = 0..255;
	
	for ($x = 0; $x != 256; $x++) {
		$y = ( $k[$x % @k] + $s[$x] + $y ) % 256;
		@s[$x, $y] = @s[$y, $x];
	}

	$x = $y = 0;

	my $z = undef;
	
	for ( unpack( 'C*', shift ) ) {
		$x = ($x + 1) % 256;
		$y = ( $s[$x] + $y ) % 256;
		@s[$x, $y] = @s[$y, $x];
		$z .= pack ( 'C', $_ ^= $s[( $s[$x] + $s[$y] ) % 256] );
	}

return $z;
}
Now then, when I ENCRYPT the original string with the key, it works. The hash returned is correct, because it's the same as the one I've been using to decrypt. So why when I then try to decrypt the hash does it not work?! It returns the garbly gook instead! I'm completely and utterly confused, and I would REALLY appreciate if someone can set me straight.
 
FINALLY I figured it out, and by myself!

When I took the garbled text and viewed it in the built-in Hex editor in Notepad++, I noticed that the hex value was exactly the encrypted value I was looking for. So I knew my 'garbly gook' text was right, but just not in the correct format. A simple Google search led me to find my solution!
Code:
my $encrypted = [b]unpack('H*'[/b],RC4($key,$str));
Voila it works!

Thanks a ton for all your help!!!!!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top