60 lines
1.9 KiB
Julia
60 lines
1.9 KiB
Julia
function playfair(key, txt, isencode=true, from = "J", to = "")
|
|
to = (to == "" && from == "J") ? "I" : to
|
|
|
|
function canonical(s, dup_toX=true)
|
|
s = replace(replace(uppercase(s), from => to), r"[^A-Z]" => "")
|
|
a, dupcount = [c for c in s], 0
|
|
for i in 1:2:length(a)-1
|
|
if s[i] == s[i + 1]
|
|
dup_toX && splice!(a, i+1+dupcount:i+dupcount, 'X')
|
|
dupcount += 1
|
|
end
|
|
end
|
|
s = String(a)
|
|
return isodd(length(s)) ? s * "X" : s
|
|
end
|
|
|
|
# Translate key into an encoding 5x5 translation matrix.
|
|
keyletters = unique([c for c in canonical(key * "ABCDEFGHIJKLMNOPQRSTUVWXYZ", false)])
|
|
m = Char.((reshape(UInt8.(keyletters[1:25]), 5, 5)'))
|
|
|
|
# encod is a dictionary of letter pairs for encoding.
|
|
encod = Dict()
|
|
|
|
# Map pairs in same row or same column of matrix m.
|
|
for i in 1:5, j in 1:5, k in 1:5
|
|
if j != k
|
|
encod[m[i, j] * m[i, k]] = m[i, mod1(j + 1, 5)] * m[i, mod1(k + 1, 5)]
|
|
end
|
|
if i != k
|
|
encod[m[i, j] * m[k, j]] = m[mod1(i + 1, 5), j] * m[mod1(k + 1, 5), j]
|
|
end
|
|
# Map pairs not on same row or same column.
|
|
for l in 1:5
|
|
if i != k && j != l
|
|
encod[m[i, j] * m[k, l]] = m[i, l] * m[k, j]
|
|
end
|
|
end
|
|
end
|
|
|
|
# Get array of pairs of letters from text.
|
|
canontxt = canonical(txt)
|
|
letterpairs = [canontxt[i:i+1] for i in 1:2:length(canontxt)-1]
|
|
|
|
if isencode
|
|
# Encode text
|
|
return join([encod[pair] for pair in letterpairs], " ")
|
|
else
|
|
# Decode text
|
|
decod = Dict((v, k) for (k, v) in encod)
|
|
return join([decod[pair] for pair in letterpairs], " ")
|
|
end
|
|
end
|
|
|
|
orig = "Hide the gold in...the TREESTUMP!!!"
|
|
println("Original: ", orig)
|
|
|
|
encoded = playfair("Playfair example", orig)
|
|
println("Encoded: ", encoded)
|
|
|
|
println("Decoded: ", playfair("Playfair example", encoded, false))
|