//This program is free software: you can redistribute it and/or modify it under the terms #of the GNU General Public License as published by the Free Software Foundation, either #version 3 of the License, or (at your option) any later version. //This program is distributed in the hope that it will be useful, but WITHOUT ANY #WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A #PARTICULAR PURPOSE. See the GNU General Public License for more details. //You should have received a copy of the GNU General Public License along with this #program. If not, see /* lucifer.c */ /* LUCIFER cipher: 128 bit key, 128 bit block */ /* Unless otherwise noted Copyright 1995 Willis E. Howard, III */ /* Willis E. Howard, III email: WEHoward@aol.com mail: POB 1473 Elkhart, IN 46515 */ /* under MSDOS, NMAKE /F LUCIFER.MAK all clean */ #include #include #include "crypt.h" #include "hex.h" #include "lucifer.h" #include "nhash.h" #include #include #include /* This routine uses the common interface to CRYPT.C. Generally, the name of this module becomes the name of the executable file. */ static int key_defined_lucifer = 0; /* Set to 1 after a valid key has been defined */ static int encrypt_or_decrypt_lucifer = ENCRYPTION_SELECT; static short mode = EN; static char key_string_lucifer[257]; static char actual_key[16]; static void process_key (char *, char *); static void makekey (char *, char *); /* cipher_doc: This array of strings must have two sections: CIPHER that describes the cipher used and KEY that describes how the key is defined and entered. */ static char *cipher_doc[] = { "CIPHER", " The program uses the LUCIFER cipher as developed by IBM.", " A 128 bit key is used to encrypt a 128 bit block.", "", " Because blocks of 16 bytes are processed, files that are not", " a multiple of 16 bytes long may increase slightly in size.", " Decrypted files may have additional spaces at the end.", " Use the -d option for decryption.", "", "KEY", " The key is an ASCII string. If you use more than one", " word in the phrase and give the key with the -k option", " on the command line, place the phrase within quotes.", " At most 256 characters will be used in the phrase.", " If the string evaluates to exactly 16 hex bytes such as", " \"F0AB 457E 006C E4AA 0DB3 57E3 AB52 2CC4\" with spaces", " ignored, then that exact 128 bit key is used. Otherwise,", " the ASCII characters are hashed to form a 128 bit key.", "", " If a key file exists, only the first line is read, and", " it is used as the key phrase.", "", " If there is no key phrase, you will be prompted for one.", NULL }; char ** crypt_help_lucifer () { return cipher_doc; /* return a pointer to the help strings */ } /* crypt_key: Get the key from the passed string (that may be a file name in some implementations) or from a key file name. Return 0 on success but exit on error. */ int crypt_key_lucifer (int key_type, char *key_text) { int i; char *s; FILE *fp; for (i=0; i<257; i++) /* initialize key string */ key_string_lucifer[i] = '\0'; if (key_type == KEY_FILE) /* a file name has been given */ { if ((fp = fopen (key_text, "r")) == NULL) { key_defined_lucifer = 0; return 0; } s = key_string_lucifer; i = 0; for (;;) { *s = fgetc (fp); if ((*s == '\n') || (*s == EOF)) { *s = '\0'; if (i == 0) { key_defined_lucifer = 0; break; } else { process_key (key_string_lucifer, actual_key); key_defined_lucifer = 1; break; } } else if (i == 255) { *++s = '\0'; process_key (key_string_lucifer, actual_key); key_defined_lucifer = 1; break; } s++; i++; } fclose (fp); return 0; } else if (key_type == KEY_IMMEDIATE) /* a key string has been given */ { if (!strcmp (key_text, "?")) /* prompt for key */ { printf ("Key: "); /* input key from stdin */ s = key_string_lucifer; i = 0; for (;;) { *s = fgetc (stdin); if ((*s == '\n') || (*s == EOF)) { *s = '\0'; process_key (key_string_lucifer, actual_key); key_defined_lucifer = 1; break; } else if (i == 255) { *++s = '\0'; process_key (key_string_lucifer, actual_key); key_defined_lucifer = 1; break; } s++; i++; } } else /* copy string up to 256 characters */ { strncpy (key_string_lucifer, key_text, 256); key_string_lucifer[256] = '\0'; process_key (key_string_lucifer, actual_key); key_defined_lucifer = 1; } return 0; } fprintf (stderr, "Error getting key\n"); exit (1); } /* crypt_key_erase: If a local copy of the key has been made, erase it from memory. This increases security that the key can not be obtained from an examination of memory. */ void crypt_key_erase_lucifer () { int i; for (i = 0; i < 257; i++) key_string_lucifer[i] = '\0'; for (i=0; i<16; i++) actual_key[i] = '\0'; key_defined_lucifer = 0; return; } /* crypt_select: If encryption and decryption require different ciphers, this routine defines the direction. Valid choices are ENCRYPTION_SELECT and DECRYPTION_SELECT. */ int crypt_select_lucifer (int selection) { if (selection == ENCRYPTION_SELECT) { if (encrypt_or_decrypt_lucifer == DECRYPTION_SELECT) { encrypt_or_decrypt_lucifer = ENCRYPTION_SELECT; mode = EN; if (key_defined_lucifer) /* if we have a key, recalculate */ process_key (key_string_lucifer, actual_key); } } if (selection == DECRYPTION_SELECT) { if (encrypt_or_decrypt_lucifer == ENCRYPTION_SELECT) { encrypt_or_decrypt_lucifer = DECRYPTION_SELECT; mode = DE; if (key_defined_lucifer) /* if we have a key, recalculate */ process_key (key_string_lucifer, actual_key); } } return encrypt_or_decrypt_lucifer; } /* crypt_file: encrypt or decrypt the source to the destination file. Do not exit from this routine. Return 0 on success and return 1 on error. Use an fprintf(stderr, ... ) to report the nature of the error and close any open files. This allows the main routine to do some cleanup before exiting. */ int crypt_file_lucifer (char *source, char *dest) { int i; int count = 16; /* block size */ char buffer[16]; FILE *infile; FILE *outfile; while (!key_defined_lucifer) crypt_key_lucifer (KEY_IMMEDIATE, "?"); if ((infile = fopen (source, "rb")) == NULL) { fprintf (stderr, "Can not open %s for reading.\n", source); return 1; } if ((outfile = fopen (dest, "wb")) == NULL) { fprintf (stderr, "Can not open %s for writing.\n", dest); fclose (infile); return 1; } for (i = 0; i < count; i++) buffer[i] = (char) 0x20; /* text files padded with spaces */ while (fread (buffer, sizeof (char), count, infile)) { lucifer ((unsigned char*)buffer); if (count != fwrite (buffer, sizeof (char), count, outfile)) { fprintf (stderr, "Could not write to %s\n", source); fclose (infile); fclose (outfile); return 1; } else { for (i = 0; i < count; i++) buffer[i] = (char) 0x20; } } fclose (infile); fclose (outfile); return 0; } /* Convert a string to a key */ static void process_key (char *s, char *key) { char string[257]; int i; int j; int shift = 1; int value = 0; int hex_count = 0; int nonhex_count = 0; int white_count = 0; /* zero string */ for (i=0; i<256; i++) string[i] = '\0'; /* check if a hex number or ascii string was entered */ for (i = 0; (i < 256) && *s; i++) { string[i] = *s++; if (ishex (string[i])) hex_count++; else if (string[i] == ' ') white_count++; else nonhex_count++; } string[i] = '\0'; /* either convert hex number or process ascii string */ if (hex_count == 32 && nonhex_count == 0) { hex_count = 0; for (i = 0; string[i] != '\0'; i++) { if ((value = hextoint (string[i])) != -1) { if (shift) { key[hex_count >> 1] = (unsigned char) value << 4; hex_count++; shift = 0; } else { key[hex_count >> 1] += (unsigned char) value; hex_count++; shift = 1; } } string[i] = '\0'; } } else { makekey (string, key); } /* select the key for use */ loadkey ((unsigned char*)key, mode); } static void makekey(char * s, char * key) //He cambiado char *s por unsigned char *s { int i; int block_count; unsigned char array[16]; unsigned char init[16] = { 0xa7, 0x6b, 0x32, 0xd4, 0x29, 0xa3, 0xe2, 0x2c, 0x97, 0x65, 0x12, 0x0e, 0x0d, 0xf1, 0xf5, 0x78 } ; if (!*s) block_count = 0; else { block_count = ( (strlen( s ) - 1 ) / 16 ) +1; if (block_count > 16) block_count = 16; } hash128 (block_count,(unsigned char*) s, init, array); for (i=0; i<16; i++) { key[i] = array[i]; array[i] = '\0'; } } /* LUCIFER is a cryptographic cipher developed by IBM in the early * seventies. It was a predecessor of the DES, and is much simpler * than that cipher. In particular, it has only two substitution * boxes. It does, however, use a 128 bit key and operates on * sixteen unsigned char data blocks... * * This implementation of LUCIFER was crafted by Graven Cyphers at the * University of Toronto, Canada, with programming assistance from * Richard Outerbridge. It is based on the FORTRAN routines which * concluded Arthur Sorkin's article "LUCIFER: A Cryptographic Algorithm", * CRYPTOLOGIA, Volume 8, Number 1, January 1984, pp22-42. The interested * reader should refer to that article rather than this program for more * details on LUCIFER. * * These routines bear little resemblance to the actual LUCIFER cipher, * which has been severely twisted in the interests of speed. They do * perform the same transformations, and are believed to be UNIX portable. * The package was developed for use on UNIX-like systems lacking crypto * facilities. They are not very fast, but the cipher is very strong. * The routines in this file are suitable for use as a subroutine library * after the fashion of crypt(3). When linked together with applications * routines they can also provide a high-level cryptographic system. * * -DENHANCE : modify LUCIFER by changing the key schedule and performing * an "autokeyed" encryption. These may improve the cipher. */ #ifndef DE #define DE 1 /* for separate compilation */ #endif static unsigned char Dps[64] = { /* Diffusion Pattern schedule */ 4, 16, 32, 2, 1, 8, 64, 128, 128, 4, 16, 32, 2, 1, 8, 64, 64, 128, 4, 16, 32, 2, 1, 8, 8, 64, 128, 4, 16, 32, 2, 1, 1, 8, 64, 128, 4, 16, 32, 2, 2, 1, 8, 64, 128, 4, 16, 32, 32, 2, 1, 8, 64, 128, 4, 16, 16, 32, 2, 1, 8, 64, 128, 4}; /* Precomputed S&P Boxes, Two Varieties */ static unsigned char TCB0[256] = { 87, 21, 117, 54, 23, 55, 20, 84, 116, 118, 22, 53, 85, 119, 52, 86, 223, 157, 253, 190, 159, 191, 156, 220, 252, 254, 158, 189, 221, 255, 188, 222, 207, 141, 237, 174, 143, 175, 140, 204, 236, 238, 142, 173, 205, 239, 172, 206, 211, 145, 241, 178, 147, 179, 144, 208, 240, 242, 146, 177, 209, 243, 176, 210, 215, 149, 245, 182, 151, 183, 148, 212, 244, 246, 150, 181, 213, 247, 180, 214, 95, 29, 125, 62, 31, 63, 28, 92, 124, 126, 30, 61, 93, 127, 60, 94, 219, 153, 249, 186, 155, 187, 152, 216, 248, 250, 154, 185, 217, 251, 184, 218, 67, 1, 97, 34, 3, 35, 0, 64, 96, 98, 2, 33, 65, 99, 32, 66, 195, 129, 225, 162, 131, 163, 128, 192, 224, 226, 130, 161, 193, 227, 160, 194, 199, 133, 229, 166, 135, 167, 132, 196, 228, 230, 134, 165, 197, 231, 164, 198, 203, 137, 233, 170, 139, 171, 136, 200, 232, 234, 138, 169, 201, 235, 168, 202, 75, 9, 105, 42, 11, 43, 8, 72, 104, 106, 10, 41, 73, 107, 40, 74, 91, 25, 121, 58, 27, 59, 24, 88, 120, 122, 26, 57, 89, 123, 56, 90, 71, 5, 101, 38, 7, 39, 4, 68, 100, 102, 6, 37, 69, 103, 36, 70, 79, 13, 109, 46, 15, 47, 12, 76, 108, 110, 14, 45, 77, 111, 44, 78, 83, 17, 113, 50, 19, 51, 16, 80, 112, 114, 18, 49, 81, 115, 48, 82}; static unsigned char TCB1[256] = { 87, 223, 207, 211, 215, 95, 219, 67, 195, 199, 203, 75, 91, 71, 79, 83, 21, 157, 141, 145, 149, 29, 153, 1, 129, 133, 137, 9, 25, 5, 13, 17, 117, 253, 237, 241, 245, 125, 249, 97, 225, 229, 233, 105, 121, 101, 109, 113, 54, 190, 174, 178, 182, 62, 186, 34, 162, 166, 170, 42, 58, 38, 46, 50, 23, 159, 143, 147, 151, 31, 155, 3, 131, 135, 139, 11, 27, 7, 15, 19, 55, 191, 175, 179, 183, 63, 187, 35, 163, 167, 171, 43, 59, 39, 47, 51, 20, 156, 140, 144, 148, 28, 152, 0, 128, 132, 136, 8, 24, 4, 12, 16, 84, 220, 204, 208, 212, 92, 216, 64, 192, 196, 200, 72, 88, 68, 76, 80, 116, 252, 236, 240, 244, 124, 248, 96, 224, 228, 232, 104, 120, 100, 108, 112, 118, 254, 238, 242, 246, 126, 250, 98, 226, 230, 234, 106, 122, 102, 110, 114, 22, 158, 142, 146, 150, 30, 154, 2, 130, 134, 138, 10, 26, 6, 14, 18, 53, 189, 173, 177, 181, 61, 185, 33, 161, 165, 169, 41, 57, 37, 45, 49, 85, 221, 205, 209, 213, 93, 217, 65, 193, 197, 201, 73, 89, 69, 77, 81, 119, 255, 239, 243, 247, 127, 251, 99, 227, 231, 235, 107, 123, 103, 111, 115, 52, 188, 172, 176, 180, 60, 184, 32, 160, 164, 168, 40, 56, 36, 44, 48, 86, 222, 206, 210, 214, 94, 218, 66, 194, 198, 202, 74, 90, 70, 78, 82}; static unsigned char Key[16], Pkey[128]; static int P[8] = {3, 5, 0, 4, 2, 1, 7, 6}; static int Smask[16] = {128, 64, 32, 16, 8, 4, 2, 1}; void lucifer (unsigned char *bytes) { register unsigned char *cp, *sp, *dp; register int val, *sbs, tcb, j, i; unsigned char *h0, *h1, *kc, *ks; h0 = bytes; /* the "lower" half */ h1 = &bytes[8]; /* the "upper" half */ kc = Pkey; ks = Key; for (i = 0; i < 16; i++) { tcb = *ks++; sbs = Smask; dp = Dps; sp = &h0[8]; #ifdef ENHANCE for (j = 0, cp = h1; j < 8; j++) tcb ^= *cp++; #endif for (j = 0; j < 8; j++) { if (tcb & *sbs++) val = TCB1[h1[j] & 0377]; else val = TCB0[h1[j] & 0377]; val ^= *kc++; for (cp = h0; cp < sp;) *cp++ ^= (val & *dp++); } /* swap (virtual) halves */ cp = h0; h0 = h1; h1 = cp; } /* REALLY swap halves */ dp = bytes; cp = &bytes[8]; for (sp = cp; dp < sp; dp++, cp++) { val = *dp; *dp = *cp; *cp = val; } return; } void loadkey (unsigned char *keystr,register int edf) { register unsigned char *ep, *cp, *pp; register int kc, i, j; unsigned char kk[16], pk[16]; cp = kk; pp = pk; ep = &kk[16]; while (cp < ep) { *cp++ = *keystr; for (*pp = i = 0; i < 8; i++) if (*keystr & Smask[i]) *pp |= Smask[P[i]]; keystr++; pp++; } cp = Key; pp = Pkey; kc = (edf == DE) ? 8 : 0; for (i = 0; i < 16; i++) { if (edf == DE) kc = (++kc) & 017; #ifdef ENHANCE *cp++ = kk[((kc == 0) ? 15 : (kc - 1))]; #else *cp++ = kk[kc]; #endif for (j = 0; j < 8; j++) { *pp++ = pk[kc]; if (j < 7 || (edf == DE)) kc = (++kc) & 017; } } return; } /* lucifer cks # < /dev/null * : 16 bytes : 32186510 6acf6094 87953eba 196f5a75 : * (-DENHANCE) : 378cfd5b bd54a07b 28513809 624e6071 : * (rwo/8412.03.18:10/V5.0) */ /************************ lucifer *******************************/