/* * engima simulation * * author: Henry Tieman * * references: * "How Polish Mathematicians Deciphered the Enigma", Marian Rejewski, * Annals of the History of Computing, Vol 3, no 3, July 1981, Pg 213 ff * appendix by C. A. Devours. * * "Machine Cryptography and Modern Cryptanalysis", C.A. Deavours and L. * Kurth, Artech House, Dedham, Mass 1985. */ #include #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define LINE_LEN 80 /* * rotor data * reference "Machine Cryptography and Modern Cryptanalysis" pg. 100 * * note: rotor stepping is associated with each @PROGCODE = rotor instead * of position or being constant. */ #define NUM_ROTORS 5 char ref_rotor[27] = "YRUHQSLDPXNGOKMIEBFZCWVJAT"; char rotor[NUM_ROTORS][27] = { /* pre defined rotors */ "EKMFLGDQVZNTOWYHXUSPAIBRCJ", "AJDKSIRUXBLHWTMCQGZNPYFVOE", "BDFHJLCPRTXVZNYEIWGAKMUSQO", "ESOVPZJAYQUIRHXLNFTGKDCMWB", "VZBRGITYUPSDNHLXAWMJQOFECK", }; int step_data[NUM_ROTORS] = { 16, 4, 21, 9, 25 /* steps at: q, e, v, j, z */ }; /* * engima key default settings */ int order[3] = { 0, 1, 2}; /* rotor order, user input is +1 */ char ring[8] = { /* ring settings */ '\0', 'A', 'A', 'A', /* default: AAA */ '\0', '\0', '\0', '\0' }; int n_plugs = 0; /* number of plugs */ char plugs[80] = ""; /* plug string */ int pos[3] = { 0, 0, 0 }; /* rotor positions */ /* * simulation data and machine state data */ int data[8][26]; /* working array for machine */ int step[3]; /* steps corresponding to rotors */ int double_step; /* rotor 2 step twice */ /* * encipher - C implementation of the engima cipher function */ int encipher(int c) { int j; /* index for counting */ int idx; /* rotor index */ if (isalpha(c)) { pos[0] = (pos[0] + 1) % 26; /* first, advances the rotors */ if (pos[0] == step[0]) pos[1] = (pos[1] + 1) % 26; if (double_step) { pos[1] = (pos[1] + 1) % 26; pos[2] = (pos[2] + 1) % 26; double_step = FALSE; } if (pos[1] == step[1]) double_step = TRUE; c -= 'A'; /* start to encipher */ if (n_plugs != 0) c = data[0][c]; for (j=0;j<3;j++) /* do rotors forward */ { idx = (c + pos[j]) % 26; c = (c + data[j+1][idx]) % 26; } c = (data[4][c]) % 26; /* reflecting rotor */ for (j=0;j<3;j++) /* do rotors reverse */ { idx = (c + pos[2-j]) % 26; c = (c + data[j+5][idx]) % 26; } if (n_plugs != 0) c = data[0][c]; c += 'A'; } return(c); } /* * encipher_file - open and encipher a file */ void encipher_file(char *file_name) { FILE *fp; /* plaintext/ciphertext FILE pointer */ char line[LINE_LEN + 1]; /* input data line, inc. '\n' */ char *ret_val; /* value from fgets(), used for EOF check */ char c; /* character from data line */ int len; /* length of data line */ int idx; /* index/counter */ fp = fopen(file_name, "r"); ret_val = fgets(line, LINE_LEN, fp); while(ret_val != NULL) { len = strlen(line); for (idx=0;idx] \n\n", str); fprintf(stderr, "\tkeyfile has the form:\n"); fprintf(stderr, "\t\tn n n\t\t- for rotor order, 1 <= n <= 5\n"); fprintf(stderr, "\t\tx x x\t\t- for ring settings, x alpha\n"); fprintf(stderr, "\t\tn\t\t- number of plugs, 0 <= n <= 13\n"); fprintf(stderr, "\t\txx xx xx ...\t- plug letter pairs, one pair" " for each n\n"); fprintf(stderr, "\t\tx x x\t\t- initial rotor position, x alpha\n\n"); fprintf(stderr, "\toutput is stdout\n"); exit(0); } /* * main - the main function, nothing special here */ void main( int argc, char ** argv ) { char *infile; /* plaintext/ciphertext file name ptr */ if ((argc < 2) || (argc > 3)) usage(argv[0]); if (argc == 2) { infile = argv[1]; } else { infile = argv[2]; read_keyfile(argv[1]); } init_mach(); encipher_file(infile); } /* * end of engima simulation */