Rail Fence Cipher Encryption and Decryption (original) (raw)

Last Updated : 22 Dec, 2023

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:

Rail Fence Algorithm

.'.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++ `

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

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

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

C#

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

} }

JavaScript

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