1*39003Sbostic /* 2*39003Sbostic * program to to decrypt caesar(tm) cypher 3*39003Sbostic * (caesar is a trademark of the roman empire) 4*39003Sbostic * 5*39003Sbostic * to compile: 6*39003Sbostic * 7*39003Sbostic * cc decrypt.c -lm -o decrypt.c 8*39003Sbostic * 9*39003Sbostic * usage: 10*39003Sbostic * 11*39003Sbostic * decrypt [n] < file 12*39003Sbostic * 13*39003Sbostic * where n is an optional forced rotation. 14*39003Sbostic * 15*39003Sbostic * authors: Stan King, John Eldridge, based on algorithm suggested by 16*39003Sbostic * Bob Morris 17*39003Sbostic * 29-Sep-82 18*39003Sbostic * 19*39003Sbostic */ 20*39003Sbostic 21*39003Sbostic #ifdef SCCSID 22*39003Sbostic static char *SccsId = "@(#)caesar.c 1.7 4/16/85"; 23*39003Sbostic #endif /* SCCSID */ 24*39003Sbostic 25*39003Sbostic #include <stdio.h> 26*39003Sbostic #include <ctype.h> 27*39003Sbostic #include <math.h> 28*39003Sbostic extern char *calloc(); 29*39003Sbostic 30*39003Sbostic main(argc, argv) 31*39003Sbostic int argc; 32*39003Sbostic char *argv[]; 33*39003Sbostic { 34*39003Sbostic /* letter frequencies (taken from some unix(tm) documentation) */ 35*39003Sbostic /* (unix is a trademark of Bell Laboratories) */ 36*39003Sbostic static double stdf[ 26 ] = 37*39003Sbostic { 38*39003Sbostic 7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 39*39003Sbostic 6.39, 0.04, 0.42, 3.81, 2.69, 5.92, 6.96, 2.91, 40*39003Sbostic 0.08, 6.63, 8.77, 9.68, 2.62, 0.81, 1.88, 0.23, 41*39003Sbostic 2.07, 0.06, 42*39003Sbostic }; 43*39003Sbostic int obs[26]; 44*39003Sbostic int bufsize; 45*39003Sbostic int c, i, try; 46*39003Sbostic double dot, winnerdot; /* .. */ 47*39003Sbostic int winner, forced = 0; 48*39003Sbostic char *inbuf; 49*39003Sbostic 50*39003Sbostic bufsize = 0; 51*39003Sbostic if( argc > 1 ) 52*39003Sbostic sscanf( argv[1], "%d", &forced ); 53*39003Sbostic if( forced == 0 ) 54*39003Sbostic forced = -1000; 55*39003Sbostic 56*39003Sbostic inbuf = calloc( BUFSIZ, 1 ); 57*39003Sbostic 58*39003Sbostic /* adjust frequency table to weight low probs REAL low */ 59*39003Sbostic for (i=0; i<26; i++) { 60*39003Sbostic stdf[i] = log(stdf[i]) + log(26.0/100.0); 61*39003Sbostic } 62*39003Sbostic 63*39003Sbostic /* Decode each line separately */ 64*39003Sbostic for (;;) { 65*39003Sbostic for (i=0; i<=25; obs[i++]=0) 66*39003Sbostic ; 67*39003Sbostic 68*39003Sbostic /* get a sample of the text */ 69*39003Sbostic for( i = 0; i < BUFSIZ; i++ ) { 70*39003Sbostic if( (c = getchar()) == EOF ) { 71*39003Sbostic exit(0); 72*39003Sbostic } 73*39003Sbostic inbuf[i] = c; 74*39003Sbostic if (c == '\n') { 75*39003Sbostic bufsize = i+1; 76*39003Sbostic break; 77*39003Sbostic } 78*39003Sbostic if (islower(c)) 79*39003Sbostic obs[c-'a'] += 1; 80*39003Sbostic else if (isupper(c)) 81*39003Sbostic obs[c-'A'] += 1; 82*39003Sbostic } 83*39003Sbostic 84*39003Sbostic /* now "dot" the freqs with the observed letter freqs */ 85*39003Sbostic /* and keep track of best fit */ 86*39003Sbostic winner = 0; 87*39003Sbostic for (try = 0; try<26; try+=13) { 88*39003Sbostic dot = 0; 89*39003Sbostic for ( i=0; i<26; i++ ) { 90*39003Sbostic dot += obs[i] * stdf[ (i+try) % 26 ]; 91*39003Sbostic } 92*39003Sbostic /* initialize winning score */ 93*39003Sbostic if( try == 0 ) 94*39003Sbostic winnerdot = dot; 95*39003Sbostic if( dot > winnerdot ) { 96*39003Sbostic /* got a new winner! */ 97*39003Sbostic winner = try; 98*39003Sbostic winnerdot = dot; 99*39003Sbostic } 100*39003Sbostic } 101*39003Sbostic 102*39003Sbostic if (forced != -1000) 103*39003Sbostic winner = forced; 104*39003Sbostic 105*39003Sbostic /* print out sample buffer */ 106*39003Sbostic for( i = 0; i < bufsize; i++ ) 107*39003Sbostic putchar( rotate( inbuf[i], winner ) ); 108*39003Sbostic } 109*39003Sbostic } 110*39003Sbostic 111*39003Sbostic 112*39003Sbostic static int 113*39003Sbostic rotate( c, perm ) 114*39003Sbostic char c; 115*39003Sbostic int perm; 116*39003Sbostic { 117*39003Sbostic if (isupper(c)) { 118*39003Sbostic return 'A' + (c - 'A' + perm) % 26 ; 119*39003Sbostic } 120*39003Sbostic else if (islower(c)) { 121*39003Sbostic return 'a' + (c-'a'+perm) % 26 ; 122*39003Sbostic } 123*39003Sbostic else return c; 124*39003Sbostic } 125