Skip to content

Instantly share code, notes, and snippets.

@geoff-nixon
Forked from lnsp/arcfour.c
Created September 30, 2020 08:34
Show Gist options
  • Save geoff-nixon/ea370d9d01c4969d1b2c253ace7bf4a7 to your computer and use it in GitHub Desktop.
Save geoff-nixon/ea370d9d01c4969d1b2c253ace7bf4a7 to your computer and use it in GitHub Desktop.
a ARC4 encryption / decryption program
// ARC4 by Ronald L. Rivest
// Implementation by mooxmirror
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#define byte unsigned char
#define STDIN_BUFFER_SIZE 8
/*
How to use:
arcfour keyfile inputfile outputfile
*/
void swap(byte *arr, size_t i, size_t j)
{
byte tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/*
Generates a cipher sqeezed by the given key.
*/
byte *rc4(byte *key, byte *data, size_t key_length, size_t data_length)
{
assert(key != NULL && data != NULL);
size_t i, j, t;
byte *seg, *cip, n;
if (key_length < 5)
{
puts("ERROR: Key to small ( < 5 bytes)\n");
abort();
}
// generate seg bytes (KSA)
seg = calloc(256, sizeof(byte));
if (seg == NULL)
{
puts("ERROR: Out of memory\n");
abort();
}
for (i = 0; i < 256; i++)
{
seg[i] = i;
}
j = 0;
for (i = 0; i < 256; i++)
{
j = (j + seg[i] + key[i % key_length]) % 256;
swap(seg, i, j);
}
// sponge function (PRG)
cip = calloc(data_length, sizeof(byte));
if (cip == NULL)
{
puts("ERROR: Out of memory\n");
abort();
}
j = i = 0;
for (t = 0; t < data_length; t++)
{
i = (i + 1) % 256;
j = (j + seg[i]) % 256;
swap(seg, i, j);
n = seg[(seg[i] + seg[j]) % 256];
cip[t] = n ^ data[t];
}
return cip;
}
/*
Prints the bytes in hexadecimal format to the standard output stream.
*/
void print_bytes(byte *arr, size_t arr_length)
{
size_t i;
for (i = 0; i < arr_length; i++)
{
printf("%.2X ", arr[i]);
}
puts("\n");
}
/*
Reads all bytes from file.
Resizes the destination fitting for all the shit.
Returns the amount of bytes read.
*/
byte *bytes_from_file(FILE *file_ptr, size_t file_length)
{
char *file_str;
// allocate memory, throw error
file_str = calloc(file_length + 1, sizeof(char));
if (file_str == NULL)
{
puts("ERROR: Out of memory");
abort();
}
// read and close key file
fread(file_str, file_length, 1, file_ptr);
// copies the content to the destination
return (byte*) file_str;
}
size_t get_file_length(FILE *file_ptr)
{
size_t file_length;
fseek(file_ptr, 0, SEEK_END);
file_length = (size_t) ftell(file_ptr);
rewind(file_ptr);
return file_length;
}
int main(int argc, char *argv[])
{
// exit, if no key file exists
if (argc < 4)
{
puts("ERROR: No key file");
puts("USAGE: ./arcfour [key_file] [input_file] [output_file]");
abort();
}
FILE *key_file, *input_file, *output_file;
byte *key, *input, *output;
size_t key_length, input_length;
key_file = fopen(argv[1], "rb");
key_length = get_file_length(key_file);
key = bytes_from_file(key_file, key_length);
fclose(key_file);
input_file = fopen(argv[2], "rb");
input_length = get_file_length(input_file);
input = bytes_from_file(input_file, input_length);
fclose(input_file);
output = rc4(key, input, key_length, input_length);
output_file = fopen(argv[3], "wb");
fwrite(output, sizeof(byte), input_length, output_file);
fclose(output_file);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment