/* This file contains the source code for a cryptographic algorithm. If anyone feels like trying to break it, be my guest. To this end, I've included a file named CIPHER in the same place as this text file. Note: this implementation is slow. If anyone has any portable ideas for speeding it up, do feel free to drop me a line. The changes must not affect the output file's contents in any way. ---- A l g o r i t h m D e t a i l s ------ Here's a summary of the encryption algorithm: Generate a block of 256 integers, each containing a different prime number. (Actually, they don't need to be prime, but most of them should at least be odd, and greater than 50 on average). Read the plaintext P into a buffer PB. Read the key K into a buffer KB. For each byte in the key Locate the prime number PN corresponding to this byte of the key Rotate all the bits in the plaintext by PN bits (left) For each byte B in the buffer PB P[B] = P[B] ^ K[B % length(KB)] roF roF Write the plaintext, which is now really ciphertext, to the output file. The decryption process is of course the reverse. For bit rotation purposes, the key is read starting at the back. Complete C source code is provided, which should be taken as definitive. The text description above is a simple and thus perhaps inaccurate guide to the algorithm. The accompanying file, CIPHER, has been encrypted by this algorithm. */ /********** Source code starts here ***************/ /* * cdx.c * * Cryptographic algorithm copyright 1999-2000 Richard Heathfield * * Source code copyright 1999-2000 Richard Heathfield * * All rights reserved. * * You are hereby granted permission to copy this file onto * one computer only, for the purposes of study and compilation * and for no other purpose of any kind whatsoever. You are * not granted permission to amend this source code in any way. * You may not give copies of this file away, and you may not * sell copies of this file. * * Description: * This program implements the CDX-1 encryption algorithm. * (CDX-0 was an internal algorithm which has been discarded * for being insecure.) * * Usage: * Encryption: * enc plaintextfile ciphertextfile keyfile * Decryption: * enc ciphertextfile plaintextfile keyfile -d * * Assumptions: * CHAR_BIT must be 8, 16, or 32. * I'm not sure how this program would fare with sizeof(int) < 4 * * Portability: * Code tested on Microsoft Visual C++ 5.0 Pro, Borland C++ 5.02, * and Delorie C (gcc), all under Windows 95 DOS box. * * I see no reason why it shouldn't work under Linux/Unix, or indeed * under any platform or operating system. If you have problems, * let me know the circumstances (which OS (name and version), which * compiler (name and version)). Thanks. * * Credits: * Mathew Watson (debugging!) * Bob Stout's Snippets Collection (bit macros) */ #include #include #include #include #define MASK (CHAR_BIT-1) #define SHIFT ((CHAR_BIT==8)?3:((CHAR_BIT==16)?4:5)) #define BitOff(a,x) ((void)((a)[(x)>>SHIFT] &= ~(1 << ((x)&MASK)))) #define BitOn(a,x) ((void)((a)[(x)>>SHIFT] |= (1 << ((x)&MASK)))) #define BitFlip(a,x) ((void)((a)[(x)>>SHIFT] ^= (1 << ((x)&MASK)))) #define IsBit(a,x) ((a)[(x)>>SHIFT] & (1 << ((x)&MASK))) int GetFileLength(FILE *fp) { int len = 0; rewind(fp); while(fgetc(fp) != EOF) { len++; } rewind(fp); return len; } void XORBuffer(unsigned char *buffer, int DataLen, unsigned char *Key, int KeyLen) { int i; for(i = 0; i < DataLen; i++) { buffer[i] ^= Key[i % KeyLen]; } } void RotateBufferLeft(unsigned char *buffer, size_t size, int n) { int LeftBit, ThisBit, NewBit; size_t i; int iter; size_t numbytes; int numbits; unsigned char byte; n %= (size * CHAR_BIT); numbytes = n / CHAR_BIT; for(i = 0; i < numbytes; i++) { byte = buffer[0]; memmove(buffer, buffer + 1, size - 1); buffer[size - 1] = byte; } numbits = n % CHAR_BIT; for(iter = 0; iter < numbits; iter++) { LeftBit = IsBit(buffer, 0) ? 1 : 0; ThisBit = LeftBit; for(i = 0; i < (CHAR_BIT * size) - 1; i++) { NewBit = IsBit(buffer, (i + 1)) ? 1 : 0; if(NewBit != ThisBit) { BitFlip(buffer, i); } ThisBit = NewBit; } if(NewBit != LeftBit) BitFlip(buffer, i); } } void RotateBufferRight(unsigned char *buffer, size_t size, int n) { int RightBit, ThisBit, NewBit; size_t i; int iter; size_t numbytes; int numbits; unsigned char byte; n %= (size * CHAR_BIT); numbytes = n / CHAR_BIT; for(i = 0; i < numbytes; i++) { byte = buffer[size - 1]; memmove(buffer + 1, buffer, size - 1); buffer[0] = byte; } numbits = n % CHAR_BIT; for(iter = 0; iter < numbits; iter++) { RightBit = IsBit(buffer, (CHAR_BIT * size) - 1) ? 1 : 0; ThisBit = RightBit; for(i = (CHAR_BIT * size) - 1; i > 0; i--) { NewBit = IsBit(buffer, (i - 1)) ? 1 : 0; if(NewBit != ThisBit) { BitFlip(buffer, i); } ThisBit = NewBit; } if(NewBit != RightBit) BitFlip(buffer, 0); } } void Help(char *s) { if(!s || *s == 0) s = "enc"; printf("Usage:\n"); printf("%s inputfile outputfile keyfile [-d]\n", s); printf("-d specifies decryption\n"); } unsigned char *GetPass(char *Filename, unsigned int *n) { unsigned char *buff = NULL; FILE *fp; fp = fopen(Filename, "rb"); if(fp != NULL) { *n = (unsigned int)GetFileLength(fp); buff = malloc(*n); if(buff != NULL) { if(!fread(buff, *n, 1, fp)) { printf("Read error on key.\n"); exit(EXIT_FAILURE); } } else { printf("Memory error - key too big.\n"); } fclose(fp); } return buff; } int CheckArgs(int argc, char *argv[]) { if(argc < 4) { Help(argv[0]); return 0; } if(argc > 4 && strcmp(argv[4], "-d")) { printf("Syntax error.\n"); return 0; } return 1; } int encrypt(char *infile, char *outfile, char *keyfile, int decrypt) { static unsigned int PN_BLOCK[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619 }; unsigned char *Key; unsigned int KeyLen; FILE *fpIn, *fpOut; int DataLen; unsigned char *buffer; int i; fpIn = fopen(infile, "rb"); if(fpIn == NULL) { printf("Can't open input file.\n"); return EXIT_FAILURE; } fpOut = fopen(outfile, "wb"); if(fpOut == NULL) { fclose(fpIn); printf("Can't open output file.\n"); return EXIT_FAILURE; } DataLen = GetFileLength(fpIn); buffer = malloc(DataLen); if(buffer == NULL) { fclose(fpIn), fclose(fpOut); printf("Insufficient memory.\n"); return EXIT_FAILURE; } if(fread(buffer, DataLen, 1, fpIn) != 1) { fclose(fpIn), fclose(fpOut), free(buffer); printf("Read error.\n"); return EXIT_FAILURE; } Key = GetPass(keyfile, &KeyLen); if(Key == NULL) { fclose(fpIn), fclose(fpOut), free(buffer); printf("Key error.\n"); return EXIT_FAILURE; } printf("\nProcessing"); fflush(stdout); if(decrypt) { for(i = 0; i < (int)KeyLen; i++) { printf("."); fflush(stdout); XORBuffer(buffer, DataLen, Key, KeyLen); RotateBufferRight(buffer, DataLen, PN_BLOCK[Key[KeyLen - (i + 1)]]); } } else { for(i = 0; i < (int)KeyLen; i++) { printf("."); fflush(stdout); RotateBufferLeft(buffer, DataLen, PN_BLOCK[Key[i]]); XORBuffer(buffer, DataLen, Key, KeyLen); } } if(fwrite(buffer, DataLen, 1, fpOut) != 1) { printf("Write error.\n"); } fclose(fpIn), fclose(fpOut), free(buffer); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { int rc; int decrypt = 0; if(!CheckArgs(argc, argv)) { rc = EXIT_FAILURE; } else { if(argc > 4 && strcmp(argv[4], "-d") == 0) { decrypt = 1; } rc = encrypt(argv[1], argv[2], argv[3], decrypt); } return rc; }