28
Playfair Cipher Encryption Program In Python
In this post I'm going to explain you how to code playfair cipher to encrypt plaintext to cipher. So this post is all about encryption program and will soon add decryption program in this series also so stay tuned!
If you don't know how the algorithm works checkout previous post in this series.
So Without further ado, LET'S BEGIN!!👨💻👩💻
Yes, You're right!
The Algorithm was consist of three steps:
- Convert plaintext into digraphs (i.e., into pair of two letters)
- Generate a Cipher Key Matrix
- Encrypt plaintext using Cipher Key Matrix and get ciphertext.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def convertPlainTextToDiagraphs (plainText): | |
# append X if Two letters are being repeated | |
for s in range(0,len(plainText)+1,2): | |
if s<len(plainText)-1: | |
if plainText[s]==plainText[s+1]: | |
plainText=plainText[:s+1]+'X'+plainText[s+1:] | |
# append X if the total letters are odd, to make plaintext even | |
if len(plainText)%2 != 0: | |
plainText = plainText[:]+'X' | |
return plainText |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def generateKeyMatrix (key): | |
# Intially Create 5X5 matrix with all values as 0 | |
# [ | |
# [0, 0, 0, 0, 0], | |
# [0, 0, 0, 0, 0], | |
# [0, 0, 0, 0, 0], | |
# [0, 0, 0, 0, 0], | |
# [0, 0, 0, 0, 0] | |
# ] | |
matrix_5x5 = [[0 for i in range (5)] for j in range(5)] | |
simpleKeyArr = [] | |
""" | |
Generate SimpleKeyArray with key from user Input | |
with following below condition: | |
1. Character Should not be repeated again | |
2. Replacing J as I (as per rule of playfair cipher) | |
""" | |
for c in key: | |
if c not in simpleKeyArr: | |
if c == 'J': | |
simpleKeyArr.append('I') | |
else: | |
simpleKeyArr.append(c) | |
""" | |
Fill the remaining SimpleKeyArray with rest of unused letters from english alphabets | |
""" | |
is_I_exist = "I" in simpleKeyArr | |
# A-Z's ASCII Value lies between 65 to 90 but as range's second parameter excludes that value we will use 65 to 91 | |
for i in range(65,91): | |
if chr(i) not in simpleKeyArr: | |
# I = 73 | |
# J = 74 | |
# We want I in simpleKeyArr not J | |
if i==73 and not is_I_exist: | |
simpleKeyArr.append("I") | |
is_I_exist = True | |
elif i==73 or i==74 and is_I_exist: | |
pass | |
else: | |
simpleKeyArr.append(chr(i)) | |
""" | |
Now map simpleKeyArr to matrix_5x5 | |
""" | |
index = 0 | |
for i in range(0,5): | |
for j in range(0,5): | |
matrix_5x5[i][j] = simpleKeyArr[index] | |
index+=1 | |
return matrix_5x5 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def indexLocator (char,cipherKeyMatrix): | |
indexOfChar = [] | |
# convert the character value from J to I | |
if char=="J": | |
char = "I" | |
for i,j in enumerate(cipherKeyMatrix): | |
# enumerate will return object like this: | |
# [ | |
# (0, ['K', 'A', 'R', 'E', 'N']), | |
# (1, ['D', 'B', 'C', 'F', 'G']), | |
# (2, ['H', 'I', 'L', 'M', 'O']), | |
# (3, ['P', 'Q', 'S', 'T', 'U']), | |
# (4, ['V', 'W', 'X', 'Y', 'Z']) | |
# ] | |
# i,j will map to tupels of above array | |
# j refers to inside matrix => ['K', 'A', 'R', 'E', 'N'], | |
for k,l in enumerate(j): | |
# again enumerate will return object that look like this in first iteration: | |
# [(0,'K'),(1,'A'),(2,'R'),(3,'E'),(4,'N')] | |
# k,l will map to tupels of above array | |
if char == l: | |
indexOfChar.append(i) #add 1st dimension of 5X5 matrix => i.e., indexOfChar = [i] | |
indexOfChar.append(k) #add 2nd dimension of 5X5 matrix => i.e., indexOfChar = [i,k] | |
return indexOfChar | |
# Now with the help of indexOfChar = [i,k] we can pretty much locate every element, | |
# inside our 5X5 matrix like this => cipherKeyMatrix[i][k] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def encryption (plainText,key): | |
cipherText = [] | |
# 1. Generate Key Matrix | |
keyMatrix = generateKeyMatrix(key) | |
# 2. Encrypt According to Rules of playfair cipher | |
i = 0 | |
while i < len(plainText): | |
# 2.1 calculate two grouped characters indexes from keyMatrix | |
n1 = indexLocator(plainText[i],keyMatrix) | |
n2 = indexLocator(plainText[i+1],keyMatrix) | |
# 2.2 if same column then look in below row so | |
# format is [row,col] | |
# now to see below row => increase the row in both item | |
# (n1[0]+1,n1[1]) => (3+1,1) => (4,1) | |
# (n2[0]+1,n2[1]) => (4+1,1) => (5,1) | |
# but in our matrix we have 0 to 4 indexes only | |
# so to make value bound under 0 to 4 we will do %5 | |
# i.e., | |
# (n1[0]+1 % 5,n1[1]) | |
# (n2[0]+1 % 5,n2[1]) | |
if n1[1] == n2[1]: | |
i1 = (n1[0] + 1) % 5 | |
j1 = n1[1] | |
i2 = (n2[0] + 1) % 5 | |
j2 = n2[1] | |
cipherText.append(keyMatrix[i1][j1]) | |
cipherText.append(keyMatrix[i2][j2]) | |
cipherText.append(", ") | |
# same row | |
elif n1[0]==n2[0]: | |
i1= n1[0] | |
j1= (n1[1] + 1) % 5 | |
i2= n2[0] | |
j2= (n2[1] + 1) % 5 | |
cipherText.append(keyMatrix[i1][j1]) | |
cipherText.append(keyMatrix[i2][j2]) | |
cipherText.append(", ") | |
# if making rectangle then | |
# [4,3] [1,2] => [4,2] [3,1] | |
# exchange columns of both value | |
else: | |
i1 = n1[0] | |
j1 = n1[1] | |
i2 = n2[0] | |
j2 = n2[1] | |
cipherText.append(keyMatrix[i1][j2]) | |
cipherText.append(keyMatrix[i2][j1]) | |
cipherText.append(", ") | |
i += 2 | |
return cipherText |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def main(): | |
#Getting user inputs Key (to make the 5x5 char matrix) and Plain Text (Message that is to be encripted) | |
key = input("Enter key: ").replace(" ","").upper() | |
plainText =input("Plain Text: ").replace(" ","").upper() | |
convertedPlainText = convertPlainTextToDiagraphs(plainText) | |
cipherText = " ".join(encryption(convertedPlainText,key)) | |
print(cipherText) | |
if __name__ == "__main__": | |
main() |
I hope the code with comments was actually sufficient to understand the logic.
Here's the repository link to the whole code file GitHub Repo
But if you still have any doubts feel free to mention below in discussion section, I would love to answer them.
Also drop a heart ❤ if you gained some knowledge!
28