Home » Blog » How to implement the Playfair cipher in python?

How to implement the Playfair cipher in python?


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:
    1. When you get two letters, if they are the same letter, you add a “filler” in the middle. It can be the letter ‘x’.
    2. 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.
    3. 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.
    4. 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.

5x5 Playfair matrix using the key "secret"
5×5 Playfair matrix using the key “secret”

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.

Encryption process

First, we need to have the matrix. So, for easy reference, I’ll repeat the picture of the matrix in this section.

5x5 Playfair matrix using the key "secret"
5×5 Playfair matrix using the key “secret”

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))

Related posts: