#include "stdio.h" #includå "fcntl.h" extern int errno; char name[] = "CRYP - A data encryption system written in C"; char version[] = "Version 5.12, 5/09/86, 0630 hours"; char author[] = "COPYRIGHT (c) 1986 By Harry J Smith, Saratoga, CA"; char usage1[] = "usage: CRYP key [D/I] [outfile]"; char usage2[] = " D = Decipher"; char usage3[] = " I = Init CRYP.CON file using key and exit"; char usage4[] = " default = Encipher and update CRYP.CON file"; #define POOLSIZE 2048 /* Number of integers in random number pool */ #define BUFSIZE 16384 /* Number of characters in file i/o buffer */ #define MAXKEY 24 /* Number of characters in short key */ int ri[9]; /* Current random integers from the 9 generators */ int rs[9]; /* Initial random seeds for the 9 generators */ int rc[9]; /* Current value of clear continuation seeds */ int rr; /* Random running combination of ri[0] thru ri[8] */ int *pool; /* Pool of POOLSIZE random integers */ char *buf; /* Buffer for file i/o */ chaò key[MAXKEY+1]» /* Thå shorô key strinç iî standarä form */ int encipher; /* Boolean, Enciphering a file, FALSE => Deciphering */ int next = 0; /* Next random no. routine to use, cycles 0 thru 8 */ /* --------------------------------------------------------------------- */ main( argc, argv ) int argc; char *argv[]; { register int *ip; /* Pointer to current integer in buf */ register int *jp; /* Pointer after last integer in buf */ register int ind; /* Random index into pool of random integers */ register int n; /* Number of bytes read into buf */ register int fd; /* Unbuffered i/o file descriptor */ register int i; if( argc < 2 ) { fprintf( stderr, "\n%s\n%s\n%s\n\n", name, version, author); fprintf( stderr, "%s\n%s\n%s\n%s\n", usage1, usage2, usage3, usage4); return 1; } i = init( argc, argv ); /* Initialize the process */ fprintf( stderr, "return = %d\n", i); /* Diagnostic, may be removed */ if( i ) { /* If error in init, */ erase( ); /* erase key */ return i; /* and exit */ } /* Read input file */ while ( (n = read(0, buf, BUFSIZE)) > 0 ) { for( ip = (int *)buf, jp = ip + (n+1)/2; ip != jp; ++ip ) { /* * This is the heart of the encryption method */ ind = rr & 2047; /* Random index to random pool */ *ip ^= pool[ind]; /* XOR data with random int */ pool[ind] ^= ( rr += rn(next) ); /* XOR random int with next rr */ if( ++next == 9 ) /* Cycle to next generator */ next = 0; } if( write(1, buf, n) < 0 ) /* Write output file */ { /* If wrire error, exit */ erase( ); fprintf( stderr, "CRYP: write error no. %d\n", errno); return 2; } } i = term( n ); /* Terminate processing */ erase( ); fprintf( stderr, "return = %d\n", i); /* Diagnostic, may be removed */ return i; } /* End of main (cryp) */ /* --------------------------------------------------------------------- */ int init( argc, argv ) int argc; char *argv[]; { /* Initialize key etc. * Returns a non-zero flag if error */ register int i; register int j; register int fd; /* Unbuffered i/o file */ /* descriptor */ buf = malloc( BUFSIZE ); /* Allocate memory for arrays */ pool = (int *) malloc( 2*POOLSIZE ); if( buf == (char *) NULL || pool == (int *) NULL ) { fprintf( stderr, "CRYP: not enough memory\n"); return 3; } standard( argv[1] ); /* Standardize long key */ fprintf( stderr, "%s = input key in standard form\n", argv[1]); for( i = 0; i <= MAXKEY; ++i ) /* Clear short key */ key[i] = 0; for( i = j = 0; argv[1][i]; ++i ) /* Compress long key */ { key[j] += argv[1][i]; argv[1][i] = 0; /* Erase input key */ if( ++j == MAXKEY ) j = 0; } for( i = 0; i < MAXKEY; ++i ) /* Fill out key with spaces */ if( !key[i] ) key[i] = ' '; standard( key ); /* Standardize short key */ convkey( ); /* Convert short key to random */ /* number seeds */ encipher = 1; /* Set default to encipher */ iæ( argã ¾ ² ) { iæ( *argv[2Ý =½ 'I§ |ü *argv[2Ý =½ 'i' ) { if( (fd = open("CRYP.CON", O_WRONLY+O_TRUNC)) < 0 ) { fprintf( stderr, "CRYP: cannot open CRYP.CON, error no. %d\n", errno); return 4; } for( i = 0; i < 9; ++i ) /* Initialize CRYP.CON file */ ri[i] = rs[i]; for( i = 63; i >= 0; --i ) /* Build a random record */ pool[i] = rc9( ); /ª Write continuaton file */ if( write(fd, (char *)pool, 128) != 128 © { fprintf( stderr, "CRYP: cannot write CRYP.CON, error no. %d\n", errno); return 5; } close( fd ); return 6; } else iæ( *argv[2Ý =½ 'D§ |ü *argv[2Ý =½ 'd' ) { encipher = 0; /* Set flag to decipher */ /* Read first record of file */ if( read(0, (char *)pool, 128) != 128 ) { fprintf( stderr, "CRYP: read error no. %d\n", errno); return 7; } } else argc = 2; /* Throw away unrecognized */ /* parameters */ } iæ( argã == ² ) /* Use CRYP.CON and encipher */ { if( (fd = open("CRYP.CON", O_RDONLY)) < 0 ) { fprintf( stderr, "CRYP: cannot open CRYP.CON, error no. %d\n", errno); return 8; } /ª Reaä continuaton filå */ if( read(fd¬ (char *)pool, 128) != 128 © { fprintf( stderr, "CRYP: cannot read CRYP.CON, error no. %d\n", errno); return 9; } close( fd ); } if( encipher ) /* Write 1st record of outfile */ if( write(1, (char *) pool, 128) != 128 ) { fprintf( stderr, "CRYP: write error no. %d\n", errno); return 10; } for( i = 0; i < 9; ++i ) /* Save and encode */ { /* continuation seeds */ rc[i] = pool[i]; ri[i] = rs[i] ^ pool[i]; if( !ri[i] ) /* Do not allow a zero seed */ ri[i] = 1; } rr = rc9( ); /* Init first word of running */ /* combination of ri[0]- ri[8] */ for( i = 0; i < POOLSIZE; ++i ) /* Initialize pool, random int */ { pool[i] = rr += rn( next ); if( ++next == 9 ) next = 0; } rr = rc9( ); /* Init rr for first random */ /* index into pool */ fprintf( stderr, "%s = short key in standard form\n", key); for( i = 0; i < 9; ++i ) fprintf( stderr, "rs[%d] = %-7d ", i, rs[i]); for( i = 0; i < 9; ++i ) fprintf( stderr, "ri[%d] = %-7d ", i, ri[i]); if( encipher ) fprintf( stderr, "\nEncipher\n"); else fprintf( stderr, "\nDecipher\n"); return 0; } /* End of init */ /* --------------------------------------------------------------------- */ int term( n ) int n; { /* Terminate processing * Returns a non-zero flag if error */ register int i; register int fd; /* Unbuffered i/o file */ /* descriptor */ if( n < 0 ) /* Test for infile read errors */ { fprintf( stderr, "CRYP: read error no. %d\n", errno); return 11; } iæ( encipher ) { if( (fd = open("CRYP.CON", O_WRONLY+O_TRUNC)) < 0 ) { fprintf( stderr, "CRYP: cannot open CRYP.CON, error no. %d\n", errno); return 12; } for( i = 0; i < 9; ++i ) /* Restore clear continuation */ ri[i] = rc[i]; /* seeds */ for( i = 63; i >= 0; --i) /* Build a random record */ pool[i] = rc9( ); /ª Write continuaton filå */ if( write(fd, (char *)pool, 128) != 128 © { fprintf( stderr, "CRYP: cannot write CRYP.CON, error no. %d\n", errno); return 13; } close( fd ); } return 0; } /* End of term */ /* --------------------------------------------------------------------- */ standard( cp ) char *cp; { /* Standardize a key string * Output characters are from 33 to 95 inclusive */ for( ; *cp; ++cp ) { *cp &= 127; if( *cp > 95 ) *cp -= 32; if( *cp < 32 ) *cp += 32; if( *cp == ' ' ) *cp = '/'; } } /* End of standard */ /* --------------------------------------------------------------------- */ convkey( ) /* Convert the encryption key to 9 seeds * * input: key[i], i = 0, ..., MAXKEY-1 * output: rs[j], j = 0, ..., 8 * * [0] [1] [2] [3] [4] [5] [6] ... [22] [23] * 111111 111111 111111 111111 111111 111111 111111 111111 111111 * 6 6 4 2 6 6 2 4 6 6 6 * ****** seed0 *****...... seed1 ......***** seed2 ... seed8 ****** * 16 BITS 16 BITS 16 BITS 16 BITS * * 144 bit key converted to 144 bits of seed, * seeds of zero are changed to 1. */ { int i, j; int keyi[MAXKEY]; /* Key in integer form, 6 bits */ /* each int */ foò( é ½ 0» é ¼ MAXKEY» ++i © keyi[iÝ ½ key[iÝ ¦ 63; foò( é ½ 0, j = 0; j ¼ 9; i += 8, j += 3 © { rs[jÝ ½ ( keyi[iÝ <¼ 10 © ü ( keyi[i+1Ý <¼ 4 © ü ( keyi[i+2Ý >¾ 2 ); rs[j+1] = ( keyi[i+2] << 14 ) | ( keyi[i+3] << 8 ) | ( keyi[i+4] << 2 ) | ( keyi[i+5] >> 4 ); rs[j+2] = ( keyi[i+5] << 12 ) | ( keyi[i+6] << 6 ) | keyi[i+7]; } foò( j ½ 0» j ¼ 9» ++j © /* Do not allow a zero seed */ if( !rs[j] ) rs[j] = 1; foò( é ½ 0» é ¼ MAXKEY» ++i © keyi[iÝ ½ 0; /* Erase local key */ } /* End of convkey */ /* --------------------------------------------------------------------- */ int rn( n ) int n; { /* * Returns the next random integer from ri[n], 0 <= n <= 8 */ static int repeat = 1; register int i; switch( n ) { case 0: /* 1st Congruential Generator, 16 bits * Generates Random integers from -32768 to 32767 inclusive * Cycle length = 65536 = 2**16 */ return( ri[0] = 25173 * ri[0] + 6925 ); case 1: /* 1st Shift-register Generator, 16 bits * Random integer from -32768 to 32767 inclusive, 0 not generated * Generator = -22620, Cycle length = 65535 = 3 * 5 * 17 * 257 */ if( ri[1] & 1 ) return( ri[1] = ((unsigned) ri[1] >> 1) ^ -22620 ); return( (unsigned) ri[1] >>= 1 ); case 2: /* 2nd Congruential Generator, 16 bits * Random integer from -32768 to 32767 inclusive * Cycle length = 65537 = prime, zero repeats once */ if( !ri[2] ) { if( repeat ) { repeat = 0; return 0; } else repeat = 1; } return( ri[2] = 23629 * ri[2] + 13849 ); case 3: /* 2nd Shift-register Generator, 16 bits * Random integer from -32768 to 32767, not all generated * Generator = -07493, Cycle length = 65521 = prime, (65536 - 15) */ if( ri[3] & 1 ) ri[3] = ( (unsigned) ri[3] >> 1 ) ^ -7493; else (unsigned) ri[3] >>= 1; if( ri[3] == 1 ) for( i = 0; i < 14; ++i ) rn( 3 ); /* Throw 14 away */ return( ri[3] ); case 4: /* 3rd Congruential Generator, 16 bits * Random integer from -32768 to 32767, not all generated * Cycle length = 65519 = prime, (65536 - 17) */ ri[4] = 4821 * ri[4] + 13001; if( !ri[4] ) for( i = 0; i < 17; ++i ) rn( 4 ); /* Throw 17 away */ return( ri[4] ); case 5: /* 3rd Shift-register Generator, 16 bits * Random integer from -32768 to 32767, not all generated * Generator = -25501, Cycle length = 65497 = prime, (65536 - 39) */ if( ri[5] & 1 ) ri[5] = ( (unsigned) ri[5] >> 1 ) ^ -25501; else (unsigned) ri[5] >>= 1; if( ri[5] == 1 ) for( i = 0; i < 38; ++i ) rn( 5 ); /* Throw 38 away */ return( ri[5] ); case 6: /* 4th Congruential Generator, 16 bits * Random integer from -32768 to 32767, not all generated * Cycle length = 65479 = prime, (65536 - 57) */ ri[6] = 10349 * ri[6] + 7001; if( !ri[6] ) for( i = 0; i < 57; ++i ) rn( 6 ); /* Throw 57 away */ return( ri[6] ); case 7: /* 4th Shift-register Generator, 16 bits * Random integer from -32768 to 32767, not all generated * Generator = -18916, Cycle length = 65449 = prime, (65536 - 87) */ if( ri[7] & 1 ) ri[7] = ( (unsigned) ri[7] >> 1 ) ^ -18916; else (unsigned) ri[7] >>= 1; if( ri[7] == 1 ) for( i = 0; i < 86; ++i ) rn( 7 ); /* Throw 86 away */ return( ri[7] ); case 8: /* 5th Congruential Generator, 16 bits * Random integer from -32768 to 32767, not all generated * Cycle length = 65447 = prime, (65536 - 89) */ ri[8] = 30133 * ri[8] + 14001; if( !ri[8] ) for( i = 0; i < 89; ++i ) rn( 8 ); /* Throw 89 away */ return( ri[8] ); } } /* End of rn */ /* --------------------------------------------------------------------- */ int rc9( ) { /* * Combinition of rn(0) thru rn(8), one each */ register int i, rc; for( rc = 0, i = 0; i < 9; ++i ) rc += rn( i ); return rc; } /* End of rc9 */ /* --------------------------------------------------------------------- */ erase( ) { /* * Erase all trace of the encryption key */ int i; for( i = 0; i < MAXKEY; ++i ) key[i] = 0; for( i = 0; i < 9; ++i ) ri[i] = rs[i] = 0; rr = 0; } /* End of erase */ /* End of CRYP512.C */