PROGRAM CodeBreaker; {Programmer: Gregory A. Perkins CS 65 Due: 12 December 1996} {This program accepts the name of a coded file, the number of possible key values in the polyalphabetic cypher used, and at least one "known" string within the coded text and decodes the encrypted file and displays it to the user} USES cs65; {Declarations Module} CONST MessMax = 255; CharRange = 95; TopCharCode = 126; KeySize = 10; TYPE Message = ARRAY[1..MessMax] OF CHAR; KeyCode = ARRAY[1..KeySize] OF INTEGER; VAR TestKey, i, Count, NumKeysNeeded, NumKeysFound : INTEGER; CharCycle, MessPointer, NumChecks : INTEGER; Found : BOOLEAN; FileName, SearchString : STRING; InFile : TEXT; Mess, MessAnswer : Message; Key : KeyCode; PROCEDURE Decrypt(Shift : INTEGER; VAR Code : CHAR); VAR NumCode : INTEGER; BEGIN NumCode := ORD(Code) + Shift; IF NumCode > TopCharCode THEN NumCode := NumCode - CharRange; Code := CHR(NumCode); END; BEGIN {program} {Needed information prompt module} WRITE('Enter the name of the file you would like to read : '); READLN(FileName); WRITE('Enter the number of encryption keys searching for : '); READLN(NumKeysNeeded); WRITE('Enter a known "string" in the encrypted text : '); READLN(SearchString); {Read File Module} RESET(InFile, FileName); i := 0; WHILE NOT EOF(InFile) DO BEGIN i := i + 1; READ(Infile, Mess[i]); END; {while loop} CLOSE(Infile); {Initialization module} TestKey := 1; {Current "key"/"offset" value used for decryption} NumKeysFound := 0; {Number of "keys" found so far} REPEAT {Status Display Module} WRITE('Testing Key Number : ', TestKey:1,'.'); WRITELN(' Found ', NumKeysFound:1, ' code keys.'); {Decrypt File Module} FOR Count := 1 TO i DO Decrypt(1, Mess[Count]); {Searching module} FOR CharCycle := 1 TO NumKeysNeeded DO BEGIN Found := FALSE; {"Found" is true when there is a possible answer found} MessPointer := 0; REPEAT {compare every char in message to char at CharCycle in SearchString} MessPointer := MessPointer + 1; {point to next char in the message} IF (Mess[MessPointer]) = (SearchString[CharCycle]) THEN BEGIN Found := TRUE; {set Found to true until proved otherwise} FOR NumChecks := 1 TO (((LENGTH(SearchString)) DIV NumKeysNeeded) - 1) DO IF (Mess[MessPointer + (NumKeysNeeded * NumChecks)] <> SearchString[CharCycle + (NumKeysNeeded * NumChecks)]) THEN Found := FALSE; {set Found to false if string values do not match} END; UNTIL ((Found) OR (MessPointer > i)); IF (MessPointer > i) THEN Found := FALSE; IF (Found) THEN BEGIN FOR Count := 1 TO i DO IF ((((Count - 1) MOD NumKeysNeeded) + 1) = (((MessPointer - 1) MOD NumKeysNeeded) + 1)) THEN MessAnswer[Count] := Mess[Count]; Key[(((MessPointer - 1) MOD NumKeysNeeded) + 1)] := TestKey; {store current key in appropriate place in array} NumKeysFound := NumKeysFound + 1; {increment number of keys found} END; {if structure} END; {for loop - CharCycle} TestKey := TestKey + 1; {Increment current "key"/"offset"} UNTIL ((NumKeysFound = NumKeysNeeded) OR (TestKey > CharRange)); {Answer Key Display Module} WRITELN; WRITELN('The encryption key is : '); FOR Count := 1 TO NumKeysNeeded DO WRITE(Key[Count]:1, ' '); WRITELN; {Decoded Message Display Module} WRITELN; WRITELN('The message is : '); FOR Count := 1 TO i DO WRITE(MessAnswer[Count]); WRITELN; END. {of program}