Hill Cipher is a polygraphic substitution cipher based on linear algebra. In this method, each letter of the alphabet is represented by a number modulo 26, commonly using the scheme A = 0, B = 1, …, Z = 25.
Example:
Input : Plaintext: ACT
Key: GYBNQKURP
Output: Ciphertext: POHInput: Plaintext: GFG
Key: HILLMAGIC
Output: Ciphertext: SWK
Encryption in Hill Cipher
For encryption ,
- Divide the plaintext into blocks of n letters.
- Treat each block as an n-dimensional vector.
- Multiply this vector by an invertible n × n key matrix.
- Take the result modulo 26.
- The final values form the ciphertext.
Illustration
We have to encrypt the message 'ACT' (n=3).The key is 'GYBNQKURP' which can be written as the nxn matrix ,

The message 'ACT' is written as vector,

The enciphered vector is given as,

which corresponds to ciphertext of 'POH'
//Driver Code Starts
// C++ code to implement Hill Cipher
#include <iostream>
using namespace std;
//Driver Code Ends
// Following function generates the
// key matrix for the key string
void getKeyMatrix(string key, int keyMatrix[][3])
{
int k = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
keyMatrix[i][j] = (key[k]) % 65;
k++;
}
}
}
// Following function encrypts the message
void encrypt(int cipherMatrix[][1],
int keyMatrix[][3],
int messageVector[][1])
{
int x, i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 1; j++)
{
cipherMatrix[i][j] = 0;
for (x = 0; x < 3; x++)
{
cipherMatrix[i][j] +=
keyMatrix[i][x] * messageVector[x][j];
}
cipherMatrix[i][j] = cipherMatrix[i][j] % 26;
}
}
}
//Driver Code Starts
// Function to implement Hill Cipher
void HillCipher(string message, string key)
{
// Get key matrix from the key string
int keyMatrix[3][3];
getKeyMatrix(key, keyMatrix);
int messageVector[3][1];
// Generate vector for the message
for (int i = 0; i < 3; i++)
messageVector[i][0] = (message[i]) % 65;
int cipherMatrix[3][1];
// Following function generates
// the encrypted vector
encrypt(cipherMatrix, keyMatrix, messageVector);
string CipherText;
// Generate the encrypted text from
// the encrypted vector
for (int i = 0; i < 3; i++)
CipherText += cipherMatrix[i][0] + 65;
// Finally print the ciphertext
cout << " Ciphertext:" << CipherText;
}
// Driver function for above code
int main()
{
// Get the message to be encrypted
string message = "ACT";
// Get the key
string key = "GYBNQKURP";
HillCipher(message, key);
return 0;
}
//Driver Code Ends
//Driver Code Starts
// Java code to implement Hill Cipher
class GFG
{
// Following function generates the
//Driver Code Ends
// key matrix for the key string
static void getKeyMatrix(String key, int keyMatrix[][])
{
int k = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
keyMatrix[i][j] = (key.charAt(k)) % 65;
k++;
}
}
}
// Following function encrypts the message
static void encrypt(int cipherMatrix[][],
int keyMatrix[][],
int messageVector[][])
{
int x, i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 1; j++)
{
cipherMatrix[i][j] = 0;
for (x = 0; x < 3; x++)
{
cipherMatrix[i][j] +=
keyMatrix[i][x] * messageVector[x][j];
}
cipherMatrix[i][j] = cipherMatrix[i][j] % 26;
}
}
}
//Driver Code Starts
// Function to implement Hill Cipher
static void HillCipher(String message, String key)
{
// Get key matrix from the key string
int [][]keyMatrix = new int[3][3];
getKeyMatrix(key, keyMatrix);
int [][]messageVector = new int[3][1];
// Generate vector for the message
for (int i = 0; i < 3; i++)
messageVector[i][0] = (message.charAt(i)) % 65;
int [][]cipherMatrix = new int[3][1];
// Following function generates
// the encrypted vector
encrypt(cipherMatrix, keyMatrix, messageVector);
String CipherText="";
// Generate the encrypted text from
// the encrypted vector
for (int i = 0; i < 3; i++)
CipherText += (char)(cipherMatrix[i][0] + 65);
// Finally print the ciphertext
System.out.print(" Ciphertext:" + CipherText);
}
// Driver code
public static void main(String[] args)
{
// Get the message to be encrypted
String message = "ACT";
// Get the key
String key = "GYBNQKURP";
HillCipher(message, key);
}
}
//Driver Code Ends
# Python3 code to implement Hill Cipher
keyMatrix = [[0] * 3 for i in range(3)]
# Generate vector for the message
messageVector = [[0] for i in range(3)]
# Generate vector for the cipher
cipherMatrix = [[0] for i in range(3)]
# Following function generates the
# key matrix for the key string
def getKeyMatrix(key):
k = 0
for i in range(3):
for j in range(3):
keyMatrix[i][j] = ord(key[k]) % 65
k += 1
# Following function encrypts the message
def encrypt(messageVector):
for i in range(3):
for j in range(1):
cipherMatrix[i][j] = 0
for x in range(3):
cipherMatrix[i][j] += (keyMatrix[i][x] *
messageVector[x][j])
cipherMatrix[i][j] = cipherMatrix[i][j] % 26
def HillCipher(message, key):
# Get key matrix from the key string
getKeyMatrix(key)
# Generate vector for the message
for i in range(3):
#Driver Code Starts
messageVector[i][0] = ord(message[i]) % 65
# Following function generates
# the encrypted vector
encrypt(messageVector)
# Generate the encrypted text
# from the encrypted vector
CipherText = []
for i in range(3):
CipherText.append(chr(cipherMatrix[i][0] + 65))
# Finally print the ciphertext
print("Ciphertext: ", "".join(CipherText))
# Driver Code
def main():
# Get the message to
# be encrypted
message = "ACT"
# Get the key
key = "GYBNQKURP"
HillCipher(message, key)
if __name__ == "__main__":
main()
#Driver Code Ends
//Driver Code Starts
// C# code to implement Hill Cipher
using System;
class GFG
{
//Driver Code Ends
// Following function generates the
// key matrix for the key string
static void getKeyMatrix(String key,
int [,]keyMatrix)
{
int k = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
keyMatrix[i, j] = (key[k]) % 65;
k++;
}
}
}
// Following function encrypts the message
static void encrypt(int [,]cipherMatrix,
int [,]keyMatrix,
int [,]messageVector)
{
int x, i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 1; j++)
{
cipherMatrix[i, j] = 0;
for (x = 0; x < 3; x++)
{
cipherMatrix[i, j] += keyMatrix[i, x] *
messageVector[x, j];
}
cipherMatrix[i, j] = cipherMatrix[i, j] % 26;
//Driver Code Starts
}
}
}
// Function to implement Hill Cipher
static void HillCipher(String message, String key)
{
// Get key matrix from the key string
int [,]keyMatrix = new int[3, 3];
getKeyMatrix(key, keyMatrix);
int [,]messageVector = new int[3, 1];
// Generate vector for the message
for (int i = 0; i < 3; i++)
messageVector[i, 0] = (message[i]) % 65;
int [,]cipherMatrix = new int[3, 1];
// Following function generates
// the encrypted vector
encrypt(cipherMatrix, keyMatrix, messageVector);
String CipherText = "";
// Generate the encrypted text from
// the encrypted vector
for (int i = 0; i < 3; i++)
CipherText += (char)(cipherMatrix[i, 0] + 65);
// Finally print the ciphertext
Console.Write("Ciphertext: " + CipherText);
}
// Driver code
public static void Main(String[] args)
{
// Get the message to be encrypted
String message = "ACT";
// Get the key
String key = "GYBNQKURP";
HillCipher(message, key);
}
}
//Driver Code Ends
// Function to generate key matrix
function getKeyMatrix(key, keyMatrix) {
let k = 0;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
keyMatrix[i][j] = key[k].charCodeAt(0) - 65;
k++;
}
}
}
// Function to encrypt the message
function encrypt(cipherMatrix, keyMatrix, messageVector) {
for (let i = 0; i < 3; i++) {
cipherMatrix[i][0] = 0;
for (let x = 0; x < 3; x++) {
cipherMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
}
cipherMatrix[i][0] = cipherMatrix[i][0] % 26;
}
}
// Hill Cipher Function
function HillCipher(message, key) {
let keyMatrix = [
[0,0,0],
[0,0,0],
[0,0,0]
];
getKeyMatrix(key, keyMatrix);
//Driver Code Starts
let messageVector = [
[0],
[0],
[0]
];
for (let i = 0; i < 3; i++) {
messageVector[i][0] = message[i].charCodeAt(0) - 65;
}
let cipherMatrix = [
[0],
[0],
[0]
];
encrypt(cipherMatrix, keyMatrix, messageVector);
let cipherText = "";
for (let i = 0; i < 3; i++) {
cipherText += String.fromCharCode(cipherMatrix[i][0] + 65);
}
console.log("Ciphertext:", cipherText);
}
// Driver Code
let message = "ACT";
let key = "GYBNQKURP";
HillCipher(message, key);
//Driver Code Ends
Output
Ciphertext: POH
Decryption in Hill Cipher
For decryption,
- Find the inverse of the key matrix (mod 26).
- Divide the ciphertext into blocks of n letters.
- Treat each block as an n-dimensional vector.
- Multiply each vector by the inverse key matrix.
- Take the result modulo 26.
- Convert the numbers back to letters to obtain the original plaintext.
Illustration
The inverse of the matrix the key "GYBNQKURP" will be ,

Now the Ciphertext is "POH",

So, the result is "ACT".
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
// Generate key matrix from key string
void getKeyMatrix(string key, int keyMatrix[3][3])
{
int k = 0;
// Fill 3x3 key matrix
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
keyMatrix[i][j] = (key[k++]) % 65;
}
// Find modular inverse
int modInverse(int a)
{
a %= 26;
for (int x = 1; x < 26; x++)
if ((a * x) % 26 == 1)
return x;
return 1;
}
// Compute inverse key matrix
void inverseKey(int key[3][3], int invKey[3][3])
{
int det = key[0][0] * (key[1][1] * key[2][2] - key[1][2] * key[2][1]) -
key[0][1] * (key[1][0] * key[2][2] - key[1][2] * key[2][0]) +
key[0][2] * (key[1][0] * key[2][1] - key[1][1] * key[2][0]);
det = (det % 26 + 26) % 26;
int invDet = modInverse(det);
// Adjoint matrix * inverse determinant
invKey[0][0] = (key[1][1] * key[2][2] - key[1][2] * key[2][1]) * invDet % 26;
invKey[0][1] = (key[0][2] * key[2][1] - key[0][1] * key[2][2]) * invDet % 26;
invKey[0][2] = (key[0][1] * key[1][2] - key[0][2] * key[1][1]) * invDet % 26;
invKey[1][0] = (key[1][2] * key[2][0] - key[1][0] * key[2][2]) * invDet % 26;
invKey[1][1] = (key[0][0] * key[2][2] - key[0][2] * key[2][0]) * invDet % 26;
invKey[1][2] = (key[0][2] * key[1][0] - key[0][0] * key[1][2]) * invDet % 26;
invKey[2][0] = (key[1][0] * key[2][1] - key[1][1] * key[2][0]) * invDet % 26;
invKey[2][1] = (key[0][1] * key[2][0] - key[0][0] * key[2][1]) * invDet % 26;
invKey[2][2] = (key[0][0] * key[1][1] - key[0][1] * key[1][0]) * invDet % 26;
}
// Decrypt cipher and return message vector
string decrypt(string cipher, string key)
{
int keyMatrix[3][3];
vector<int> cipherVector(3);
vector<int> messageVector(3);
getKeyMatrix(key, keyMatrix);
int invKey[3][3];
inverseKey(keyMatrix, invKey);
// Convert cipher to numbers
for (int i = 0; i < 3; i++)
cipherVector[i] = cipher[i] % 65;
// Matrix multiplication
for (int i = 0; i < 3; i++)
{
messageVector[i] = 0;
for (int j = 0; j < 3; j++)
messageVector[i] += invKey[i][j] * cipherVector[j];
messageVector[i] = (messageVector[i] % 26 + 26) % 26;
}
string result;
for (int x : messageVector)
result.push_back(char(x + 65));
return result;
}
//Driver Code Starts
int main()
{
string cipher = "POH";
string key = "GYBNQKURP";
string result = decrypt(cipher, key);
// Print decrypted text
cout << "Decrypted Text: "<<result<<endl;
return 0;
}
//Driver Code Ends
//Driver Code Starts
public class GfG {
//Driver Code Ends
// Generate key matrix from key string
static void getKeyMatrix(String key, int[][] keyMatrix)
{
int k = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
keyMatrix[i][j] = key.charAt(k++) % 65;
}
// Find modular inverse
static int modInverse(int a)
{
a %= 26;
for (int x = 1; x < 26; x++)
if ((a * x) % 26 == 1)
return x;
return 1;
}
// Compute inverse key matrix
static void inverseKey(int[][] key, int[][] invKey)
{
int det = key[0][0]
* (key[1][1] * key[2][2]
- key[1][2] * key[2][1])
- key[0][1]
* (key[1][0] * key[2][2]
- key[1][2] * key[2][0])
+ key[0][2]
* (key[1][0] * key[2][1]
- key[1][1] * key[2][0]);
det = (det % 26 + 26) % 26;
int invDet = modInverse(det);
invKey[0][0] = (key[1][1] * key[2][2]
- key[1][2] * key[2][1])
* invDet % 26;
invKey[0][1] = (key[0][2] * key[2][1]
- key[0][1] * key[2][2])
* invDet % 26;
invKey[0][2] = (key[0][1] * key[1][2]
- key[0][2] * key[1][1])
* invDet % 26;
invKey[1][0] = (key[1][2] * key[2][0]
- key[1][0] * key[2][2])
* invDet % 26;
invKey[1][1] = (key[0][0] * key[2][2]
- key[0][2] * key[2][0])
* invDet % 26;
invKey[1][2] = (key[0][2] * key[1][0]
- key[0][0] * key[1][2])
* invDet % 26;
invKey[2][0] = (key[1][0] * key[2][1]
- key[1][1] * key[2][0])
* invDet % 26;
invKey[2][1] = (key[0][1] * key[2][0]
- key[0][0] * key[2][1])
* invDet % 26;
invKey[2][2] = (key[0][0] * key[1][1]
- key[0][1] * key[1][0])
* invDet % 26;
}
// Decrypt cipher
static String decrypt(String cipher, String key)
{
int[][] keyMatrix = new int[3][3];
int[][] invKey = new int[3][3];
int[] cipherVector = new int[3];
int[] messageVector = new int[3];
getKeyMatrix(key, keyMatrix);
inverseKey(keyMatrix, invKey);
for (int i = 0; i < 3; i++)
cipherVector[i] = cipher.charAt(i) % 65;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
messageVector[i]
+= invKey[i][j] * cipherVector[j];
messageVector[i]
= (messageVector[i] % 26 + 26) % 26;
}
String result = "";
for (int x : messageVector)
result += (char)(x + 65);
return result;
}
//Driver Code Starts
public static void main(String[] args)
{
String cipher = "POH";
String key = "GYBNQKURP";
String result = decrypt(cipher, key);
System.out.println("Decrypted Text: " + result);
}
}
//Driver Code Ends
# Generate key matrix
def getKeyMatrix(key):
keyMatrix = [[0]*3 for _ in range(3)]
k = 0
for i in range(3):
for j in range(3):
keyMatrix[i][j] = ord(key[k]) % 65
k += 1
return keyMatrix
# Find modular inverse
def modInverse(a):
a %= 26
for x in range(1,26):
if (a*x) % 26 == 1:
return x
return 1
# Compute inverse key matrix
def inverseKey(key):
invKey = [[0]*3 for _ in range(3)]
det = key[0][0]*(key[1][1]*key[2][2]-key[1][2]*key[2][1]) \
- key[0][1]*(key[1][0]*key[2][2]-key[1][2]*key[2][0]) \
+ key[0][2]*(key[1][0]*key[2][1]-key[1][1]*key[2][0])
det = (det % 26 + 26) % 26
invDet = modInverse(det)
invKey[0][0]=(key[1][1]*key[2][2]-key[1][2]*key[2][1])*invDet%26
invKey[0][1]=(key[0][2]*key[2][1]-key[0][1]*key[2][2])*invDet%26
invKey[0][2]=(key[0][1]*key[1][2]-key[0][2]*key[1][1])*invDet%26
invKey[1][0]=(key[1][2]*key[2][0]-key[1][0]*key[2][2])*invDet%26
invKey[1][1]=(key[0][0]*key[2][2]-key[0][2]*key[2][0])*invDet%26
invKey[1][2]=(key[0][2]*key[1][0]-key[0][0]*key[1][2])*invDet%26
invKey[2][0]=(key[1][0]*key[2][1]-key[1][1]*key[2][0])*invDet%26
invKey[2][1]=(key[0][1]*key[2][0]-key[0][0]*key[2][1])*invDet%26
invKey[2][2]=(key[0][0]*key[1][1]-key[0][1]*key[1][0])*invDet%26
return invKey
# Decrypt cipher
def decrypt(cipher,key):
keyMatrix = getKeyMatrix(key)
invKey = inverseKey(keyMatrix)
cipherVector = [ord(c)%65 for c in cipher]
messageVector = [0]*3
for i in range(3):
for j in range(3):
messageVector[i]+=invKey[i][j]*cipherVector[j]
messageVector[i]=(messageVector[i]%26+26)%26
result="".join(chr(x+65) for x in messageVector)
return result
#Driver Code Starts
if __name__=="__main__":
cipher="POH"
key="GYBNQKURP"
print("Decrypted Text:",decrypt(cipher,key))
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GfG
{
//Driver Code Ends
// Find modular inverse
static int modInverse(int a)
{
a %= 26;
for(int x = 1; x < 26; x++)
if((a * x) % 26 == 1)
return x;
return 1;
}
// Compute inverse key matrix
static void inverseKey(int[,] key, int[,] invKey)
{
int det =
key[0,0]*(key[1,1]*key[2,2]-key[1,2]*key[2,1]) -
key[0,1]*(key[1,0]*key[2,2]-key[1,2]*key[2,0]) +
key[0,2]*(key[1,0]*key[2,1]-key[1,1]*key[2,0]);
det = (det % 26 + 26) % 26;
int invDet = modInverse(det);
// Adjoint matrix * inverse determinant
invKey[0,0] = (key[1,1]*key[2,2]-key[1,2]*key[2,1]) * invDet % 26;
invKey[0,1] = (key[0,2]*key[2,1]-key[0,1]*key[2,2]) * invDet % 26;
invKey[0,2] = (key[0,1]*key[1,2]-key[0,2]*key[1,1]) * invDet % 26;
invKey[1,0] = (key[1,2]*key[2,0]-key[1,0]*key[2,2]) * invDet % 26;
invKey[1,1] = (key[0,0]*key[2,2]-key[0,2]*key[2,0]) * invDet % 26;
invKey[1,2] = (key[0,2]*key[1,0]-key[0,0]*key[1,2]) * invDet % 26;
invKey[2,0] = (key[1,0]*key[2,1]-key[1,1]*key[2,0]) * invDet % 26;
invKey[2,1] = (key[0,1]*key[2,0]-key[0,0]*key[2,1]) * invDet % 26;
invKey[2,2] = (key[0,0]*key[1,1]-key[0,1]*key[1,0]) * invDet % 26;
}
// Decrypt cipher and return message vector
static List<int> decrypt(string cipher, int[,] invKey)
{
int[] cipherVector = new int[3];
List<int> messageVector = new List<int>();
// Convert cipher to numbers
for(int i = 0; i < 3; i++)
cipherVector[i] = cipher[i] % 65;
// Matrix multiplication
for(int i = 0; i < 3; i++)
{
int value = 0;
for(int j = 0; j < 3; j++)
value += invKey[i,j] * cipherVector[j];
messageVector.Add((value % 26 + 26) % 26);
}
return messageVector;
}
//Driver Code Starts
static void Main()
{
string cipher = "POH";
int[,] key = {
{6,24,1},
{13,16,10},
{20,17,15}
};
int[,] invKey = new int[3,3];
inverseKey(key, invKey);
List<int> message = decrypt(cipher, invKey);
// Print decrypted text
Console.Write("Decrypted Text: ");
foreach(int x in message)
Console.Write((char)(x + 65));
}
}
//Driver Code Ends
// Find modular inverse
function modInverse(a)
{
a %= 26;
for(let x = 1; x < 26; x++)
if((a * x) % 26 == 1)
return x;
return 1;
}
// Compute inverse key matrix
function inverseKey(key)
{
let invKey = [[0,0,0],[0,0,0],[0,0,0]];
let det =
key[0][0]*(key[1][1]*key[2][2]-key[1][2]*key[2][1]) -
key[0][1]*(key[1][0]*key[2][2]-key[1][2]*key[2][0]) +
key[0][2]*(key[1][0]*key[2][1]-key[1][1]*key[2][0]);
det = (det % 26 + 26) % 26;
let invDet = modInverse(det);
// Adjoint matrix * inverse determinant
invKey[0][0] = (key[1][1]*key[2][2]-key[1][2]*key[2][1]) * invDet % 26;
invKey[0][1] = (key[0][2]*key[2][1]-key[0][1]*key[2][2]) * invDet % 26;
invKey[0][2] = (key[0][1]*key[1][2]-key[0][2]*key[1][1]) * invDet % 26;
invKey[1][0] = (key[1][2]*key[2][0]-key[1][0]*key[2][2]) * invDet % 26;
invKey[1][1] = (key[0][0]*key[2][2]-key[0][2]*key[2][0]) * invDet % 26;
invKey[1][2] = (key[0][2]*key[1][0]-key[0][0]*key[1][2]) * invDet % 26;
invKey[2][0] = (key[1][0]*key[2][1]-key[1][1]*key[2][0]) * invDet % 26;
invKey[2][1] = (key[0][1]*key[2][0]-key[0][0]*key[2][1]) * invDet % 26;
invKey[2][2] = (key[0][0]*key[1][1]-key[0][1]*key[1][0]) * invDet % 26;
return invKey;
}
// Decrypt cipher and return message vector
function decrypt(cipher, invKey)
{
let cipherVector = new Array(3);
let messageVector = new Array(3).fill(0);
// Convert cipher to numbers
for(let i = 0; i < 3; i++)
cipherVector[i] = cipher.charCodeAt(i) % 65;
// Matrix multiplication
for(let i = 0; i < 3; i++)
{
for(let j = 0; j < 3; j++)
messageVector[i] += invKey[i][j] * cipherVector[j];
messageVector[i] = (messageVector[i] % 26 + 26) % 26;
}
return messageVector;
}
//Driver Code Starts
// Driver code
let cipher = "POH";
let key = [
[6,24,1],
[13,16,10],
[20,17,15]
];
let invKey = inverseKey(key);
let message = decrypt(cipher, invKey);
// Print decrypted text
let result = message.map(x => String.fromCharCode(x + 65)).join("");
console.log("Decrypted Text:", result);
//Driver Code Ends
Output
Decrypted Text: ACT