Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!

 TUCoPS :: Crypto :: enigma.txt Enigma encryption simulation

```
/*
* 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 <stdio.h>
#include <ctype.h>

#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<len;idx++)
{
c = line[idx];
if (isalpha(c))
{
c = encipher((int)(toupper(c)));
line[idx] = c;
}
}
printf("%s", line);
ret_val = fgets(line, LINE_LEN, fp);
}
fclose(fp);
}

/*
* init_mach - set up data according to the input data
*/

void
init_mach( void )
{
int i, j;                      /* indexes */
int ds;                        /* used during ring settings */
int u, v;                      /* temps for plugboard input */

/* setup rotor data */
for (j=0;j<26;j++)
data[4][j] = ((int)ref_rotor[j]-'A'+26)%26;

for (i=1;i<4;i++)
{
step[i-1] = step_data[order[i-1]];
for (j=0;j<26;j++)
{
data[i][j] = ((int)(rotor[order[i-1]][j])-'A' + 26) % 26;
data[8-i][data[i][j]] = j;
}
}

/* setup ring settings */
ring[7] = ring[1];
ring[6] = ring[2];
ring[5] = ring[3];
for (i=1;i<8;i++)
if (i != 4)
{
ds = (int)(ring[i]) - 'A';
if (ds != 0)
{
for (j=0;j<26;j++)
data[0][j] = data[i][j];
for (j=0;j<26;j++)
data[i][j] = data[0][(26-ds+j)%26];
}
}

/* setup plug data */
if (n_plugs != 0)
{
j = 0;
for (i=0;i<26;i++)
data[0][i] = i;
for (i=0;i<n_plugs;i++)
{
while (!isalpha(plugs[j]))
{
j++;
if (plugs[j] == '\0')
break;
}
u = toupper(plugs[j++]) - 'A';
v = toupper(plugs[j++]) - 'A';
data[0][u] = v;
data[0][u] = u;
}
}

/* convert all moving rotor data to displacements */
for (i=1;i<8;i++)
{
if (i!=4)
for (j=0;j<26;j++)
data[i][j] = (data[i][j] - j + 26) % 26;
}

/* setup rotor starting positions */
double_step = FALSE;              /* no previous rotor position */
/* input function has already done the rotor positions */
}

/*
* read_keyfile - a simple function to read in the key file
*/

void
{
FILE *kf;                         /* input key FILE pointer */
int num;                          /* dummy returned from fscanf() */
int idx;                          /* index/counter */
char a[3];                        /* dummy for input */

kf = fopen(str, "r");
num = fscanf(kf, "%d %d %d\n", &order[0], &order[1], &order[2]);
num = fscanf(kf, "%c %c %c\n", &ring[1], &ring[2], &ring[3]);
num = fscanf(kf, "%d\n", &n_plugs);

if (n_plugs != 0)
num = fscanf(kf, "%[^\n]\n", plugs);
num = fscanf(kf, "%c %c %c\n", &a[0], &a[1], &a[2]);

for (idx = 0; idx < 3; idx++)
{
(order[idx])--;
ring[idx+1] = toupper(ring[idx+1]);
pos[idx] = toupper(a[idx]) - 'A';
}
fclose(kf);
}

/*
* usage - function to print out the correct usage of the program
*/

void
usage( char *str )
{
fprintf(stderr, "usage: %s [<keyfile>] <infile>\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];
}

init_mach();
encipher_file(infile);
}

/*
* end of engima simulation
*/

```

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).