Cryptography - Decryption of Simple Substitution Cipher



In the last chapter we saw different encryption programs for simple substitution cipher. Now we will discuss the decryption methods to decrypt the given message using a simple substitution cipher using Python, Java and C++.

As you may know that decryption is the reverse process of encryption so we will reverse all the programs we have created for encryption in the previous chapter.

Implementation using Python

We can implement the decryption of simple substitution cipher using below methods −

  • Using a specified shift value

  • Using a Dictionary Mapping

  • Using ASCII Values Directly

In the next sections, we will try to describe each of these ways in detail so that you can gain a better understanding of Python cryptography and simple substitution cipher decryption.

Approach 1: Using a specified shift value

To create a decryption function for the previous encryption program, we can use the same approach but reverse the shift direction. This below function reverses the encryption process by shifting each letter in the encrypted text in the opposite direction of the original shift. It works by subtracting the shift value instead of adding it. So basically we are undoing the encryption.

Here is the implementation of decryption process using this approach in Python −

Example

# function for decryption
def substitution_decrypt(encrypted_text, shift):
   decrypted_text = ""
   for char in encrypted_text:
      if char.isalpha():
         ascii_val = ord(char)
         if char.isupper():
            # Reverse the shift for uppercase letters
            shifted_ascii = ((ascii_val - 65 - shift) % 26) + 65
         else:
            # Reverse the shift for lowercase letters
            shifted_ascii = ((ascii_val - 97 - shift) % 26) + 97
         decrypted_char = chr(shifted_ascii)
         decrypted_text += decrypted_char
      else:
         decrypted_text += char
   return decrypted_text

# our cipher text
encrypted_text = "Mjqqt, jajwdtsj!"
shift = 5
decrypted_text = substitution_decrypt(encrypted_text, shift)
print("Cipher Text: ", encrypted_text)
print("Decrypted text:", decrypted_text)

Following is the output of the above example −

Input/Output
Cipher Text:  Mjqqt, jajwdtsj!
Decrypted text: Hello, everyone!

Approach 2: Using a Dictionary Mapping

Here we will use dictionary mapping to implement a simple substitution cipher decryption. As we have used dictionary mapping in the previous chapter for encrypting the plaintext. Now we will use the same technique but in reverse direction. We need to reverse this mapping. In place of mapping each letter to the next one, we map each letter in the encrypted text back to its original letter in the plaintext.

This needs creating a reverse dictionary in which the keys are the characters in the encrypted text and the values are the corresponding characters in the plaintext.

Below is the Python implementation for the simple substitution cipher decryption using reverse dictionary mapping −

# function for decryption
def substitution_decrypt(encrypted_text, key):
   # a reverse dictionary mapping for decryption
   reverse_mapping = {key[i]: chr(97 + i) for i in range(26)}
   # Decrypt the using reverse mapping
   decrypted_text = ''.join(reverse_mapping.get(char, char) for char in encrypted_text)
   return decrypted_text


# our cipher text
encrypted_text = "ifmmp, efbs gsjfoe!"
key = "bcdefghijklmnopqrstuvwxyza"  # Example substitution key
decrypted_text = substitution_decrypt(encrypted_text, key)
print("Cipher Text: ", encrypted_text)
print("Decrypted text:", decrypted_text)

Following is the output of the above example −

Input/Output

Cipher Text:  ifmmp, efbs gsjfoe!
Decrypted text: hello, dear friend!

Approach 3: Using ASCII Values Directly

ASCII is a character encoding standard in which we assign numerical values to letters, digits, and other characters. During encryption, each letter of the plaintext is shifted by a fixed amount using ASCII values. Now we have to decrypt so we will reverse the shifting process by subtracting the same fixed amount from each character.

For example, if we are decrypting 'd' (ASCII value 100) shifted by 3, we subtract 3 to get back to 'a' (ASCII value 97).

So here is a Python implementation for the simple substitution cipher decryption using ASCII values directly −

# function for decryption
def substitution_decrypt(encrypted_text, shift):
   decrypted_text = ""
   for char in encrypted_text:
     if char.isalpha():
         # Use ASCII values directly to reverse the shift for decryption
         ascii_val = ord(char)
         shifted_ascii = ascii_val - shift
         if char.isupper():
            if shifted_ascii < 65:
               shifted_ascii += 26
            elif shifted_ascii > 90:
               shifted_ascii -= 26
         elif char.islower():
            if shifted_ascii < 97:
               shifted_ascii += 26
            elif shifted_ascii > 122:
               shifted_ascii -= 26
         decrypted_text += chr(shifted_ascii)
     else:
         decrypted_text += char
   return decrypted_text

# our cipher text
encrypted_text = "Khoor, pb ghdu froohdjxh!"
shift = 3
decrypted_text = substitution_decrypt(encrypted_text, shift)
print("Cipher Text: ", encrypted_text)
print("Decrypted text:", decrypted_text)

Following is the output of the above example −

Input/Output

Cipher Text:  Khoor, pb ghdu froohdjxh!
Decrypted text: Hello, my dear colleague!

Implementation using Java

In this example we will be using Java for implementing decryption of simple substitution cipher. So we will be using Java's Hashmap and Map library for implementing this functionality. The decryptMessage() method will work similarly to the encryption method but in this we will use the decryption map instead. It will map each encrypted letter back to its actual letter in the alphabet. We will use this method to decrypt the encrypted text we have generated in the previous chapter and get the original plaintext.

Example

So the implementation using Java's Hashmap and Map library is as follows −

import java.util.HashMap;
import java.util.Map;

public class SSC {

   private static final String alphabet = "abcdefghijklmnopqrstuvwxyz";
   private static final String encrypted_alphabet = "bcdefghijklmnopqrstuvwxyza";
   private static final Map<Character, Character> encryptionMap = new HashMap<>();
   private static final Map<Character, Character> decryptionMap = new HashMap<>();

   static {
      for (int i = 0; i < alphabet.length(); i++) {
         encryptionMap.put(alphabet.charAt(i), encrypted_alphabet.charAt(i));
         decryptionMap.put(encrypted_alphabet.charAt(i), alphabet.charAt(i));
      }
   }

   public static String decryptMessage(String ciphertext) {
     StringBuilder plaintext = new StringBuilder();
     for (char c : ciphertext.toLowerCase().toCharArray()) {
         if (decryptionMap.containsKey(c)) {
            plaintext.append(decryptionMap.get(c));
         } else {
            plaintext.append(c);
         }
      }
      return plaintext.toString();
   }

   public static void main(String[] args) {
      String et = "ifmmp uvupsjbmtqpjou";
      System.out.println("The Encrypted text: " + et);

      String dt = decryptMessage(et);
      System.out.println("The Decrypted text: " + dt);
   }
}

Following is the output of the above example −

Input/Output

The Encrypted text: ifmmp uvupsjbmtqpjou
The Decrypted text: hello tutorialspoint

Implementation using C++

Now we will use C++ to implement decryption process of simple substitution cipher. So we will reverse the process of encryption which we have discussed in the previous chapter. So in this we are using 'unordered_map' container of C++. It is used to map each encrypted letter back to its actual form in the alphabet. We will use this method to decrypt the encrypted text and get the plaintext message.

Example

See the code below for decryption function of simple substitution cipher in C++ programming langugage −

#include <iostream>
#include <unordered_map>
#include <string>

using namespace std;

class SSC {
private:
   const string alphabet = "abcdefghijklmnopqrstuvwxyz";
   const string encrypted_alphabet = "bcdefghijklmnopqrstuvwxyza";
   unordered_map<char, char> encryptionMap;
   unordered_map<char, char> decryptionMap;

public:
   SSC() {
      for (int i = 0; i < alphabet.length(); i++) {
         encryptionMap[alphabet[i]] = encrypted_alphabet[i];
         decryptionMap[encrypted_alphabet[i]] = alphabet[i];
      }
   }

   string decryptMessage(string ciphertext) {
      string plaintext = "";
      for (char c : ciphertext) {
         if (decryptionMap.find(tolower(c)) != decryptionMap.end()) {
            plaintext += decryptionMap[tolower(c)];
         } else {
            plaintext += c;
         }
      }
      return plaintext;
   }
};

int main() {
   SSC cipher;
   string et = "ifmmp uifsf ipx bsf zpv!";
   cout << "The Encrypted text: " << et << endl;
   string dt = cipher.decryptMessage(et);
   cout << "The Decrypted text: " << dt << endl;

   return 0;
}

Following is the output of the above example −

Input/Output

The Encrypted text: ifmmp uifsf ipx bsf zpv!
The Decrypted text: hello there how are you!

Summary

This chapter explains different methods for decrypting a Simple Substitution Cipher in Python, Java and C++. We have seen methods using a specified shift value, dictionary mapping, using ASCII values directly and by mapping. These approaches explain different ways to decrypt text encrypted using a Simple Substitution Cipher which offers flexibility of using different programming langugages.

Advertisements