This is a surprisingly difficult cipher to code since it uses a combination of substitution and transposition, but within a framework hat it is comparatively easy for humans to work with (once explained) – compressing alphabet into 5×5 grid, and using digraphs – but slightly unnatural from an algorithmic point of view… at least I think so.
import libraries and get inputs
from sets import Set
plaintext = raw_input("enter plaintext to encipher: ")
shift = raw_input("enter key, no repeated letters, and no combination that includes both i and j: ")
set up the grid, starts with Caesar shift on a key > 5 letters.
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i/j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
prepare keyphrase
shift = shift.lower()
shift = shift.replace(" ", "")
shift = shift.replace("i", "i/j")
shift = shift.replace("j", "i/j")
shift = [letter for letter in shift]
then second part
shift1 = Set(shift)
letters = Set([letter for letter in letters])
string_balance = letters - shift1
string_balance = list(string_balance)
string_balance = sorted(string_balance)
for letter in string_balance:
shift.append(letter)
Construct the Playfair grid
Playfair_Grid_horizontal:
w, h = 5, 5;
Playfair_Grid_horizontal = [[0 for x in range(w)] for y in range(h)]
x = 0
i = 0
while i < 5:
j = 0
while j < 5:
Playfair_Grid_horizontal[i][j] = shift[x]
x += 1
j += 1
i += 1
Playfair_Grid_vertical:
w, h = 5, 5;
Playfair_Grid_vertical = [[0 for x in range(w)] for y in range(h)]
j = 0
while j < 5:
i = 0
while i < 5:
Playfair_Grid_vertical[j][i] = Playfair_Grid_horizontal[i][j]
i += 1
j += 1
prepare text
plaintext = plaintext.lower()
plaintext = plaintext.replace(" ", "")
plaintext = [letter for letter in plaintext]
prepare digraphs
digraph_list = []
i = 0
while i< len(plaintext):
a = str(plaintext[i])
if i+1 == len(plaintext):
plaintext.append('x')
b = str(plaintext[i+1])
if a==b:
b = 'x'
c = a+b
digraph_list.append(c)
i += 1
else:
c = a+b
digraph_list.append(c)
i += 2
encipher plaintext digraphs
cipher_digraph_list = []
for digraph in digraph_list:
if digraph[0]=='i' or digraph[0]=='j':
digraph = [letter for letter in digraph]
digraph[0]='i/j'
elif digraph[1]=='i' or digraph[1]=='j':
digraph = [letter for letter in digraph]
digraph[1]='i/j'
marker = 0
z = 0
while z < 5:
if (digraph[0] in Playfair_Grid_horizontal[z]) and (digraph[1] in Playfair_Grid_horizontal[z]):
index = 0
for letter in Playfair_Grid_horizontal[z]:
if digraph[0]!=letter:
index += 1
if digraph[0]==letter:
break
if index == 4:
ciphertext_digraph1 = Playfair_Grid_horizontal[z][0]
else:
ciphertext_digraph1 = Playfair_Grid_horizontal[z][index+1]
index = 0
for letter in Playfair_Grid_horizontal[z]:
if digraph[1]!=letter:
index += 1
if digraph[1]==letter:
break
if index == 4:
ciphertext_digraph2 = Playfair_Grid_horizontal[z][0]
else:
ciphertext_digraph2 = Playfair_Grid_horizontal[z][index+1]
if ciphertext_digraph1=='i/j':
ciphertext_digraph1 = 'i'
elif ciphertext_digraph2=='i/j':
ciphertext_digraph2 = 'i'
cipher_digraph = ciphertext_digraph1+ciphertext_digraph2
cipher_digraph_list.append(cipher_digraph)
marker = 1
elif (digraph[0] in Playfair_Grid_vertical[z]) and (digraph[1] in Playfair_Grid_vertical[z]):
index = 0
for letter in Playfair_Grid_vertical[z]:
if digraph[0]!=letter:
index += 1
if digraph[0]==letter:
break
if index == 4:
ciphertext_digraph1 = Playfair_Grid_vertical[z][0]
else:
ciphertext_digraph1 = Playfair_Grid_vertical[z][index+1]
index = 0
for letter in Playfair_Grid_vertical[z]:
if digraph[1]!=letter:
index += 1
if digraph[1]==letter:
break
if index == 4:
ciphertext_digraph2 = Playfair_Grid_vertical[z][0]
else:
ciphertext_digraph2 = Playfair_Grid_vertical[z][index+1]
if ciphertext_digraph1=='i/j':
ciphertext_digraph1 = 'i'
elif ciphertext_digraph2=='i/j':
ciphertext_digraph2 = 'i'
cipher_digraph = ciphertext_digraph1+ciphertext_digraph2
cipher_digraph_list.append(cipher_digraph)
marker = 1
z +=1
if marker == 0:
list1 = []
list2 = []
for row in Playfair_Grid_horizontal:
if (digraph[0] in row):
list1 = row
for column in Playfair_Grid_vertical:
if (digraph[1])in column:
list2 = column
list1 = set(list1)
list2 = set(list2)
union_letter = list1.intersection(list2)
ciphertext_digraph1 = list(union_letter)
list3 = []
list4 = []
for row in Playfair_Grid_horizontal:
if (digraph[1] in row):
list3 = row
for column in Playfair_Grid_vertical:
if (digraph[0])in column:
list4 = column
list3 = set(list3)
list4 = set(list4)
union_letter = list3.intersection(list4)
ciphertext_digraph2 = list(union_letter)
ciphertext_digraph1 = ciphertext_digraph1[0]
ciphertext_digraph2 = ciphertext_digraph2[0]
if ciphertext_digraph1=='i/j':
ciphertext_digraph1 = 'i'
elif ciphertext_digraph2=='i/j':
ciphertext_digraph2 = 'i'
ciphertext_digraph1 = str(ciphertext_digraph1)
ciphertext_digraph2 = str(ciphertext_digraph2)
cipher_digraph = ciphertext_digraph1+ciphertext_digraph2
cipher_digraph_list.append(cipher_digraph)
else:
continue
then convert to ciphertext:
cipher_text = ''
for digraph in cipher_digraph_list:
digraph = digraph.upper()
digraph = str(digraph)
cipher_text += digraph+' '
cipher_text = cipher_text[:-1]
print "ciphertext is: ",cipher_text
gives:
ciphertext is: GD DO GD RQ AR KY GD HD NK PR DA MS OG UP GK IC QY
deciphering is symmetrical
ciphertext = raw_input("enter ciphertext to decipher: ")
shift = raw_input("enter key: ")
set up the grid, starts with Ceasar shift on a key > 5 letters.
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i/j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
prepare keyphrase
shift = shift.lower()
shift = shift.replace(" ", "")
shift = shift.replace("i", "i/j")
shift = shift.replace("j", "i/j")
shift = [letter for letter in shift]
Then second part
shift1 = Set(shift)
letters = Set([letter for letter in letters])
string_balance = letters - shift1
string_balance = list(string_balance)
string_balance = sorted(string_balance)
for letter in string_balance:
shift.append(letter)
Playfair_Grid_horizontal
w, h = 5, 5;
Playfair_Grid_horizontal = [[0 for x in range(w)] for y in range(h)]
x = 0
i = 0
while i < 5:
j = 0
while j < 5:
Playfair_Grid_horizontal[i][j] = shift[x]
x += 1
j += 1
i += 1
Playfair_Grid_vertical
<code?w, h = 5, 5;
Playfair_Grid_vertical = [[0 for x in range(w)] for y in range(h)]
j = 0
while j < 5:
i = 0
while i < 5:
Playfair_Grid_vertical[j][i] = Playfair_Grid_horizontal[i][j]
i += 1
j += 1
prepare ciphertext
ciphertext = ciphertext.lower()
ciphertext = ciphertext.split(' ')
decipher digraph by digraph
plaintext_digraph_list = []
for digraph in ciphertext:
if digraph[0]=='i' or digraph[0]=='j':
digraph = [letter for letter in digraph]
digraph[0]='i/j'
elif digraph[1]=='i' or digraph[1]=='j':
digraph = [letter for letter in digraph]
digraph[1]='i/j'
marker = 0
z = 0
while z < 5:
if (digraph[0] in Playfair_Grid_horizontal[z]) and (digraph[1] in Playfair_Grid_horizontal[z]):
index = 0
for letter in Playfair_Grid_horizontal[z]:
if digraph[0]!=letter:
index += 1
if digraph[0]==letter:
break
if index == 0:
plaintext_digraph1 = Playfair_Grid_horizontal[z][4]
else:
plaintext_digraph1 = Playfair_Grid_horizontal[z][index-1]
index = 0
for letter in Playfair_Grid_horizontal[z]:
if digraph[1]!=letter:
index += 1
if digraph[1]==letter:
break
if index == 0:
plaintext_digraph2 = Playfair_Grid_horizontal[z][4]
else:
plaintext_digraph2 = Playfair_Grid_horizontal[z][index-1]
if plaintext_digraph1=='i/j':
plaintext_digraph1 = 'i'
elif plaintext_digraph2=='i/j':
plaintext_digraph2 = 'i'
plaintext_digraph = plaintext_digraph1+plaintext_digraph2
plaintext_digraph_list.append(plaintext_digraph)
marker = 1
elif (digraph[0] in Playfair_Grid_vertical[z]) and (digraph[1] in Playfair_Grid_vertical[z]):
index = 0
for letter in Playfair_Grid_vertical[z]:
if digraph[0]!=letter:
index += 1
if digraph[0]==letter:
break
if index == 0:
plaintext_digraph1 = Playfair_Grid_vertical[z][4]
else:
plaintext_digraph1 = Playfair_Grid_vertical[z][index-1]
index = 0
for letter in Playfair_Grid_vertical[z]:
if digraph[1]!=letter:
index += 1
if digraph[1]==letter:
break
if index == 0:
plaintext_digraph2 = Playfair_Grid_vertical[z][4]
else:
plaintext_digraph2 = Playfair_Grid_vertical[z][index-1]
if plaintext_digraph1=='i/j':
plaintext_digraph1 = 'i'
elif plaintext_digraph2=='i/j':
plaintext_digraph2 = 'i'
plaintext_digraph = plaintext_digraph1+plaintext_digraph2
plaintext_digraph_list.append(plaintext_digraph)
marker = 1
z +=1
if marker == 0:
list1 = []
list2 = []
for row in Playfair_Grid_horizontal:
if (digraph[0] in row):
list1 = row
for column in Playfair_Grid_vertical:
if (digraph[1])in column:
list2 = column
list1 = set(list1)
list2 = set(list2)
union_letter = list1.intersection(list2)
plaintext_digraph1 = list(union_letter)
list3 = []
list4 = []
for row in Playfair_Grid_horizontal:
if (digraph[1] in row):
list3 = row
for column in Playfair_Grid_vertical:
if (digraph[0])in column:
list4 = column
list3 = set(list3)
list4 = set(list4)
union_letter = list3.intersection(list4)
plaintext_digraph2 = list(union_letter)
plaintext_digraph1 = plaintext_digraph1[0]
plaintext_digraph2 = plaintext_digraph2[0]
if plaintext_digraph1=='i/j':
plaintext_digraph1 = 'i'
elif plaintext_digraph2=='i/j':
plaintext_digraph2 = 'i'
plaintext_digraph1 = str(plaintext_digraph1)
plaintext_digraph2 = str(plaintext_digraph2)
plaintext_digraph = plaintext_digraph1+plaintext_digraph2
plaintext_digraph_list.append(plaintext_digraph)
else:
continue
and form the plaintext:
plain_text = ''
for digraph in plaintext_digraph_list:
digraph = digraph.upper()
digraph = str(digraph)
plain_text += digraph
print "plaintext is: ",plain_text
gives:
plaintext is: MEETMEATHAMXMERSMITHBRIDGETONIGHTX