zentara, as promised I returned on the analysis of the codes to get a solution for this interworking. I don't know if multiple replies to a post is frowned, I make a new reply just to allow people "--" me on the other sloppy response :)

The initial key's state shuffling is different in the two programs, mainly due to the unpack/pack trick (at least in this I did not make a mistake). Quoting from perldoc -f pack:

The "h" and "H" fields pack a string that many nybbles (4-bit groups, representable as hexadecimal digits, 0-9a-f) long.

Each byte of the input field of pack() generates 4 bits of the result. For non- alphabetical bytes the result is based on the 4 least-significant bits of the input byte, i.e., on "ord($byte)%16". In par- ticular, bytes "0" and "1" generate nyb- bles 0 and 1, as do bytes "\0" and "\1". For bytes "a".."f" and "A".."F" the result is compatible with the usual hexadecimal digits, so that "a" and "A" both generate the nybble "0xa==10". The result for bytes "g".."z" and "G".."Z" is not well-defined.

Which I read as: "never, never, never count on it for evaluating portable shuffling keys in ARCFOUR implementations!".

The initial shuffling in the C program is even more akward, if possible: trying to interpret characters out of [0-9a-fA-F] as hexadecimal can lead to a situation in which the input key is virtually ignored (for example, key "zentara!" leads to "AAAAAAAA" in hex, much like "pppppppp"...).

To make both programs use the same shuffling data, I've simply used the input key - how good this system is I leave to the experts. This is straightforward in C, and requires a bit of map mangling in Perl (C has to be better for something. :-) Interworking has been tested on a very little test file, I leave further analysis to the interested ones.

The Perl modified code is the following. I've added strict and warnings just to be sure that there wasn't anything spoiling the output under the hood. The shuffling array @k is evaluated from the input key applying ord() to each input char. Yes, I could use unpack() instead of split().

#!/usr/bin/perl -0777 -- # $0 key infile > outfile # symmetric works both ways use strict; use warnings; my @k = map { ord($_) } split //, shift; my (@s, $x, $y); $y = 0; for ( my @t = @s = 0 .. 255 ) { $y = ( $k[ $_ % @k ] + $s[ $x = $_ ] + $y ) % 256; &S; } $x = $y = 0; for ( unpack( 'C*', <> ) ) { $x++; $y = ( $s[ $x %= 256 ] + $y ) % 256; &S; print pack( 'C', $_ ^= $s[ ( $s[$x] + $s[$y] ) % 256 ] ); } sub S { @s[ $x, $y ] = @s[ $y, $x ] }
The C code is virtually unmodified (for being a C code, of course). I added a couple of includes and removed some unneeded variables to shut the warnings off (-Wall was added for the same reasons I used strict and warnings). Of course, I eliminated the initial key mangling to make the program use it directly for state shuffling inside key.
/* gcc -o rc4 rc4.c -Wall */ #include <stdio.h> #include <string.h> #include <stdlib.h> #define buf_size 1024 typedef struct rc4_key { unsigned char state[256]; unsigned char x; unsigned char y; } rc4_key; #define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t void dumphex(unsigned char* data, unsigned long size) { unsigned long i; printf("%lu elementi\n\t", size); for (i = 0; i < size; ) { printf("%02X ", data[i]); if (! (++i % 16)) { printf("\n\t"); } } printf("\n"); } void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_ke +y *key) { unsigned char t; unsigned char index1; unsigned char index2; unsigned char* state; short counter; state = &key->state[0]; for(counter = 0; counter < 256; counter++) state[counter] = counter; key->x = 0; key->y = 0; index1 = 0; index2 = 0; for(counter = 0; counter < 256; counter++) { index2 = (key_data_ptr[index1] + state[counter] + index2) % 256; swap_byte(&state[counter], &state[index2]); index1 = (index1 + 1) % key_data_len; } } void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) { unsigned char t; unsigned char x; unsigned char y; unsigned char* state; unsigned char xorIndex; short counter; x = key->x; y = key->y; state = &key->state[0]; for(counter = 0; counter < buffer_len; counter++) { x = (x + 1) % 256; y = (state[x] + y) % 256; swap_byte(&state[x], &state[y]); xorIndex = (state[x] + state[y]) % 256; buffer_ptr[counter] ^= state[xorIndex]; } key->x = x; key->y = y; } int main(int argc, char* argv[]) { char seed[256]; char buf[buf_size]; int rd; rc4_key key; if (argc < 2) { fprintf(stderr,"%s key <in >out\n",argv[0]); exit(1); } strcpy(seed,argv[1]); prepare_key(seed, strlen(seed), &key); rd = fread(buf,1,buf_size,stdin); while (rd>0) { rc4(buf,rd,&key); fwrite(buf,1,rd,stdout); rd = fread(buf,1,buf_size,stdin); } return 0; }
As a final note, it has to be observed that the C approach seems more robust for large input files: read a chunk of data, encrypt and write. In the Perl version, slurp mode in input (according to "-0777") makes the process read the entire file in memory before analysing it. Transforming the encription cycle in the Perl source is left as an exercise for the memory impaired Monk.

Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

Don't fool yourself.

In reply to Re: perl encryptions keys vs. c by polettix
in thread perl encryptions keys vs. c by zentara

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.