The Playfair cipher is a multiple letter encryption cipher that uses a substitution technique.
The steps to implement it are as follows:
- Create a 5×5 matrix using the secrete key. In this matrix, I and J are in the same cell. you start filling the matrix with the key, then you use the alphabet. Letters are placed only once in the matrix.
- We encrypt the message using two letters each time. To do that, we follow four rules:
- When you get two letters, if they are the same letter, you add a “filler” in the middle. It can be the letter ‘x’.
- If the two letters fall in the same row of the matrix, you substitute them with the next letter in the row. Rows have a circular behavior. The next letter of the last in a row is the first letter in that row.
- If the two letters fall in the same column of the matrix, you substitute them with the next letter in the column (going down). Columns have a circular behavior. The next letter of the last in a column is the first letter in that column.
- If the two letters are not in the same row and column, then you substitute each letter by the letter in the same row and the column of the second letter.
Table of Contents
Keep reading for you to see examples of each step and rule, and the full Python code for the cipher.
Creating the 5×5 matrix
Let’s start with an example of how the matrix should look like.
If the secret key is “secret”, the matrix should look as in the picture below.
As you can see in the picture above, we first add each letter from the secret key (without repeating a letter). Notice after the ‘R’, we add the ‘T’ because the ‘E’ was previously added.
From there, we complete the matrix with the alphabet, without repeating letters and using ‘I’ and ‘J’ as the same character.
Separate same letters
Let’s assume we want to encrypt this message (plain text): “my secret message”. As per the second rule, we encrypt two letters at a time.
Let’s divide our plain text into a sequence of pairs of letters.
MY, SE, CR, ET, ME, SS, AG, EX
As you can see, we have the same letter together in a pair. Here, we use a “filler” to separate the two ‘S’.
MY, SE, CR, ET, ME, SX, SA, GE
Now we are ready to start the encryption.
First, we need to have the matrix. So, for easy reference, I’ll repeat the picture of the matrix in this section.
Let’s start the encryption.
- MY. Not in the same column and not in the same row. So, we use rule 4. ‘M’ is substituted by ‘L’, because ‘L’ is in the same row as M and in the same column as ‘Y’ (the other letter from the pair). ‘Y’ is substituted by ‘Z’, because ‘Z’ is in the same row as ‘Y’ and in the same column as ‘M’ (the other letter from the pair).
- SE. They are in the same row. So, ‘S’ is substituted for the next one in the row ‘E’, and ‘E’ is substituted by the next one in the row ‘C’. So, ‘SE’ is encrypted as ‘EC’.
- CR. It is encrypted as ‘RT’. Same rule as the previous case.
- ET. It is encrypted as ‘CS’. Same rule as the previous case. Notice that in this case ‘T’ is the last letter in the row, so the next is the first letter in the same row, ‘S’ in this case.
- ME. It is encrypted as ‘IT’ following rule 4 (same as ‘MY’).
- SX. It is encrypted as CV. Same rule as the previous example.
- SA. It is encrypted as ‘AH’ by following rule 3. The two letters fall in the same column.
- GE. It is encrypted as ‘BT’ following rule 4.
So, if we encrypt the message “my secret message” using the key “secret” and the Playfair cipher, we get the ciphertext “LZECRTCSITCVAHBT”.
Full Python code
See below the full python code for the Playfair cipher.
Creating the matrix.
# Create a 5x5 matrix using a secret key def create_matrix(key): key = key.upper() matrix = [[0 for i in range (5)] for j in range(5)] letters_added =  row = 0 col = 0 # add the key to the matrix for letter in key: if letter not in letters_added: matrix[row][col] = letter letters_added.append(letter) else: continue if (col==4): col = 0 row += 1 else: col += 1 #Add the rest of the alphabet to the matrix # A=65 ... Z=90 for letter in range(65,91): if letter==74: # I/J are in the same position continue if chr(letter) not in letters_added: # Do not add repeated letters letters_added.append(chr(letter)) #print (len(letters_added), letters_added) index = 0 for i in range(5): for j in range(5): matrix[i][j] = letters_added[index] index+=1 return matrix
Code to separate same letters.
#Add fillers if the same letter is in a pair def separate_same_letters(message): index = 0 while (index<len(message)): l1 = message[index] if index == len(message)-1: message = message + 'X' index += 2 continue l2 = message[index+1] if l1==l2: message = message[:index+1] + "X" + message[index+1:] index +=2 return message
Code to encrypt and decrypt a message
#Return the index of a letter in the matrix #This will be used to know what rule (1-4) to apply def indexOf(letter,matrix): for i in range (5): try: index = matrix[i].index(letter) return (i,index) except: continue #Implementation of the playfair cipher #If encrypt=True the method will encrypt the message # otherwise the method will decrypt def playfair(key, message, encrypt=True): inc = 1 if encrypt==False: inc = -1 matrix = create_matrix(key) message = message.upper() message = message.replace(' ','') message = separate_same_letters(message) cipher_text='' for (l1, l2) in zip(message[0::2], message[1::2]): row1,col1 = indexOf(l1,matrix) row2,col2 = indexOf(l2,matrix) if row1==row2: #Rule 2, the letters are in the same row cipher_text += matrix[row1][(col1+inc)%5] + matrix[row2][(col2+inc)%5] elif col1==col2:# Rule 3, the letters are in the same column cipher_text += matrix[(row1+inc)%5][col1] + matrix[(row2+inc)%5][col2] else: #Rule 4, the letters are in a different row and column cipher_text += matrix[row1][col2] + matrix[row2][col1] return cipher_text if __name__=='__main__': # a sample of encryption and decryption print ('Encripting') print ( playfair('secret', 'my secret message')) print ('Decrypting') print ( playfair('secret', 'LZECRTCSITCVAHBT', False))