Keyword cipher is a form of monoalphabetic substitution. A keyword is used as the key, and it determines the letter matchings of the cipher alphabet to the plain alphabet. Repeats of letters in the word are removed, then the cipher alphabet is generated with the keyword matching to A, B, C, etc. until the keyword is used up, whereupon the rest of the ciphertext letters are used in alphabetical order, excluding those already used in the key.
Encryption:
The first line of input contains the keyword which you wish to enter. The second line of input contains the string which you have to encrypt.
Plaintext: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Encrypted: K R Y P T O S A B C D E F G H I J L M N Q U V W X Z
With KRYPTOS as the keyword, all As become Ks, all Bs becoming Rs, and so on. Encrypting the message “knowledge is power” using the keyword “Kryptos”:
Encrypting the message: Knowledge is Power
Encoded message: IlmWjbaEb GQ NmWbp
Examples:
Input :
Keyword : secret
Message : Zombie Here
Output :
Ciphered String : ZLJEFT DTOT
Take the first example, we used "secret" keyword there.
Plain Text : A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
When "secret" keyword is used, the new encrypting text becomes :
Encrypting : S E C R T A B D F G H I J K L M N O P Q U V W X Y Z
This means 'A' means 'S', 'B' means 'E' and 'C' means 'C' and so on.
Lets encode the given message "Zombie Here"
ZOMBIE HERE becomes ZLJEFT DTOT
Input :
Keyword : Star War
Message : Attack at dawn
Output :
Ciphered String : SPPSAG SP RSVJ
Few points to be noted in this method:
- All the messages are encoded in uppercase.
- Whitespace, special characters, and numbers do not take into consideration keywords although you can put them in there.
- While encrypting the message, whitespace, special characters and numbers remain unaffected.
Below is the implementation:
Output
Keyword : Computer
Message before Ciphering : GeeksforGeeks
Ciphered Text : EUUDNTILEUUDN
Decryption:
To decode the message you check the position of the given message in encrypting text with the plain text.
Plaintext: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Encrypted: K R Y P T O S A B C D E F G H I J L M N Q U V W X Z
Message: PTYBIATLEP
Deciphered Text: DECIPHERED
Now, how do we generate the deciphered string? We search for ‘P’ in Encrypted Text and compare its position with plain text letter and generate that letter. So ‘P’ becomes ‘D’, ‘T’ becomes ‘E’, ‘Y’ becomes ‘C’, and so on.
Examples:
Input :
Keyword : secret
Message : zljeft dtOT
Output :
Deciphered String : ZOMBIE HERE
Input :
Keyword : joker0O7hack123
Message : QjTijl
Output :
Deciphered String : BATMAN
Below is the implementation:
Example 1
CPP
#include <bits/stdc++.h>
using namespace std;
string plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
string encoder(string key)
{
string encoded = "" ;
bool arr[26] = { 0 };
for ( int i = 0; i < key.size(); i++) {
if (key[i] >= 'A' && key[i] <= 'Z' ) {
if (arr[key[i] - 65] == 0) {
encoded += key[i];
arr[key[i] - 65] = 1;
}
}
else if (key[i] >= 'a' && key[i] <= 'z' ) {
if (arr[key[i] - 97] == 0) {
encoded += key[i] - 32;
arr[key[i] - 97] = 1;
}
}
}
for ( int i = 0; i < 26; i++) {
if (arr[i] == 0) {
arr[i] = 1;
encoded += char (i + 65);
}
}
return encoded;
}
string decipheredIt(string msg, string encoded)
{
map< char , int > enc;
for ( int i = 0; i < encoded.size(); i++) {
enc[encoded[i]] = i;
}
string decipher = "" ;
for ( int i = 0; i < msg.size(); i++) {
if (msg[i] >= 'a' && msg[i] <= 'z' ) {
int pos = enc[msg[i] - 32];
decipher += plaintext[pos];
}
else if (msg[i] >= 'A' && msg[i] <= 'Z' ) {
int pos = enc[msg[i]];
decipher += plaintext[pos];
}
else {
decipher += msg[i];
}
}
return decipher;
}
int main()
{
string key;
key = "Computer" ;
cout << "Keyword : " << key << endl;
string encoded = encoder(key);
string message = "EUUDN TIL EUUDN" ;
cout << "Message before Deciphering : " << message
<< endl;
cout << "Ciphered Text : "
<< decipheredIt(message, encoded) << endl;
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
class GFG
{
public static String encoder( char [] key)
{
String encoded = "" ;
boolean [] arr = new boolean [ 26 ];
for ( int i = 0 ; i < key.length; i++)
{
if (key[i] >= 'A' && key[i] <= 'Z' )
{
if (arr[key[i] - 65 ] == false )
{
encoded += ( char ) key[i];
arr[key[i] - 65 ] = true ;
}
}
else if (key[i] >= 'a' && key[i] <= 'z' )
{
if (arr[key[i] - 97 ] == false )
{
encoded += ( char ) (key[i] - 32 );
arr[key[i] - 97 ] = true ;
}
}
}
for ( int i = 0 ; i < 26 ; i++)
{
if (arr[i] == false )
{
arr[i] = true ;
encoded += ( char ) (i + 65 );
}
}
return encoded;
}
public static String decipheredIt(String msg, String input)
{
String plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
String decipher = "" ;
Map<Character, Integer> enc = new HashMap<>();
for ( int i = 0 ; i < input.length(); i++)
{
enc.put(input.charAt(i), i);
}
for ( int i = 0 ; i < msg.length(); i++)
{
if (msg.charAt(i) >= 'a' && msg.charAt(i) <= 'z' )
{
int pos = enc.get(( char )(msg.charAt(i)- 32 ));
decipher += plaintext.charAt(pos);
}
else if (msg.charAt(i) >= 'A' && msg.charAt(i) <= 'Z' )
{
int pos = enc.get(msg.charAt(i));
decipher += plaintext.charAt(pos);
}
else
{
decipher += msg.charAt(i);
}
}
return decipher;
}
public static void main(String[] args)
{
String key;
key = "Computer" ;
System.out.println( "Keyword : " + key);
String decoded = encoder(key.toCharArray());
String message = "EUUDN TIL EUUDN" ;
System.out.println( "Message before Deciphering : " + message);
System.out.println( "Ciphered Text : " + decipheredIt(message,
decoded));
}
}
|
Python3
import string
all_alphabets = list (string.ascii_uppercase)
def encoder(key):
encoded = ""
arr = [ False ] * 26
for i in range ( len (key)):
if key[i] > = 'A' and key[i] < = 'Z' :
if arr[ ord (key[i]) - 65 ] = = False :
encoded + = key[i]
arr[ ord (key[i]) - 65 ] = True
elif key[i] > = 'a' and key[i] < = 'z' :
if arr[ ord (key[i]) - 97 ] = = False :
encoded + = chr ( ord (key[i]) - 32 )
arr[ ord (key[i]) - 97 ] = True
for i in range ( 26 ):
if arr[i] = = False :
arr[i] = True
encoded + = ( chr (i + 65 ))
return encoded
def decipheredIt(msg, encoded):
plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
decipher = ""
enc = {}
for i in range ( len (encoded)):
enc[encoded[i]] = i
for i in range ( len (msg)):
if msg[i] > = 'a' and msg[i] < = 'z' :
pos = enc.get(( chr )(msg[i] - 32 ))
decipher + = plaintext[pos]
elif msg[i] > = 'A' and msg[i] < = 'Z' :
pos = enc.get(msg[i])
decipher + = plaintext[pos]
else :
decipher + = msg[i]
return decipher
key = "Computer"
print ( "Keyword : " + key)
decoded = encoder( list (key))
message = "EUUDN TIL EUUDN"
print ( "Message before Deciphering : " + message)
print ( "Ciphered Text : " + decipheredIt(message, decoded))
|
C#
using System;
using System.Collections.Generic;
class GFG {
public static String encoder( char [] key)
{
String encoded = "" ;
bool [] arr = new bool [26];
for ( int i = 0; i < key.Length; i++) {
if (key[i] >= 'A' && key[i] <= 'Z' ) {
if (arr[key[i] - 65] == false ) {
encoded += ( char )key[i];
arr[key[i] - 65] = true ;
}
}
else if (key[i] >= 'a' && key[i] <= 'z' ) {
if (arr[key[i] - 97] == false ) {
encoded += ( char )(key[i] - 32);
arr[key[i] - 97] = true ;
}
}
}
for ( int i = 0; i < 26; i++) {
if (arr[i] == false ) {
arr[i] = true ;
encoded += ( char )(i + 65);
}
}
return encoded;
}
public static String decipheredIt(String msg,
String input)
{
String plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
String decipher = "" ;
Dictionary< char , int > enc
= new Dictionary< char , int >();
for ( int i = 0; i < input.Length; i++) {
enc.Add(input[i], i);
}
for ( int i = 0; i < msg.Length; i++) {
if (msg[i] >= 'a' && msg[i] <= 'z' ) {
int pos = enc[( char )(msg[i] - 32)];
decipher += plaintext[pos];
}
else if (msg[i] >= 'A' && msg[i] <= 'Z' ) {
int pos = enc[msg[i]];
decipher += plaintext[pos];
}
else {
decipher += msg[i];
}
}
return decipher;
}
static void Main()
{
String key;
key = "Computer" ;
Console.WriteLine( "Keyword : " + key);
String decoded = encoder(key.ToCharArray());
String message = "EUUDN TIL EUUDN" ;
Console.WriteLine( "Message before Deciphering : "
+ message);
Console.WriteLine( "Ciphered Text : "
+ decipheredIt(message, decoded));
}
}
|
Javascript
let plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
function encoder(key)
{
let encoded = "" ;
let arr = new Array(26).fill(0);
for (let i = 0; i < key.length; i++) {
if (key[i] >= 'A' && key[i] <= 'Z' ) {
if (arr[key.charCodeAt(i) - 65] == 0) {
encoded += key[i];
arr[key.charCodeAt(i) - 65] = 1;
}
}
else if (key[i] >= 'a' && key[i] <= 'z' ) {
if (arr[key.charCodeAt(i) - 97] == 0) {
encoded += String.fromCharCode((key.charCodeAt(i) - 32));
arr[key.charCodeAt(i) - 97] = 1;
}
}
}
for (let i = 0; i < 26; i++) {
if (arr[i] == 0) {
arr[i] = 1;
encoded += String.fromCharCode(65+i);
}
}
return encoded;
}
function decipheredIt(msg, encoded)
{
let enc = new Map();
for (let i = 0; i < encoded.length; i++) {
enc[encoded[i]] = i;
}
let decipher = "" ;
for (let i = 0; i < msg.length; i++) {
if (msg[i] >= 'a' && msg[i] <= 'z' ) {
let pos = enc[msg.charCodeAt(i) - 32];
decipher += plaintext[pos];
}
else if (msg[i] >= 'A' && msg[i] <= 'Z' ) {
let pos = enc[msg[i]];
decipher += plaintext[pos];
}
else {
decipher += msg[i];
}
}
return decipher;
}
let key;
key = "Computer" ;
console.log( "Keyword : " , key );
let encoded = encoder(key);
let message = "EUUDN TIL EUUDN" ;
console.log( "Message before Deciphering : " , message);
console.log( "Ciphered Text : " , decipheredIt(message, encoded));
|
Output
Keyword : Computer
Message before Deciphering : EUUDN TIL EUUDN
Ciphered Text : GEEKS FOR GEEKS
Example 2
Python
import string
all_alphabets = list (string.ascii_uppercase)
keyword = "Star War"
keyword1 = keyword.upper()
ciphertext = "SPPSAG SP RSVJ"
ct = []
for i in ciphertext:
ct.append(i.upper())
def duplicates( list ):
key = []
for i in list :
if i not in key:
key.append(i)
return key
keyword1 = duplicates(keyword1)
encrypting = duplicates(keyword1 + all_alphabets)
for i in encrypting:
if (i = = ' ' ):
encrypting.remove( ' ' )
message = ""
for i in range ( len (ct)):
if (ct[i] ! = ' ' ):
message = message + all_alphabets[encrypting.index(ct[i])]
else :
message = message + ' '
print ( "Keyword : " , keyword)
print ( "Ciphered Text : " , ciphertext)
print ( "Message before Ciphering : " , message)
|
Javascript
const all_alphabets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .split( '' );
const keyword = "Star War" ;
let keyword1 = keyword.toUpperCase();
const ciphertext = "SPPSAG SP RSVJ" ;
const ct = ciphertext.toUpperCase().split( '' );
const duplicates = (list) => {
let key = [];
for (let i = 0; i < list.length; i++) {
if (!key.includes(list[i])) {
key.push(list[i]);
}
}
return key;
}
keyword1 = duplicates(keyword1);
const encrypting = duplicates(keyword1.concat(all_alphabets));
for (let i = 0; i < encrypting.length; i++) {
if (encrypting[i] === ' ' ) {
encrypting.splice(i, 1);
}
}
let message = "" ;
for (let i = 0; i < ct.length; i++) {
if (ct[i] !== ' ' ) {
message = message + all_alphabets[encrypting.indexOf(ct[i])];
} else {
message = message + ' ' ;
}
}
console.log( "Keyword : " , keyword);
console.log( "Ciphered Text : " , ciphertext);
console.log( "Message before Ciphering : " , message);
|
C++
#include <bits/stdc++.h>
int main()
{
std::vector< char > all_alpha{
'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' ,
'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' ,
'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'
};
std::string keyword = "Star War" ;
std::transform(keyword.begin(), keyword.end(),
keyword.begin(), :: toupper );
std::vector< char > keyword1;
for ( char c : keyword) {
if (std::find(keyword1.begin(), keyword1.end(), c)
== keyword1.end()) {
keyword1.push_back(c);
}
}
std::string ciphertext = "SPPSAG SP RSVJ" ;
std::transform(ciphertext.begin(), ciphertext.end(),
ciphertext.begin(), :: toupper );
std::vector< char > ct;
for ( char c : ciphertext) {
if (c != ' ' ) {
ct.push_back(c);
}
}
std::vector< char > encrypting = keyword1;
for ( char c : all_alpha) {
if (std::find(encrypting.begin(), encrypting.end(),
c)
== encrypting.end()) {
encrypting.push_back(c);
}
}
encrypting.erase(std:: remove (encrypting.begin(),
encrypting.end(), ' ' ),
encrypting.end());
std::string message;
for ( char c : ct) {
if (c != ' ' ) {
auto it = std::find(encrypting.begin(),
encrypting.end(), c);
int index
= std::distance(encrypting.begin(), it);
message += all_alpha[index];
}
else {
message += ' ' ;
}
}
std::cout << "Keyword : " << keyword << std::endl;
std::cout << "Ciphered Text : " << ciphertext
<< std::endl;
std::cout << "Message before Ciphering : " << message
<< std::endl;
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Character> all_alpha = new ArrayList<>(Arrays.asList(
'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' ,
'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' ,
'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z'
));
String keyword = "Star War" ;
keyword = keyword.toUpperCase();
List<Character> keyword1 = new ArrayList<>();
for ( char c : keyword.toCharArray()) {
if (!keyword1.contains(c)) {
keyword1.add(c);
}
}
String ciphertext = "SPPSAG SP RSVJ" ;
ciphertext = ciphertext.toUpperCase();
List<Character> ct = new ArrayList<>();
for ( char c : ciphertext.toCharArray()) {
if (c != ' ' ) {
ct.add(c);
}
}
List<Character> encrypting = new ArrayList<>(keyword1);
for ( char c : all_alpha) {
if (!encrypting.contains(c)) {
encrypting.add(c);
}
}
encrypting.remove(Character.valueOf( ' ' ));
StringBuilder message = new StringBuilder();
for ( char c : ct) {
if (c != ' ' ) {
int index = encrypting.indexOf(c);
message.append(all_alpha.get(index));
} else {
message.append( ' ' );
}
}
System.out.println( "Keyword : " + keyword);
System.out.println( "Ciphered Text : " + ciphertext);
System.out.println( "Message before Ciphering : " + message);
}
}
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class MainClass {
public static void Main( string [] args)
{
string allAlphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
string keyword = "Star War" ;
string keyword1 = keyword.ToUpper();
string ciphertext = "SPPSAG SP RSVJ" ;
List< char > ct = new List< char >();
foreach ( char c in ciphertext)
{
ct.Add(Char.ToUpper(c));
}
List< char > keywordList
= new List< char >(keyword1.Distinct());
List< char > encrypting
= keywordList.Concat(allAlphabets)
.Distinct()
.ToList();
encrypting.Remove( ' ' );
string message = "" ;
foreach ( char c in ct)
{
if (c != ' ' ) {
message
+= allAlphabets[encrypting.IndexOf(c)];
}
else {
message += " " ;
}
}
Console.WriteLine( "Keyword : " + keyword);
Console.WriteLine( "Ciphered Text : " + ciphertext);
Console.WriteLine( "Message before Ciphering : "
+ message);
}
}
|
Output
('Keyword : ', 'Star War')
('Ciphered Text : ', 'SPPSAG SP RSVJ')
('Message before Ciphering : ', 'ATTACK AT DAWN')
Note: One can improve this Classical Cipher: Keyword also. Here we are only taking A-Z in plain text. You can take uppercase, lowercase, and numbers also into consideration.
Ways to attack a keyword cipher:
The best ways to attack a keyword cipher without knowing the keyword are through the known-plaintext attack, frequency analysis, and discovery of the keyword (often a cryptanalyst will combine all three techniques). Keyword discovery allows immediate decryption since the table can be made immediately.
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!