(** * Attacks affine cipher text string via analysis of char-frequency * **) function attackAffineCipher(cipherText: string): string; var i, j, a, b, c, d, cipherCharDeci, mostFreqCipherChar, secondMostFreqCipherChar, tempTopCount, modInv: integer; mostFreqGerChars: array of integer; cipherCharFrequency: array[95] of integer (* only ascii chars from 32 to 127 are allowed in plaintext: 95 chars in alphabet! *) begin mostFreqGerChars := ( ord(' ')-32, ord('e')-32, ord('n')-32, ord('i')-32, ord('s')-32); (* create array with number of frequence of each ciphertext char *) for i:=0 to length(cipherText)-1 do cipherCharDeci := ord(cipherText[i])-32; cipherCharFrequency[cipherCharDeci] := cipherCharFrequency[cipherCharDeci]+1; end; (* compute 1st most frequently ciphertext char *) for i:=0 to length(cipherCharFrequency)-1 do if cipherCharFrequency[i] > tempTopCount then tempTopCount := cipherCharFrequency[i]; mostFreqCipherChar := i; end; end; (* compute 2nd most frequently ciphertext char *) tempTopCount := -1; (* reset temporary counter *) for i:=0 to length(cipherCharFrequency)-1 do if i <> mostFreqCipherChar then if cipherCharFrequency[i] > tempTopCount then tempTopCount := cipherCharFrequency[i]; secondMostFreqCipherChar := i; end; end; end; writeln(); writeln("1st most frequently ciphertext char: ", concat(''',chr(mostFreqCipherChar+32),'''), " .. and 2nd most: ", concat(''',chr(secondMostFreqCipherChar+32),''')); writeln() writeln("starting decription:"); (* iterate all permutations of given most frequently german chars (extendable) *) for i:=0 to length(mostFreqGerChars)-1 do for j:=0 to length(mostFreqGerChars)-1 do modInv := mod_inverse(mostFreqGerChars[i]-mostFreqGerChars[j],95); (* skip loop if mod-inverse is not given (is also needed to eliminate coefficient of 'a' in upcoming equation to compute 'a') *) if modInv = 0 then continue; end; writeln("__________________________________________"); writeln("using y1 = ",mostFreqGerChars[i]," (",chr(mostFreqGerChars[i]+32),") and y2 = ",mostFreqGerChars[j]," (",chr(mostFreqGerChars[j]+32),")"); a := ((mostFreqCipherChar - secondMostFreqCipherChar) * modInv) mod 95; b := (secondMostFreqCipherChar - (mostFreqGerChars[j] * a)) mod 95; (* compare value of b with value of dedicated second equation to make paranoia sure *) if b = (mostFreqCipherChar - (mostFreqGerChars[i] * a)) mod 95 then writeln("using a: ",a," and b: ",b); (* compute coefficients 'c' and 'd' for upcoming decryption procedure *) c := mod_inverse(a,95); d := mod_inverse(a,95) * b mod 95; writeln("decrypted plain text: ", decrypt(cipherText,c,d)); end; end; end; end; (** * Encrypts plain text (ASCII 32 to 127) into affine chiffre * **) function encrypt(plainText: string): string; var i, a, b, y: integer; encryptedText: string; begin encryptedText := ""; a := random(95); while gcd(a,95) <> 1 do a := random(95); end; b := random(95); writeln("encypted plain text '", plainText, "' with a: ",a," and b: ",b); for i:=0 to length(plainText)-1 do y := ord(plainText[i]) - 32; y := (a * y + b) mod 95; y := y + 32; encryptedText := concat(encryptedText,chr(y)); end; return encryptedText; end; (** * Decrypts affine cipher chiffre into plain text via factor c and sub d * **) function decrypt(cipherText: string; c,d: integer): string; var decryptedText: string; i,x: integer; ch: char; begin decryptedText := ""; x := 0; for i:=0 to length(cipherText)-1 do x := ord(cipherText[i]) - 32; x := (c * x - d) mod 95; x := x + 32; decryptedText := concat(decryptedText,chr(x)); end; return decryptedText; end;