/******************************************************************************* * * arc4.c -- a simple ARC4 implementation * by timdoug -- timdoug@gmail.com -- http://www.timdoug.com -- 2008-07-08 * see http://en.wikipedia.org/wiki/RC4 * ******************************************************************************** * * Copyright (c) 2008, timdoug(@gmail.com) -- except for the encryption algorithm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY timdoug ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL timdoug BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************** * * the encryption algorithm is unchanged (except for whitespace) from: * http://cypherpunks.venona.com/date/1994/09/msg00304.html * I have no idea about its copyright status or viability.... * * compile with: * gcc -Wall -Werror -pedantic -ansi -g -O2 arc4.c -o arc4 * * some example timings/usage (Mac OS X 10.5, MacBook Pro, 2.4GHz Core 2 Duo): * $ time ./arc4 mykey ubuntu.iso.enc * real 0m24.446s * user 0m10.512s * sys 0m4.294s * $ time ./arc4 mykey ubuntu.iso.out * real 0m43.177s * user 0m11.782s * sys 0m4.793s * $ md5 ubuntu.iso ubuntu.iso.out * MD5 (ubuntu.iso) = b78ef719e3361e726b89bab78c526ad0 * MD5 (ubuntu.iso.out) = b78ef719e3361e726b89bab78c526ad0 * *******************************************************************************/ #include #include #include #define BLOCK_SIZE 256 typedef struct rc4_key { unsigned char state[256]; unsigned char x; unsigned char y; } rc4_key; void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key); void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key); static void swap_byte(unsigned char *a, unsigned char *b); int main(int argc, char *argv[]) { unsigned char buf[BLOCK_SIZE]; rc4_key key; size_t len; if (argc != 2) { printf("usage: %s enckey outfile\n", argv[0]); exit(-1); } prepare_key((unsigned char *)argv[1], strlen(argv[1]), &key); do { rc4(buf, (len = fread(buf, 1, BLOCK_SIZE, stdin)), &key); fwrite(buf, 1, len, stdout); } while (len != 0); return 0; } void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) { 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 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; } static void swap_byte(unsigned char *a, unsigned char *b) { unsigned char swapByte; swapByte = *a; *a = *b; *b = swapByte; }