/* grc.c Programmer: Paul Chubb Date: 8/7/95 Purpose: demonstrate German reduction codes of 1918 cf grc.txt Language: MSC 6.01a Maintenance: */ #include #include #include #include #include #define GRPSIZE 5 // size of code groups to output // matrix for encoding char acCodeArray[6][6] = {'F','L','1','A','O','2', 'J','D','W','3','G','U', 'C','I','Y','B','4','P', 'R','5','Q','8','V','E', '6','K','7','Z','M','X', 'S','N','H','0','T','9'}; int aiIndexer[26]; // gives the numeric for index string char acIndexer[7] = "ADFGVX"; // index string char acEncipher[36][3]; // gives matrix loc for each char char **acBilateral; // bilateral matrix int iKeySize,iNumRows, iRowIndex; // bilateral indexes #ifdef DEBUG // convert from char index to int index int CtoIIndex(char c) { int i; i = aiIndexer[c - 'A']; return (i); } #else #define CtoIIndex(c)(aiIndexer[(c - 'A')]) #endif #ifdef DEBUG // convert from int index to char index char ItoCIndexer(int i) { return acIndexer[i]; } #else #define ItoCIndexer(i)(acIndexer[i]) #endif /* ** BuildIndexer() ** ** build char to int index table ** */ void BuildIndexer(void) { int i; for(i = 0; i < 6; i++) aiIndexer[acIndexer[i] - 'A'] = i; } /* ** BuildEncipher() ** ** build cipher index pair table (reverse of acCodeArray) ** */ void BuildEncipher(void) { int i,j; for (i = 0; i < 6; i++) for (j = 0; j < 6; j++) { acEncipher[acCodeArray[i][j]][0] = ItoCIndexer(i); acEncipher[acCodeArray[i][j]][1] = ItoCIndexer(j); acEncipher[acCodeArray[i][j]][2] = 0; } } /* ** BuildBilat() ** ** initialise the bilateral structure ** */ void BuildBilat(char *pKey) { // update the key size and create the initial table // note first row is the key iRowIndex = iKeySize = strlen(pKey); iNumRows = 1; acBilateral = calloc(iNumRows,sizeof(char *)); if (acBilateral == NULL) { printf("Failed to allocate the bilateral matrix\n"); exit(2); } acBilateral[iNumRows - 1] = (char *)malloc(iKeySize); if (acBilateral[iNumRows - 1] == NULL) { printf("Failed to allocate the bilateral matrix\n"); exit(2); } // copy the key to the table strncpy(acBilateral[0],pKey,iKeySize); } /* ** AddCipher() ** ** build the bilateral table by one code group ** */ void AddCipher(char *pCode) { int i; for (i = 0; i < 2; i++) { // check there is space on this row if (iRowIndex >= iKeySize) { // add another row iNumRows++; acBilateral = (char **)realloc(acBilateral,iNumRows * sizeof(char *)); if (acBilateral == NULL) { printf("Failed to allocate the bilateral matrix\n"); exit(2); } acBilateral[iNumRows - 1] = (char *)malloc(iKeySize); if (acBilateral[iNumRows - 1] == NULL) { printf("Failed to allocate the bilateral matrix\n"); exit(2); } memset(acBilateral[iNumRows - 1],0,iKeySize); iRowIndex = 0; } acBilateral[iNumRows - 1][iRowIndex] = pCode[i]; iRowIndex++; } } /* ** OutputColumn() ** ** output the string in groups of four or less ** */ void OutputColumn(int iKeyDex,FILE *fpOut) { static int iCount = 0; int i; // output whole column for (i = 1; (acBilateral[i][iKeyDex] != 0) && (i < iNumRows); ) { // output in groups of four while((acBilateral[i][iKeyDex] != 0) && (iCount < GRPSIZE) && (i < iNumRows)) { fprintf(fpOut,"%c",acBilateral[i][iKeyDex]); iCount++; i++; } if (iCount >= GRPSIZE) { fprintf(fpOut," "); iCount = 0; } } } /* ** OutputBilat() ** ** Output the matrix following the other axis(column) in key character order ** */ void OutputBilat(FILE *fpOut) { int iKeyDex; char c; // find each in alpha order for (c = 'A'; c <= 'Z'; c++) { // check each column left to right for (iKeyDex = 0;iKeyDex < iKeySize; iKeyDex++) { // if the column matches output it if (c == acBilateral[0][iKeyDex]) OutputColumn(iKeyDex,fpOut); } } } /* ** Encipher() ** ** encodes the infile to outfile ** */ void Encipher(FILE *fpIn, FILE *fpOut) { int c; // build intermediate text c = getc(fpIn); while (!feof(fpIn)) { if (c == ' ') ;// printf("%c",c); else { // printf("%s",acEncipher[toupper(c)]); AddCipher(acEncipher[toupper(c)]); } c = getc(fpIn); } // printf("\n"); // output the bilat matrix on the other axis in key order OutputBilat(fpOut); } /* ** ReadColumn() ** ** Read a column ** */ void ReadColumn(int iKeyDex, FILE *fpIn, int iExtra) { int iDepth,i; // set up the read depth if (iKeyDex >= iExtra) iDepth = iNumRows - 1; else iDepth = iNumRows; // read it in for (i = 1; i < iDepth && !feof(fpIn); ) { acBilateral[i][iKeyDex] = (char)getc(fpIn); if (acBilateral[i][iKeyDex] != ' ') i++; } } /* ** ReadBilat() ** ** read in the file in the order it was written ** */ void ReadBilat(FILE *fpIn, int iExtra) { int iKeyDex; char c; for (c = 'A'; c <= 'Z'; c++) { // check each column left to right for (iKeyDex = 0;iKeyDex < iKeySize; iKeyDex++) { // if the column matches output it if (c == acBilateral[0][iKeyDex]) ReadColumn(iKeyDex,fpIn,iExtra); } } } /* ** CountCode() ** ** counts the valid code characters in a file ** */ int CountCode(FILE *fpIn) { int c,iCount = 0; while (!feof(fpIn)) { c = getc(fpIn); switch(c) { case 'A' : case 'D' : case 'F' : case 'G' : case 'V' : case 'X' : iCount++; } } fseek(fpIn,SEEK_SET,0); return iCount; } /* ** DeCipher() ** ** unencrypt the given string ** */ void DeCipher(FILE *fpIn, FILE *fpOut) { int iExtra,iLen,i,j; char c1,c2; // figure out the depth of the bilateral matrix iLen = CountCode(fpIn); iNumRows = iLen / iKeySize; iExtra = iLen % iKeySize; iNumRows++; if (iExtra) iNumRows++; else iExtra = iKeySize; // create the space acBilateral = (char **)realloc(acBilateral,iNumRows * sizeof(char *)); if (acBilateral == NULL) { printf("Failed to allocate the bilateral matrix\n"); exit(2); } for(i = 1; i < iNumRows; i++) { acBilateral[i] = (char *)malloc(iKeySize); if (acBilateral == NULL) { printf("Failed to allocate the bilateral matrix\n"); exit(2); } memset(acBilateral[i],0,iKeySize); } // read in the matrix ReadBilat(fpIn,iExtra); // decode the bilateral matrix into fpout j = 1; i = 0; while (j < iNumRows) { // get the next two characters if ((i >= iKeySize) || ((j == iNumRows - 1) && (i >= iExtra))) { j++; i = 0; continue; } c1 = acBilateral[j][i]; i++; if (i >= iKeySize) { j++; i = 0; if (j > iNumRows) { printf("Bad code text\n"); fcloseall(); exit(4); } } c2 = acBilateral[j][i]; i++; fprintf(fpOut,"%c",acCodeArray[CtoIIndex(c1)][CtoIIndex(c2)]); } } main (int argc, char *argv[]) { FILE *fpIn, *fpOut; if (argc != 5) { printf("GRC \n"); printf("\tWhere is either /E or /D for encode/decode\n"); printf("\t may be \"console\" and may be \"screen\"\n"); return 0; } // set up BuildIndexer(); BuildEncipher(); strupr(argv[4]); BuildBilat(argv[4]); // open the input file if (strcmpi(argv[2],"console") == 0) fpIn = stdin; else { fpIn = fopen(argv[2],"r"); if (fpIn == NULL) { printf("Failed to open file %s\n",argv[2]); return 1; } } // open the output file if (strcmpi(argv[3],"screen") == 0) fpOut = stdout; else { fpOut = fopen(argv[3],"w"); if (fpOut == NULL) { printf("Failed to open file %s\n",argv[3]); return 1; } } // do the work if (strcmpi(argv[1],"/E") == 0) Encipher(fpIn,fpOut); else if (strcmpi(argv[1],"/D") == 0) DeCipher(fpIn,fpOut); else printf("Unrecognised switch: %s\n",argv[1]); // close up fcloseall(); return 0; }