Cryptography - Rail Fence Cipher



A basic type of transposition cipher is the rail fence method. It is a kind of cryptographic process where the letters in a message are rearranged to form a new, seemingly unrelated message. The name of the approach comes from the message we write. When a text is created using the rail fence approach, the outcome is a zigzag pattern where each letter is spelled out before going on to the next row.

The message has to be written in the first row of a table in order to be encrypted using the rail fence approach. In addition, the second letter of the message needs to be written in the second row. This procedure must be continued until all of the message's letters have been written. Finally, we read the database row-wise to create the encrypted message.

Let us get started now discuss how to decode a message. Finding the number of rows in the table depending on the encrypted message's length is the first step in decrypting it. In addition, we have to write the encrypted message's initial letter in the first row, its second letter in the second row, and so on. This process has to be followed until all of the message's letters have been written.

All things considered, the rail fence method of encryption is really straightforward. It does not offer very strong security. Even someone with a basic understanding of cryptography can easily break it. However, at times when a high level of security is not necessary, it can continue to be useful for simple communication.

How Rail Fence Cipher Work?

This section will give a detailed explanation of the encryption and decryption processes used by the rail fence cipher.

Encryption

In order to decrypt a message using the rail fence cipher, we should first choose the number of rails, write the message diagonally in a zigzag pattern using that number, and then combine the letters along each rail from left to right. We will walk through each step with an example below.

Let us start by considering "RAILFENCE" as a plaintext. Let us now assume that there are three rails or fences, which is also known as a key. The zigzag pattern's height will be determined by the key. The message can then be written diagonally, from left to right, in a zigzag pattern −

Rail Fence Encryption

In order to create the ciphertext we will merge distinct rows, which in this case is "RFEALECIN."

Decryption

The number of rows and columns in the cipher text needs to be determined before we can start the decryption process. The length of the ciphertext is equal to the number of columns. After that, we need to determine how many rows-which function as the key-were encrypted.

Now that we know how many rows and columns there are, we can build the table and figure out where the letters should go because the rail fence cipher zigzags to encrypt the text diagonally from left to right −

Rail Fence Decryption

The points where letters from the ciphertext are inserted to create the plaintext are indicated by the *(asterisk). Beginning from the top row, which is the first "rail," we fill in the letters going left to right. Up until all of the asterisk spots are filled with letters from the ciphertext, we then carry on with this pattern on the following rail and so on −

Rail Fence Decryption

Let us finish the table above −

Rail Fence Decryption

Finally, we are able to combine the characters from left to right and top to bottom to get the Plaintext, "RAILFENCE."

Implementation

Now we are going to implement the Rail Fence Cipher using Python, Java, C++ and Javascript.

Implement using Python

So first we will create a code suing Python and implement Rail Fence Cipher. We will create two different functions one for encryption and other one for decryption. So see the code below −

Example

# Function to encrypt a message
def encrypt_rail_fence(plaintext, rails):

   # Create the matrix for cipher
   rail_matrix = [['\n' for i in range(len(plaintext))]
   for j in range(rails)]
	
   # Find the direction
   down_direction = False
   row, col = 0, 0
	
   for i in range(len(plaintext)):
		
      # Check the direction of flow
      # Reverse the direction if just filled the top or bottom rail
      if (row == 0) or (row == rails - 1):
         down_direction = not down_direction
		
         # Fill the corresponding alphabet
         rail_matrix[row][col] = plaintext[i]
         col += 1
		
         # Find the next row using direction flag
         if down_direction:
            row += 1
         else:
            row -= 1
	
   # Construct the cipher using the rail matrix
   cipher_text = []
   for i in range(rails):
      for j in range(len(plaintext)):
         if rail_matrix[i][j] != '\n':
            cipher_text.append(rail_matrix[i][j])
      return("" . join(cipher_text))
	
# Function to decrypt the cipher-text
# Function to decrypt the cipher-text
def decrypt_rail_fence(cipher, rails):

   # Create the matrix to cipher
   # plaintext - rows, length(cipher) - columns
   # Fill the rail matrix to distinguish filled spaces from blank ones
   rail_matrix = [['\n' for i in range(len(cipher))]
   for j in range(rails)]
	
   # Find the direction
   down_direction = None
   row, col = 0, 0
	
   for i in range(len(cipher)):
		
      # Check the direction of flow
      if row == 0:
         down_direction = True
      if row == rails - 1:
         down_direction = False
		
      # Place the cipher text in the rail matrix
      rail_matrix[row][col] = '*'
      col += 1
		
      # Find the next row using direction flag
      if down_direction:
         row += 1
      else:
         row -= 1
			
   # Reconstruct the rail matrix with cipher text
   index = 0
   for i in range(rails):
      for j in range(len(cipher)):
         if rail_matrix[i][j] == '*' and index < len(cipher):
            rail_matrix[i][j] = cipher[index]
            index += 1
				
   # Read the rail matrix in zig-zag manner to construct the resultant text
   result = []
   row, col = 0, 0
   for i in range(len(cipher)):
		
      # Check the direction of flow
      if row == 0:
         down_direction = True
      if row == rails - 1:
         down_direction = False
			
      # Add characters from the rail matrix to the result
      if rail_matrix[row][col] != '*':
         result.append(rail_matrix[row][col])
         col += 1
			
      # Find the next row using direction flag
      if down_direction:
         row += 1
      else:
         row -= 1
	
      return ''.join(result)

# Driver code
if __name__ == "__main__":
   print("First Encrypted Text: ", encrypt_rail_fence("Hello Tutorialspoint", 2))
   print("Second Encrypted Text: ", encrypt_rail_fence("Simple Text", 3))
   print("Third Encrypted Text: ", encrypt_rail_fence("I am great Cipher", 5))
   # Decryption of the cipher-text
   print("First Decrypted Text: ", decrypt_rail_fence("HloTtrasonel uoilpit", 2))
   print("Second Decrypted Text: ", decrypt_rail_fence("SleipeTxm t", 3))
   print("Third Decrypted Text: ", decrypt_rail_fence("Iar etear hmgCp i", 5))

Following is the output of the above example −

Input/Output
First Encrypted Text:  HloTtrason
Second Encrypted Text:  S
Third Encrypted Text:  I
First Decrypted Text:  H
Second Decrypted Text:  S
Third Decrypted Text:  I

Implement using Java

Now we will implement the Rail fence Cipher using Java programming langugage. We will use the same approach what we have used in the Python. Here we will use Arrays library of Java for the purpose of Rail matrix. So the code is as follows −

Example

import java.util.Arrays;
public class CustomRailFence {

   //Encrypt a message
   public static String encryptMessage(String plaintext, int rails) {

      // Create the matrix
      char[][] railMatrix = new char[rails][plaintext.length()];

      // Filling the rail matrix
      for (int i = 0; i < rails; i++)
      Arrays.fill(railMatrix[i], '\n');

      boolean dirDown = false;
      int row = 0, col = 0;

      for (int i = 0; i < plaintext.length(); i++) {

         // Check the direction of flow
         if (row == 0 || row == rails - 1)
         dirDown = !dirDown;

         // Fill the corresponding alphabet
         railMatrix[row][col++] = plaintext.charAt(i);

         // Find the next row using direction flag
         if (dirDown)
            row++;
         else
            row--;
      }
      // Now we can create the cipher 
      StringBuilder result = new StringBuilder();
      for (int i = 0; i < rails; i++)
      for (int j = 0; j < plaintext.length(); j++)
      if (railMatrix[i][j] != '\n')
      result.append(railMatrix[i][j]);

      return result.toString();
   }

    //Decrypt the ciphertext
   public static String decryptMessage(String cipher, int rails) {
      // Create the matrix 
      char[][] railMatrix = new char[rails][cipher.length()];

      // Filling the rail matrix 
      for (int i = 0; i < rails; i++)
      Arrays.fill(railMatrix[i], '\n');

      // Find the direction
      boolean dirDown = true;

      int row = 0, col = 0;

      // Mark the places with '*'
      for (int i = 0; i < cipher.length(); i++) {
         // Check the direction of flow
         if (row == 0)
            dirDown = true;
         if (row == rails - 1)
            dirDown = false;

         // Place the marker
         railMatrix[row][col++] = '*';

         // Find the next row 
         if (dirDown)
            row++;
         else
            row--;
      }

      // Now we can produce the fill the rail matrix
      int index = 0;
      for (int i = 0; i < rails; i++)
      for (int j = 0; j < cipher.length(); j++)
      if (railMatrix[i][j] == '*' && index < cipher.length())
         railMatrix[i][j] = cipher.charAt(index++);

      StringBuilder result = new StringBuilder();

      row = 0;
      col = 0;
      for (int i = 0; i < cipher.length(); i++) {
         // Check the direction of flow
         if (row == 0)
         dirDown = true;
         if (row == rails - 1)
         dirDown = false;

         // Place the marker
         if (railMatrix[row][col] != '*')
         result.append(railMatrix[row][col++]);

         // Find the next row using direction flag
         if (dirDown)
            row++;
         else
            row--;
      }
      return result.toString();
   }

   // Driver function
   public static void main(String[] args) {
      // Encryption
      System.out.println("The Encrypted Messages: ");
      System.out.println(encryptMessage("hello world", 2));
      System.out.println(encryptMessage("Simple Text", 4));
      System.out.println(encryptMessage("Java is great", 5));

      // Now decryption of the same cipher-text
      System.out.println("\nThe Decrypted Messages: ");
      System.out.println(decryptMessage("hlowrdel ol", 2));
      System.out.println(decryptMessage("S ieTmletpx", 4));
      System.out.println(decryptMessage("Jga rvseaia t", 5));
   }
}

Following is the output of the above example −

Input/Output
The Encrypted Message: 
hlowrdel ol
S ieTmletpx
Jga rvseaia t

The Decrypted Messages: 
hello world
Simple Text
Java is great

Implement using C++

In this we will built C++ code to showcase the Rail Fence Cipher process. It will use necessary libraries like iostream and string. The program defines two main functions, encryptMessage and decryptMessage to encrypt and decrypt the message using Rail Fence. These functions use a matrix representation to create the Rail Fence Cipher algorithm, filling the matrix in a zigzag pattern as per the given number of rails. Here is the C++ program with encryption and decryption functions for Rail Fence Cipher −

Example

#include <iostream>
#include <string>
using namespace std;

// Function to encrypt a message using Rail Fence Cipher
string encryptMessage(string plaintext, int rails) {
   // Create a matrix to represent the rail fence
   char rail[rails][plaintext.length()];

   // Fill the rail matrix with newline characters
   for (int i = 0; i < rails; i++) {
      for (int j = 0; j < plaintext.length(); j++) {
         rail[i][j] = '\n';
      }
   }

   // Determine the direction of movement
   bool moveDown = false;
   int row = 0, col = 0;

   // Traverse the plaintext and fill the rail matrix
   for (int i = 0; i < plaintext.length(); i++) {
      if (row == 0 || row == rails - 1) {
         moveDown = !moveDown;
      }
      rail[row][col++] = plaintext[i];
      moveDown ? row++ : row--;
   }

   // Construct the cipher text from the rail matrix
   string ciphertext;
   for (int i = 0; i < rails; i++) {
      for (int j = 0; j < plaintext.length(); j++) {
         if (rail[i][j] != '\n') {
            ciphertext.push_back(rail[i][j]);
         }
      }
   }
   return ciphertext;
}

// Function to decrypt the cipher text using Rail Fence Cipher
string decryptMessage(string ciphertext, int rails) {
   char rail[rails][ciphertext.length()];

   // Fill the rail matrix with newline characters
   for (int i = 0; i < rails; i++) {
      for (int j = 0; j < ciphertext.length(); j++) {
         rail[i][j] = '\n';
      }
   }

   // Determine the direction of movement
   bool moveDown = true;
   int row = 0, col = 0;

   // Mark the places with '*'
   for (int i = 0; i < ciphertext.length(); i++) {
      if (row == 0) {
         moveDown = true;
      }
      if (row == rails - 1) {
         moveDown = false;
      }
      rail[row][col++] = '*';
      moveDown ? row++ : row--;
   }

   // Reconstruct the rail matrix with cipher text
   int index = 0;
   for (int i = 0; i < rails; i++) {
      for (int j = 0; j < ciphertext.length(); j++) {
         if (rail[i][j] == '*' && index < ciphertext.length()) {
            rail[i][j] = ciphertext[index++];
         }
      }
   }

   // Construct the plaintext from the rail matrix
   string plaintext;
   row = 0, col = 0;
   for (int i = 0; i < ciphertext.length(); i++) {
      if (row == 0) {
         moveDown = true;
      }
      if (row == rails - 1) {
         moveDown = false;
      }

      if (rail[row][col] != '*') {
         plaintext.push_back(rail[row][col++]);
      }
      moveDown ? row++ : row--;
   }
   return plaintext;
}

int main() {
   cout << "The Encrypted Messages: " << endl;
   cout << encryptMessage("hello Tutorialspoint", 2) << endl;
   cout << encryptMessage("Simple Text", 4) << endl;
   cout << encryptMessage("Cplusplus is great", 5) << endl;

   // Now decryption of the same cipher-text
   cout << "\nThe Decrypted Messages: " << endl;
   cout << decryptMessage("hloTtrasonel uoilpit", 2) << endl;
   cout << decryptMessage("S ieTmletpx", 4) << endl;
   cout << decryptMessage("Csapu etllirupsgs", 5) << endl;

   return 0;
}

Following is the output of the above example −

Input/Output
The Encrypted Messages: 
hloTtrasonel uoilpit
S ieTmletpx
Csapu etllirupsgs 

The Decrypted Messages: 
hello Tutorialspoint
Simple Text
Cptrgulus lpssiea

Complexity and Applications

  • The number of rows required to create the message determines how complex the rail fence technique is. The encryption will become more complicated the more rows we use. Moreover, an attacker may find it more difficult to figure out the initial positions of the characters in the message if there are more rows.

  • The rail fence technique is still not a very safe form of encryption, however, even with multiple rows. It is always open to certain forms of attacks, and attackers can quickly break them.

  • In modern communication, the rail fence technique is not often used. It was an integral part of various basic, low-security protocols for communication. However, more secure solutions that are more appropriate for securing private data are now available.

  • Using the rail fence method for educational games or activities for kids is one usage of it. It can be a quick and entertaining approach to go over the fundamentals of cryptography. It should not be used for any important security applications, though.

Advantages

We now understand the basic concept behind the rail fence method. Let's discuss the advantages −

  • The rail fence approach has a number of benefits, including versatility, simplicity, and ease of usage.

  • The rail fence technique is a useful option for basic communication when a greater level of security is not required because it is relatively easy to understand and apply. The rail fence technique can be carried out manually without the need for specialised tools or software.

  • Finally, any number of rows can be used with the rail fence system. It lets the user select the degree of complexity that best suits their requirements.

Disadvantages

Now let us discuss the disadvantages of Rail Fence −

  • This technique's primary disadvantages are its vulnerability to attacks, lack of security, and limited effectiveness.

  • As anyone with even basic cryptography knowledge can easily break the rail fence technique, it is not a secure form of encryption. For longer messages, this method is also not very successful.

  • Additionally, certain attack types, like known-plaintext attacks, can target the rail fence method. As a result, an attacker can simply initiate attacks to decrypt the data.

Limitation

With frequency analysis, the encryption of the rail fence cipher is easily broken. A number that is less than or equal to the length of the ciphertext acts as the encryption key. It is therefore very vulnerable to brute-force attacks.

Advertisements