encrypt[plaintext_, polybius_, key_] := Module[{fraction, fractioned}, fraction = Thread[Characters[polybius] -> Tuples[Characters["ADFGVX"], 2]]; fractioned = Partition[Flatten[Characters[plaintext] /. fraction], UpTo[StringLength[key]]]; StringJoin[Flatten[Part[Flatten[fractioned, {2}], Ordering[Characters[key]]]]]]; decrypt[encrypted_, polybius_, key_] := Module[{perm, colLengths, fractioned, defraction}, perm = Ordering[Characters[key]]; colLengths = Length /@ Part[Flatten[Partition[Characters[encrypted], UpTo[Length[perm]]], {2}], perm]; fractioned = Flatten[Part[TakeList[Characters[encrypted], colLengths], InversePermutation[perm]], {2}]; defraction = Thread[Tuples[Characters["ADFGVX"], 2] -> Characters[polybius]]; StringJoin[Partition[Flatten[fractioned], 2] /. defraction]]; words = ReadList["unixdict.txt", Word]; key = Select[words, StringLength[#] == 9 && DuplicateFreeQ[Characters[#]] &] // RandomChoice; polybius = StringJoin@RandomSample@Characters["ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"]; plaintext = "ATTACKAT1200AM"; encrypted = encrypt[plaintext, polybius, key]; decrypted = decrypt[encrypted, polybius, key]; Print["Key: ", key]; Print["Polybius: ", polybius]; Print["Plaintext: ", plaintext]; Print["Encrypted: ", encrypted]; Print["Decrypted: ", decrypted];