obfuscator/Obfuscator-3_0/Obfuscate.c

163 lines
6.2 KiB
C

/* Copyright 2001, 2013 Neil Edelman, distributed under the terms of the
GNU General Public License, see copying.txt */
/* Friday, January 5, 2001 16:54 */
/* Friday, January 4, 2013 15:39 */
#include <stdlib.h> /* malloc free */
#include <stdio.h> /* fprintf, fread, fwrite */
#include <string.h> /* strlen */
/* constants */
static const char *programme = "Obfuscator";
static const char *year = "2001, 2013";
static const int versionMajor = 3;
static const int versionMinor = 0;
/* private */
static void encrypt(char *key);
static void decrypt(char *key);
static void usage(const char *argvz);
/** private (entry point) */
int main(int argc, char **argv) {
if(argc <= 2) {
usage(argv[0]);
return EXIT_SUCCESS;
}
if(strcmp(argv[1], "+") == 0) {
encrypt(argv[2]);
} else if(strcmp(argv[1], "-") == 0) {
decrypt(argv[2]);
} else {
usage(argv[0]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/** this is shifting the values one way, called "encrypt" */
static void encrypt(char *key) {
unsigned char buffer[1024], *bufPos;
const size_t buffer_size = sizeof buffer / sizeof(char);
unsigned char value[256], address[256];
unsigned char data, garb, addr, permute, parity = 0, byte;
int i, n;
int shift = 0, keyPos = 0;
const int keyLen = strlen(key);
size_t read;
/* determine how far the initial values in the table should be shifted */
for(i = 0; i < keyLen; i++) shift ^= key[i] << (i & 7);
/* if the password is "xxxxx" decypting with "xxx" might otherwise yield a
less-strongly encrypted file */
shift -= keyLen;
/* make a table of isomophic translation values */
for(i = 0; i < 256; i++) {
value[i] = i + shift;
address[i] = i - shift;
}
/* go through and mess with the file */
fprintf(stderr, "Progress: ");
while((read = fread(buffer, sizeof(char), buffer_size, stdin))) {
for(i = 0, bufPos = buffer; i < read; i++, bufPos++) {
data = *bufPos;
/* get the address in the valuetable of the data to write */
addr = address[(int)data];
/* address of the current character in the password */
byte = key[keyPos];
/* create an encryption seed based on the possword and file
position; passwords normally only contain alphanumeric values */
for(n = 0, permute = 0; n < keyLen; n++) permute ^= byte << (n & 7);
/* so that the key changes for the same glyph in the password across the file */
permute += ((char)i ^ (char)(i >> (key[keyLen - 1 - keyPos] & 7)));
/* encrypt the data to find where to look in the table */
garb = addr ^ permute;
/* use two parts of the password, and modify the operation based on previous data */
if(parity) garb += key[keyLen - 1 - keyPos];
else garb -= key[keyLen - 1 - keyPos];
/* write to the buffer */
*bufPos = garb;
/* set the parity for next time */
parity = data & 1;
/* now swap this result with the value of the original data in the translation table */
value[(int)data] ^= value[(int)garb];
value[(int)garb] ^= value[(int)data];
value[(int)data] ^= value[(int)garb];
/* and swap the addresses which point to these values */
address[(int)value[(int)data]] ^= address[(int)value[(int)garb]];
address[(int)value[(int)garb]] ^= address[(int)value[(int)data]];
address[(int)value[(int)data]] ^= address[(int)value[(int)garb]];
/* dynamically modify the password sequence */
key[keyPos] += value[(int)addr];
/* move to the next character in the sequence */
keyPos = (keyPos + 1) % keyLen;
}
if(fwrite(buffer, sizeof(char), read, stdout) != read) perror("writing");
fprintf(stderr, "|");
}
if(!feof(stdin)) perror("end of writing");
fprintf(stderr, " done.\n");
}
/** again, "decrypt" is a misnomer, it's just moving them the opposite way */
static void decrypt(char *key) {
unsigned char buffer[1024], *bufPos;
const size_t buffer_size = sizeof buffer / sizeof(char);
unsigned char value[256];
unsigned char data, garb, addr, permute, parity = 0, byte;
int i, n;
int shift = 0, keyPos = 0;
const int keyLen = strlen(key);
size_t read;
fprintf(stderr, "Progress: ");
for(i = 0; i < keyLen; i++) shift ^= key[i] << (i & 7);
shift -= keyLen;
for(i = 0; i < 256; i++) value[i] = i + shift;
while((read = fread(buffer, sizeof(char), buffer_size, stdin))) {
for(i = 0, bufPos = buffer; i < read; i++, bufPos++) {
garb = *bufPos;
byte = key[keyPos];
for(n = 0, permute = 0; n < keyLen; n++) permute ^= byte << (n & 7);
permute += ((char)i ^ (char)(i >> (key[keyLen - 1 - keyPos] & 7)));
/* reverse this part of the obfuscaption */
if(parity) addr = garb - key[keyLen - 1 - keyPos];
else addr = garb + key[keyLen - 1 - keyPos];
/* decrypt the garbage in addr to find where to look in the table */
addr ^= permute;
/* get the output data from this point in the table */
data = value[addr];
*bufPos = data;
parity = data & 1;
/* swap this result with the value of the original translation */
value[(int)data] ^= value[(int)garb];
value[(int)garb] ^= value[(int)data];
value[(int)data] ^= value[(int)garb];
/* dynamically modify the password sequence */
key[keyPos] += value[addr];
/* move to the next character in the sequence */
keyPos = (keyPos + 1) % keyLen;
}
if(fwrite(buffer, sizeof(char), read, stdout) != read) perror("writing");
fprintf(stderr, "|");
}
if(!feof(stdin)) perror("end of writing");
fprintf(stderr, " done.\n");
}
static void usage(const char *argvz) {
fprintf(stderr, "%s Copyright %s Neil Edelman\n", programme, year);
fprintf(stderr, "Version %d.%d.\n\n", versionMajor, versionMinor);
fprintf(stderr, "This program comes with ABSOLUTELY NO WARRANTY.\n");
fprintf(stderr, "This is free software, and you are welcome to redistribute it\n");
fprintf(stderr, "under certain conditions; see copying.txt.\n\n");
fprintf(stderr, "Usage: %s mode key\n\n", argvz);
fprintf(stderr, "mode either + or -; eg, a file encrypted with - and then re-encrypted\n");
fprintf(stderr, " with - will be decrypted by running + and +.\n\n");
fprintf(stderr, "key the secret stream cipher private-key\n\n");
fprintf(stderr, "Example:\n");
fprintf(stderr, "%s + \"12345\" < secret > secret_encrypted\n", programme);
fprintf(stderr, "%s - \"12345\" < secret_encrypted > secret_decrypted\n\n", programme);
}