Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Verbose, compartmentalized solution in Clear category for Playfair Cipher by kkkkk
DEFAULT_KEYS = 'abcdefghijklmnopqrstuvwxyz0123456789'
ROW_LEN = 6
def create_key_table(key):
""" Create the table of Playfair cypher keys. """
# Prepare key - fill out the key table by adding the default letters
# and removing any duplicate letters or numbers.
all_keys = key + DEFAULT_KEYS
keys = [j for i,j in enumerate(all_keys) if j not in all_keys[:i]]
# Truncate the table to the expected length and create rows within
# the table.
return [keys[i:i+ROW_LEN] for i in range(0, ROW_LEN*ROW_LEN, ROW_LEN)]
def create_diagraphs(message):
""" Translate message into a list of diagraphs for Playfair cypher. """
# Prepare the message - covert it to lower case and remove punctuation
# and blanks.
message = list(filter(lambda x: x.isalnum() and x is not ' ',
message.lower()))
# Replace double letters with an 'x' inserted in between, but if the
# double letters are 'xx', insert a 'z'. Form into digraphs.
diagraphs = []
pair_started = False
last_letter = message[0]
for current_letter in message:
if pair_started:
if last_letter != current_letter:
diagraphs.append([last_letter, current_letter])
pair_started = False
elif last_letter == 'x':
diagraphs.append([last_letter, 'z'])
last_letter = current_letter
else:
diagraphs.append([last_letter, 'x'])
last_letter = current_letter
else:
last_letter = current_letter
pair_started = True
# Ensure the last element in the diagraph is a pair.
if pair_started:
if message[-1] == 'z':
diagraphs.append([last_letter, 'x'])
else:
diagraphs.append([last_letter, 'z'])
return diagraphs
def key_table_loc(key_table, letter):
""" Find letter's row, col index within Playfair key table. """
for idx, row in enumerate(key_table):
if letter in row:
row_idx = idx
break
for idx, col in enumerate(zip(*key_table)):
if letter in col:
col_idx = idx
break
return (row_idx, col_idx)
def cypher(key_table, diagraphs, adjustment):
""" Apply the Playfair cypher given the key table and diagraphs.
Encoding a message requires an adjustment of +1.
Decoding a message requires an adjustment of -1.
"""
encoded_msg = ''
for diagraph in diagraphs:
# Obtain x, y locations in key table for each character in
# diagraph pair.
first_loc = key_table_loc(key_table, diagraph[0])
second_loc = key_table_loc(key_table, diagraph[1])
# Both letters in same row? Use adjacent letters.
if first_loc[0] == second_loc[0]:
y_loc = first_loc[0]
x_loc = (first_loc[1] + adjustment) % ROW_LEN
encoded_msg += key_table[y_loc][x_loc]
x_loc = (second_loc[1] + adjustment) % ROW_LEN
encoded_msg += key_table[y_loc][x_loc]
# Both letters in same column? Use letters above or below.
elif first_loc[1] == second_loc[1]:
x_loc = first_loc[1]
y_loc = (first_loc[0] + adjustment) % ROW_LEN
encoded_msg += key_table[y_loc][x_loc]
y_loc = (second_loc[0] + adjustment) % ROW_LEN
encoded_msg += key_table[y_loc][x_loc]
# Letters neither in the same row or column? Find other corners
# of rectangle.
else:
encoded_msg += key_table[first_loc[0]][second_loc[1]]
encoded_msg += key_table[second_loc[0]][first_loc[1]]
return encoded_msg
def encode(message, key):
""" Encode the message using the Playfair cypher. """
key_table = create_key_table(key)
diagraphs = create_diagraphs(message)
return cypher(key_table, diagraphs, +1)
def decode(secret_message, key):
""" Decode the secret message using the Playfair cypher. """
key_table = create_key_table(key)
diagraphs = create_diagraphs(secret_message)
return cypher(key_table, diagraphs, -1)
May 8, 2015
Comments: