I've made this some time ago for an assignment and I was wondering how it could be improved both in terms of performance and best practices for C code.
#include <stdio.h>
#include <string.h>
#define NR_ROTORS 3 /* Number of rotors */
#define ROTORSIZE 26 /* Rotor charset size */
#define INIT_CHAR 'A' /* initial char */
typedef struct Rotor Rotor;
struct Rotor {
int start;
int rotatePos;
int rotateCount;
char elemts[ROTORSIZE+1];
};
void rotorInit(Rotor *r);
void reflectorInit(int *reflector, char *conf);
int getConf(Rotor *r, int *reflector, int *messages);
int calcOffset(Rotor r, int offset);
void shiftRotors(Rotor *r);
int encrypt(Rotor *r, int *reflector, int rotate, int offset);
int mod(int a, int b);
void rotorInit(Rotor *r){
for(int i = 0; i < NR_ROTORS; i++) {
r[i].start = 0;
r[i].rotatePos = 0;
r[i].rotateCount = 0;
}
}
void reflectorInit(int *reflector, char *conf) {
for(int i = 0; i < ROTORSIZE; i++) {
for(int j = 0; j < ROTORSIZE; j++) {
if (conf[i] == conf[j] && reflector[i] == -1 && i!=j) {
reflector[i] = j;
reflector[j] = i;
break;
}
}
}
}
int getConf(Rotor *r, int *reflector, int *messages) {
for(int i = 0; i < NR_ROTORS; i++) {
scanf("%s %d", r[i].elemts , &r[i].rotatePos);
if (strlen(r[i].elemts) != ROTORSIZE)
return 1;
}
char conf[ROTORSIZE+1];
scanf("%s", conf);
reflectorInit(reflector, conf);
scanf("%d", messages);
if (strlen(conf) != ROTORSIZE || *messages < 0)
return 1;
return 0;
}
int calcOffset(Rotor r, int offset) {
return mod(offset + r.elemts[mod((r.start+offset),ROTORSIZE)] -
(INIT_CHAR + mod((r.start+offset),ROTORSIZE)),ROTORSIZE);
}
void shiftRotors(Rotor *r) {
r[NR_ROTORS-1].start = mod(++r[NR_ROTORS-1].start, ROTORSIZE);
r[NR_ROTORS-1].rotateCount++;
for (int i = NR_ROTORS-1; i > 0; i--) {
if (r[i].rotateCount == ROTORSIZE) {
r[i-1].start = mod(++r[i-1].start, ROTORSIZE);
r[i-1].rotateCount++;
r[i].rotateCount = 0;
}
}
}
int encrypt(Rotor *r, int *reflector, int rotate, int offset) {
for (int j = NR_ROTORS-1; j >= 0; j--)
offset = calcOffset(r[j], offset);
offset = reflector[offset];
for (int j = 0; j < NR_ROTORS; j++) {
for (int k = 0; k < ROTORSIZE; k++) {
if (INIT_CHAR + (mod((r[j].start+(offset)),ROTORSIZE))
== r[j].elemts[mod((r[j].start+k),ROTORSIZE)]) {
offset = k;
break;
}
}
}
return offset;
}
int mod(int a, int b) {
int r = a % b;
return r < 0 ? r + b : r;
}
int main (int argc , char* argv[]) {
Rotor rotors[NR_ROTORS];
int reflector[ROTORSIZE] = {[0 ... ROTORSIZE-1] = -1};
char initPos[NR_ROTORS+1];
int messages = 0, rotate = 0;
rotorInit(rotors);
if (getConf(rotors, reflector, &messages) == 1) {
fprintf (stderr, "Error: Bad input\n");
return 1;
}
for (int i = 0; i < messages; i++) {
initPos[NR_ROTORS] = 0;
scanf("%s\n", initPos);
if (initPos[NR_ROTORS] != '*')
rotate = 1;
else rotate = 0;
for(int j = 0; j < NR_ROTORS; j++) {
rotors[j].start = initPos[j] - INIT_CHAR;
rotors[j].rotateCount = ROTORSIZE -
(rotors[j].rotatePos - rotors[j].start+1);
rotors[j].rotateCount = mod(rotors[j].rotateCount,
ROTORSIZE);
}
int offset = 0;
char c = fgetc(stdin);
while (c != '\n') {
if (rotate == 1)
shiftRotors(rotors);
offset = c - INIT_CHAR;
printf("%c",INIT_CHAR
+ encrypt(rotors, reflector, rotate, offset));
c = fgetc(stdin);
}
printf("\n");
}
return 0;
}
In order to run the program you need to give it an initial rotor and reflector configurations. Input example:
EKMFLGDQVZNTOWYHXUSPAIBRCJ 16
AJDKSIRUXBLHWTMCQGZNPYFVOE 4
BDFHJLCPRTXVZNYEIWGAKMUSQO 21
ABCDEFGDIJKGMKMIEBFTCVVJAT
2
MCK
QMJIDOMZWZJFJR
ABC
ENCRYPTTHISMESSAGE
- The first 3 lines define the rotor configuration. The integer denotes the position in which the rotor causes the rotation of next rotor.
- Fourth line defines the reflector configuration.
- The fifth line is the number of messages you want to encrypt/decrypt
- Sixth line is the initial position (letter) of each rotor
- Seventh line is the actual message you want to encrypt/decrypt
Repeat six and seven depending on your input in the fifth line.