/* rotor.c */ /* This program performs encryption and decryption in the spirit of the rotor engine. Only alphabetic characters are * encrypted and case is ignored. * * Input is from stdin; Output is to stdout; Error is to stderr. * * One command line parameter is required of the form -dkey or -ekey where -e specifies encryption mode and -d specifies * decryption mode. The key is always three alphabetic characters which specify the initial configuration of the rotors. */ #include #define LET 26 #define DECRYPT 0 #define ENCRYPT 1 /* Function to calculate an encryption array from a given decryption array */ int dectoenc( int dec[], int enc[] ) { int i, j; /* loop counters */ for( i = 0; i < LET; i++ ) /* calculate each enc entry */ { for( j = 0; j < LET; j++ ) /* search for this connection */ { if( i == dec[(j + i) % LET] ) { enc[i] = j; /* found it */ break; } /* end if */ } /* end for */ if( j == LET ) return 1; /* didn't find an entry for enc */ } /* end for */ return 0; /* normal status */ } /* end dectoinc */ int main(int argc, char **argv) { /* Decryption arrays (rotor connections) */ int dec1[LET] = {0, 18, 9, 13, 25, 19, 7, 15, 6, 21, 3, 10, 4, 16, 8, 11, 22, 17, 1, 24, 5, 23, 12, 20, 2, 14}; int dec2[LET] = {0, 5, 3, 14, 2, 13, 11, 22, 4, 15, 1, 21, 18, 10, 17, 24, 23, 12, 6, 9, 7, 20, 8, 25, 16, 19}; int dec3[LET] = {7, 17, 25, 16, 19, 21, 9, 2, 12, 10, 3, 22, 4, 23, 8, 11, 24, 15, 18, 5, 14, 20, 1, 6, 0, 13}; /* Encryption arrays (rotor connection displacements) */ int enc1[LET]; int enc2[LET]; int enc3[LET]; int rot1, rot2, rot3; /* the 3 rotor displacements */ int next; /* next character read */ int mode; /* encryption or decryption? */ int out1in2, out2in3; /* temporaries for rotor calculations */ /* Check command line parameter */ if( (argc == 2) && (argv[1][0] == '-') && (argv[1][5] == '\0') && ((argv[1][1] == 'e') || (argv[1][1] == 'd')) ) { if( argv[1][1] == 'd' ) mode = DECRYPT; else { int errcode = 0; mode = ENCRYPT; /* calculate encs from decs */ errcode += dectoenc(dec1, enc1); errcode += dectoenc(dec2, enc2); errcode += dectoenc(dec3, enc3); if( errcode ) { fprintf(stderr, "\nOne of the rotors is incorrectly specified.\n"); return 1; } /* end if */ } /* end if */ /* Initialize the rotors based on key */ rot1 = tolower(argv[1][2]) - (int)'a'; rot2 = tolower(argv[1][3]) - (int)'a'; rot3 = tolower(argv[1][4]) - (int)'a'; /* Check validity of key */ if( (rot1 < 0) || (rot1 >= LET) || (rot2 < 0) || (rot2 >= LET) || (rot3 < 0) || (rot3 >= LET) ) { fprintf(stderr, "\nMalformed key: %c%c%c (e.g. xar).\n", argv[1][2], argv[1][3], argv[1][4]); return 1; } /* end if */ } else /* Malformed invocation */ { fprintf(stderr, "\nUsage: %s -[e|d]key\n", argv[0]); return 1; } /* end if */ /* Process input */ while( (next = tolower(getchar())) != EOF ) /* read to end of file */ { if( (next < (int)'a') || (next > (int)'z') ) { /* it's not a letter, so don't change it */ printf("%c", next); continue; } /* end if */ /* process this character */ next -= (int)'a'; /* normalize -- a = 0, b = 1, c = 2, ..., z = 25 */ if( mode == ENCRYPT ) /* use the rotors to encrypt it */ { out1in2 = (next + enc1[(next + rot1) % LET]) % LET; out2in3 = (out1in2 + enc2[(out1in2 + rot2) % LET]) % LET; printf("%c", (char)(((out2in3 + enc3[(out2in3 + rot3) % LET]) % LET) + (int)'a')); } else /* mode == DECRYPT */ { /* reverse the encryption process by using the rotors backwards */ out2in3 = (dec3[(next + rot3) % LET] + LET - rot3) % LET; out1in2 = (dec2[(out2in3 + rot2) % LET] + LET - rot2) % LET; printf("%c", (char)(((dec1[(out1in2 + rot1) % LET] + LET - rot1) % LET) + (int)'a')); } /* update (turn) the rotors */ rot3 = (rot3 + 1) % LET; if( rot3 == 0 ) { rot2 = (rot2 + 1) % LET; if( rot2 == 0 ) rot1 = (rot1 + 1) % LET; } /* end if */ } /* end while */ return 0; }