Open In App

Rail Fence Cipher – Encryption and Decryption

Given a plain-text message and a numeric key, cipher/de-cipher the given text using Rail Fence algorithm. 
The rail fence cipher (also called a zigzag cipher) is a form of transposition cipher. It derives its name from the way in which it is encoded. 
Examples: 

Encryption
Input : "GeeksforGeeks "
Key = 3
Output : GsGsekfrek eoe
Decryption
Input : GsGsekfrek eoe
Key = 3
Output : "GeeksforGeeks "

Encryption
Input : "defend the east wall"
Key = 3
Output : dnhaweedtees alf tl
Decryption
Input : dnhaweedtees alf tl
Key = 3
Output : defend the east wall

Encryption
Input : "attack at once"
Key = 2
Output : atc toctaka ne
Decryption
Input : "atc toctaka ne"
Key = 2
Output : attack at once

Encryption



In a transposition cipher, the order of the alphabets is re-arranged to obtain the cipher-text. 

For example, if the message is “GeeksforGeeks” and the number of rails = 3 then cipher is prepared as: 
 



.’.Its encryption will be done row wise i.e. GSGSEKFREKEOE

 

Decryption

As we’ve seen earlier, the number of columns in rail fence cipher remains equal to the length of plain-text message. And the key corresponds to the number of rails.
 

Implementation: 
Let cipher-text = “GsGsekfrek eoe” , and Key = 3 
 

Hence original matrix will be of 3*13 , now marking places with text as ‘*’ we get 
 

* _ _ _ * _ _ _ * _ _ _ *
_ * _ * _ * _ * _ * _ *
_ _ * _ _ _ * _ _ _ * _

Below is a program to encrypt/decrypt the message using the above algorithm. 
 




// C++ program to illustrate Rail Fence Cipher
// Encryption and Decryption
#include <bits/stdc++.h>
using namespace std;
 
// function to encrypt a message
string encryptRailFence(string text, int key)
{
    // create the matrix to cipher plain text
    // key = rows , length(text) = columns
    char rail[key][(text.length())];
 
    // filling the rail matrix to distinguish filled
    // spaces from blank ones
    for (int i=0; i < key; i++)
        for (int j = 0; j < text.length(); j++)
            rail[i][j] = '\n';
 
    // to find the direction
    bool dir_down = false;
    int row = 0, col = 0;
 
    for (int i=0; i < text.length(); i++)
    {
        // check the direction of flow
        // reverse the direction if we've just
        // filled the top or bottom rail
        if (row == 0 || row == key-1)
            dir_down = !dir_down;
 
        // fill the corresponding alphabet
        rail[row][col++] = text[i];
 
        // find the next row using direction flag
        dir_down?row++ : row--;
    }
 
    //now we can construct the cipher using the rail matrix
    string result;
    for (int i=0; i < key; i++)
        for (int j=0; j < text.length(); j++)
            if (rail[i][j]!='\n')
                result.push_back(rail[i][j]);
 
    return result;
}
 
// This function receives cipher-text and key
// and returns the original text after decryption
string decryptRailFence(string cipher, int key)
{
    // create the matrix to cipher plain text
    // key = rows , length(text) = columns
    char rail[key][cipher.length()];
 
    // filling the rail matrix to distinguish filled
    // spaces from blank ones
    for (int i=0; i < key; i++)
        for (int j=0; j < cipher.length(); j++)
            rail[i][j] = '\n';
 
    // to find the direction
    bool dir_down;
 
    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)
            dir_down = true;
        if (row == key-1)
            dir_down = false;
 
        // place the marker
        rail[row][col++] = '*';
 
        // find the next row using direction flag
        dir_down?row++ : row--;
    }
 
    // now we can construct the fill the rail matrix
    int index = 0;
    for (int i=0; i<key; i++)
        for (int j=0; j<cipher.length(); j++)
            if (rail[i][j] == '*' && index<cipher.length())
                rail[i][j] = cipher[index++];
 
 
    // now read the matrix in zig-zag manner to construct
    // the resultant text
    string result;
 
    row = 0, col = 0;
    for (int i=0; i< cipher.length(); i++)
    {
        // check the direction of flow
        if (row == 0)
            dir_down = true;
        if (row == key-1)
            dir_down = false;
 
        // place the marker
        if (rail[row][col] != '*')
            result.push_back(rail[row][col++]);
 
        // find the next row using direction flag
        dir_down?row++: row--;
    }
    return result;
}
 
//driver program to check the above functions
int main()
{
    cout << encryptRailFence("attack at once", 2) << endl;
    cout << encryptRailFence("GeeksforGeeks ", 3) << endl;
    cout << encryptRailFence("defend the east wall", 3) << endl;
 
    //Now decryption of the same cipher-text
    cout << decryptRailFence("GsGsekfrek eoe",3) << endl;
    cout << decryptRailFence("atc toctaka ne",2) << endl;
    cout << decryptRailFence("dnhaweedtees alf  tl",3) << endl;
 
    return 0;
}




// Java program to illustrate Rail Fence Cipher
// Encryption and Decryption
import java.util.Arrays;
class RailFence {
 
    // function to encrypt a message
    public static String encryptRailFence(String text,
                                          int key)
    {
 
        // create the matrix to cipher plain text
        // key = rows , length(text) = columns
        char[][] rail = new char[key][text.length()];
 
        // filling the rail matrix to distinguish filled
        // spaces from blank ones
        for (int i = 0; i < key; i++)
            Arrays.fill(rail[i], '\n');
 
        boolean dirDown = false;
        int row = 0, col = 0;
 
        for (int i = 0; i < text.length(); i++) {
 
            // check the direction of flow
            // reverse the direction if we've just
            // filled the top or bottom rail
            if (row == 0 || row == key - 1)
                dirDown = !dirDown;
 
            // fill the corresponding alphabet
            rail[row][col++] = text.charAt(i);
 
            // find the next row using direction flag
            if (dirDown)
                row++;
            else
                row--;
        }
 
        // now we can construct the cipher using the rail
        // matrix
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < key; i++)
            for (int j = 0; j < text.length(); j++)
                if (rail[i][j] != '\n')
                    result.append(rail[i][j]);
 
        return result.toString();
    }
 
    // This function receives cipher-text and key
    // and returns the original text after decryption
    public static String decryptRailFence(String cipher,
                                          int key)
    {
 
        // create the matrix to cipher plain text
        // key = rows , length(text) = columns
        char[][] rail = new char[key][cipher.length()];
 
        // filling the rail matrix to distinguish filled
        // spaces from blank ones
        for (int i = 0; i < key; i++)
            Arrays.fill(rail[i], '\n');
 
        // to 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 == key - 1)
                dirDown = false;
 
            // place the marker
            rail[row][col++] = '*';
 
            // find the next row using direction flag
            if (dirDown)
                row++;
            else
                row--;
        }
 
        // now we can construct the fill the rail matrix
        int index = 0;
        for (int i = 0; i < key; i++)
            for (int j = 0; j < cipher.length(); j++)
                if (rail[i][j] == '*'
                    && index < cipher.length())
                    rail[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 == key - 1)
                dirDown = false;
 
            // place the marker
            if (rail[row][col] != '*')
                result.append(rail[row][col++]);
 
            // find the next row using direction flag
            if (dirDown)
                row++;
            else
                row--;
        }
        return result.toString();
    }
 
    // driver program to check the above functions
    public static void main(String[] args)
    {
 
        // Encryption
        System.out.println("Encrypted Message: ");
        System.out.println(
            encryptRailFence("attack at once", 2));
        System.out.println(
            encryptRailFence("GeeksforGeeks ", 3));
        System.out.println(
            encryptRailFence("defend the east wall", 3));
 
        // Now decryption of the same cipher-text
        System.out.println("\nDecrypted Message: ");
        System.out.println(
            decryptRailFence("atc toctaka ne", 2));
        System.out.println(
            decryptRailFence("GsGsekfrek eoe", 3));
        System.out.println(
            decryptRailFence("dnhaweedtees alf  tl", 3));
    }
}
// This code is contributed by Jay




# Python3 program to illustrate
# Rail Fence Cipher Encryption
# and Decryption
 
# function to encrypt a message
def encryptRailFence(text, key):
 
    # create the matrix to cipher
    # plain text key = rows ,
    # length(text) = columns
    # filling the rail matrix
    # to distinguish filled
    # spaces from blank ones
    rail = [['\n' for i in range(len(text))]
                for j in range(key)]
     
    # to find the direction
    dir_down = False
    row, col = 0, 0
     
    for i in range(len(text)):
         
        # check the direction of flow
        # reverse the direction if we've just
        # filled the top or bottom rail
        if (row == 0) or (row == key - 1):
            dir_down = not dir_down
         
        # fill the corresponding alphabet
        rail[row][col] = text[i]
        col += 1
         
        # find the next row using
        # direction flag
        if dir_down:
            row += 1
        else:
            row -= 1
    # now we can construct the cipher
    # using the rail matrix
    result = []
    for i in range(key):
        for j in range(len(text)):
            if rail[i][j] != '\n':
                result.append(rail[i][j])
    return("" . join(result))
     
# This function receives cipher-text
# and key and returns the original
# text after decryption
def decryptRailFence(cipher, key):
 
    # create the matrix to cipher
    # plain text key = rows ,
    # length(text) = columns
    # filling the rail matrix to
    # distinguish filled spaces
    # from blank ones
    rail = [['\n' for i in range(len(cipher))]
                for j in range(key)]
     
    # to find the direction
    dir_down = None
    row, col = 0, 0
     
    # mark the places with '*'
    for i in range(len(cipher)):
        if row == 0:
            dir_down = True
        if row == key - 1:
            dir_down = False
         
        # place the marker
        rail[row][col] = '*'
        col += 1
         
        # find the next row
        # using direction flag
        if dir_down:
            row += 1
        else:
            row -= 1
             
    # now we can construct the
    # fill the rail matrix
    index = 0
    for i in range(key):
        for j in range(len(cipher)):
            if ((rail[i][j] == '*') and
            (index < len(cipher))):
                rail[i][j] = cipher[index]
                index += 1
         
    # now read the 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:
            dir_down = True
        if row == key-1:
            dir_down = False
             
        # place the marker
        if (rail[row][col] != '*'):
            result.append(rail[row][col])
            col += 1
             
        # find the next row using
        # direction flag
        if dir_down:
            row += 1
        else:
            row -= 1
    return("".join(result))
 
# Driver code
if __name__ == "__main__":
    print(encryptRailFence("attack at once", 2))
    print(encryptRailFence("GeeksforGeeks ", 3))
    print(encryptRailFence("defend the east wall", 3))
     
    # Now decryption of the
    # same cipher-text
    print(decryptRailFence("GsGsekfrek eoe", 3))
    print(decryptRailFence("atc toctaka ne", 2))
    print(decryptRailFence("dnhaweedtees alf  tl", 3))
 
# This code is contributed
# by Pratik Somwanshi




using System;
 
class GFG_RailFence {
 
  // function to encrypt a message
  public static string EncryptRailFence(string text, int key) {
 
    // create the matrix to cipher plain text
    // key = rows, length(text) = columns
    char[,] rail = new char[key, text.Length];
 
    // filling the rail matrix to distinguish filled
    // spaces from blank ones
    for (int i = 0; i < key; i++)
      for (int j = 0; j < text.Length; j++)
        rail[i, j] = '\n';
 
    bool dirDown = false;
    int row = 0, col = 0;
 
    for (int i = 0; i < text.Length; i++) {
      // check the direction of flow
      // reverse the direction if we've just
      // filled the top or bottom rail
      if (row == 0 || row == key - 1)
        dirDown = !dirDown;
 
      // fill the corresponding alphabet
      rail[row, col++] = text[i];
 
      // find the next row using direction flag
      if (dirDown)
        row++;
      else
        row--;
    }
 
    // now we can construct the cipher using the rail
    // matrix
    string result = "";
    for (int i = 0; i < key; i++)
      for (int j = 0; j < text.Length; j++)
        if (rail[i, j] != '\n')
          result += rail[i, j];
 
    return result;
  }
 
  // This function receives cipher-text and key
  // and returns the original text after decryption
  public static string DecryptRailFence(string cipher, int key) {
    // create the matrix to cipher plain text
    // key = rows, length(text) = columns
    // create the matrix to cipher plain text
    // key = rows , length(text) = columns
    char[,] rail = new char[key, cipher.Length];
 
    // filling the rail matrix to distinguish filled
    // spaces from blank ones
    for (int i = 0; i < key; i++)
      for (int j = 0; j < cipher.Length; j++)
        rail[i, j] = '\n';
 
    // to find the direction
    bool 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 == key - 1)
        dirDown = false;
 
      // place the marker
      rail[row, col++] = '*';
 
      // find the next row using direction flag
      if (dirDown)
        row++;
      else
        row--;
    }
 
    // now we can construct the fill the rail matrix
    int index = 0;
    for (int i = 0; i < key; i++)
      for (int j = 0; j < cipher.Length; j++)
        if (rail[i, j] == '*' && index < cipher.Length)
          rail[i, j] = cipher[index++];
 
    // create the result string
    string result = "";
    row = 0;
    col = 0;
 
    // iterate through the rail matrix
    for (int i = 0; i < cipher.Length; i++) {
      // check the direction of flow
      if (row == 0)
        dirDown = true;
      if (row == key - 1)
        dirDown = false;
 
      // place the marker
      if (rail[row, col] != '*')
        result += rail[row, col++];
 
      // find the next row using direction flag
      if (dirDown)
        row++;
      else
        row--;
    }
    return result;
  }
 
  // driver program to check the above functions
  public static void Main() {
 
    // Encryption
    Console.WriteLine("Encrypted Message: ");
    Console.WriteLine(EncryptRailFence("attack at once", 2));
    Console.WriteLine(
      EncryptRailFence("GeeksforGeeks ", 3));
    Console.WriteLine(
      EncryptRailFence("defend the east wall", 3));
 
    // Now decryption of the same cipher-text
    Console.WriteLine("\nDecrypted Message: ");
    Console.WriteLine(
      DecryptRailFence("atc toctaka ne", 2));
    Console.WriteLine(
      DecryptRailFence("GsGsekfrek eoe", 3));
    Console.WriteLine(
      DecryptRailFence("dnhaweedtees alf  tl", 3));
  }
}




// function to encrypt a message
function encryptRailFence(text, key) {
  // create the matrix to cipher plain text
  // key = rows , text.length = columns
  let rail = new Array(key).fill().map(() => new Array(text.length).fill('\n'));
 
  // filling the rail matrix to distinguish filled
  // spaces from blank ones
  let dir_down = false;
  let row = 0, col = 0;
 
  for (let i = 0; i < text.length; i++) {
    // check the direction of flow
    // reverse the direction if we've just
    // filled the top or bottom rail
    if (row == 0 || row == key - 1) dir_down = !dir_down;
 
    // fill the corresponding alphabet
    rail[row][col++] = text[i];
 
    // find the next row using direction flag
    dir_down ? row++ : row--;
  }
 
  // now we can construct the cipher using the rail matrix
  let result = '';
  for (let i = 0; i < key; i++)
    for (let j = 0; j < text.length; j++)
      if (rail[i][j] != '\n') result += rail[i][j];
 
  return result;
}
 
// function to decrypt a message
function decryptRailFence(cipher, key) {
  // create the matrix to cipher plain text
  // key = rows , text.length = columns
  let rail = new Array(key).fill().map(() => new Array(cipher.length).fill('\n'));
 
  // filling the rail matrix to mark the places with '*'
  let dir_down = false;
  let row = 0, col = 0;
 
  for (let i = 0; i < cipher.length; i++) {
    // check the direction of flow
    if (row == 0) dir_down = true;
    if (row == key - 1) dir_down = false;
 
    // place the marker
    rail[row][col++] = '*';
 
    // find the next row using direction flag
    dir_down ? row++ : row--;
  }
 
  // now we can construct the rail matrix by filling the marked places with cipher text
  let index = 0;
  for (let i = 0; i < key; i++)
    for (let j = 0; j < cipher.length; j++)
      if (rail[i][j] == '*' && index < cipher.length) rail[i][j] = cipher[index++];
 
  // now read the matrix in zig-zag manner to construct the resultant text
  let result = '';
  row = 0, col = 0;
  for (let i = 0; i < cipher.length; i++) {
    // check the direction of flow
    if (row == 0) dir_down = true;
    if (row == key - 1) dir_down = false;
 
    // place the marker
    if (rail[row][col] != '*') result += rail[row][col++];
 
    // find the next row using direction flag
    dir_down ? row++ : row--;
  }
 
  return result;
}
 
// driver program to check the above functions
 
 // Encryption
console.log(encryptRailFence('attack at once', 2));
console.log(encryptRailFence('GeeksforGeeks', 3));
console.log(encryptRailFence('defend the east wall', 3));
// Now decryption of the same cipher-text
console.log(decryptRailFence('GsGsekfrek eoe', 3));
console.log(decryptRailFence('atc toctaka ne', 2));
console.log(decryptRailFence('dnhaweedtees alf  tl', 3));

Output
atc toctaka ne
GsGsekfrek eoe
dnhaweedtees alf  tl
GeeksforGeeks 
attack at once
defend the east wall

Time Complexity: O(row * col)
Auxiliary Space: O(row * col) 
References: 
https://en.wikipedia.org/wiki/Rail_fence_cipher
This article is contributed by Ashutosh Kumar

 


Article Tags :