/* 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 /* malloc free */ #include /* fprintf, fread, fwrite */ #include /* 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); }