99 lines
2.3 KiB
Nim
99 lines
2.3 KiB
Nim
import pegs, strutils
|
|
|
|
type
|
|
Position = tuple[x, y: int]
|
|
Playfair = object
|
|
positions: array['A'..'Z', Position]
|
|
table: array[5, array[5, char]]
|
|
|
|
const None: Position = (-1, -1) # Default value for positions.
|
|
|
|
|
|
proc initPlayfair(key: string; jti: bool): Playfair =
|
|
|
|
for item in result.positions.mitems: item = None
|
|
|
|
var alphabet = key & "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
alphabet = if jti: alphabet.replace('J', 'I')
|
|
else: alphabet.replace("Q", "")
|
|
|
|
var k = 0
|
|
for ch in alphabet:
|
|
if result.positions[ch] == None:
|
|
result.table[k div 5][k mod 5] = ch
|
|
result.positions[ch] = (k mod 5, k div 5)
|
|
inc k
|
|
|
|
|
|
proc codec(playfair: Playfair; text: string; direction: int): string =
|
|
|
|
result.setLen(text.len)
|
|
|
|
for i in countup(0, text.high, 2):
|
|
var
|
|
(col1, row1) = playfair.positions[text[i]]
|
|
(col2, row2) = playfair.positions[text[i + 1]]
|
|
|
|
if row1 == row2:
|
|
col1 = (col1 + direction) mod 5
|
|
col2 = (col2 + direction) mod 5
|
|
elif col1 == col2:
|
|
row1 = (row1 + direction) mod 5
|
|
row2 = (row2 + direction) mod 5
|
|
else:
|
|
swap col1, col2
|
|
|
|
result[i] = playfair.table[row1][col1]
|
|
result[i + 1] = playfair.table[row2][col2]
|
|
|
|
|
|
proc encode(playfair: Playfair; text: string): string =
|
|
var
|
|
text = text
|
|
i = 0
|
|
|
|
while i < text.len:
|
|
if i == text.high:
|
|
if (text.len and 1) != 0:
|
|
text.add 'X'
|
|
elif text[i] == text[i + 1]:
|
|
text.insert("X", i + 1)
|
|
inc i, 2
|
|
|
|
result = playfair.codec(text, 1)
|
|
|
|
|
|
proc decode(playfair: Playfair; text: string): string =
|
|
result = playfair.codec(text, 4)
|
|
|
|
|
|
proc prompt(msg: string): string =
|
|
stdout.write msg
|
|
try:
|
|
result = stdin.readLine()
|
|
except EOFError:
|
|
echo ""
|
|
quit getCurrentExceptionMsg(), QuitFailure
|
|
|
|
|
|
when isMainModule:
|
|
|
|
var key: string
|
|
while key.len <= 6:
|
|
key = prompt("Enter an encryption key (min letters 6): ").toUpperAscii().replace(peg"[^A-Z]")
|
|
|
|
var text: string
|
|
while text.len == 0:
|
|
text = prompt("Enter the message: ").toUpperAscii().replace(peg"[^A-Z]")
|
|
|
|
var answer: string
|
|
while answer notin ["y", "n"]:
|
|
answer = prompt("Replace J with I? y/n: ").toLowerAscii()
|
|
let jti = (answer == "y")
|
|
|
|
let playfair = initPlayfair(key, jti)
|
|
let enc = playfair.encode(text)
|
|
let dec = playfair.decode(enc)
|
|
|
|
echo "Encoded message: ", enc
|
|
echo "Decoded message: ", dec
|