Hill Cipher and Caesar Cipher Implementation in JavaScript
The trekhleb/javascript-algorithms repository implements both ciphers as pure functions under src/algorithms/cryptography/, using modular arithmetic for Caesar shifts and matrix multiplication via a shared linear algebra utility for Hill cipher encryption.
The trekhleb/javascript-algorithms repository provides clean, educational implementations of classic cryptographic algorithms including the Caesar cipher and Hill cipher. Located under src/algorithms/cryptography/, these implementations demonstrate functional programming patterns while handling alphabet shifts, modular arithmetic, and linear algebra operations required for polygraphic substitution.
Caesar Cipher Implementation
Core Architecture and File Location
The Caesar cipher implementation resides in src/algorithms/cryptography/caesar-cipher/caesarCipher.js. It defines a standard English alphabet array and exports two primary functions: caesarCipherEncrypt and caesarCipherDecrypt.
The implementation creates a simple alphabet array once:
const englishAlphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
The getCipherMap Function
At the heart of the implementation is getCipherMap(alphabet, shift), a helper that constructs a mapping object using Array.prototype.reduce. For each character, it calculates the target index as (charIndex + shift) % alphabet.length, handling negative shifts by adding alphabet.length when results fall below zero. This pure function enables both encryption and decryption via shift directionality.
Encryption and Decryption Functions
The caesarCipherEncrypt(str, shift, alphabet = englishAlphabet) function normalizes input to lowercase, splits it into characters, substitutes each via the cipher map (preserving non-alphabet symbols), and joins the result. The caesarCipherDecrypt function reuses the same machinery but passes a negative shift to getCipherMap, effectively reversing the substitution.
import {
caesarCipherEncrypt,
caesarCipherDecrypt,
} from './src/algorithms/cryptography/caesar-cipher/caesarCipher';
// Encrypt with a shift of 3
const secret = caesarCipherEncrypt('Hello, World!', 3);
console.log(secret); // khoor, zruog!
// Decrypt back to original
const plain = caesarCipherDecrypt(secret, 3);
console.log(plain); // hello, world!
Hill Cipher Implementation
Linear Algebra Foundation
The Hill cipher implementation in src/algorithms/cryptography/hill-cipher/hillCipher.js treats text as vectors and keys as matrices. It relies on the shared matrix utility at src/algorithms/math/matrix/Matrix.js for generation and multiplication operations, separating cryptographic logic from linear algebra mechanics.
Key Matrix Generation
The generateKeyMatrix function accepts a keyString whose length must be a perfect square (yielding an N×N matrix). Using mtrx.generate([size, size], callback), it populates each cell with values derived from character codes: (keyString.codePointAt(idx)) % alphabetCodeShift, where alphabetCodeShift is 65 (Unicode 'A'). This maps 'A'→0, 'B'→1, through 'Z'→25.
Message Vector Processing
The generateMessageVector function produces a column vector from the plaintext message, applying the same modulo transformation to each character's code point. This ensures numerical compatibility with the key matrix for subsequent multiplication.
Encryption Logic and Matrix Multiplication
The hillCipherEncrypt(message, keyString) function validates that inputs contain only letters (/^[a-zA-Z]+$/), generates the key matrix and message vector, and verifies dimensional compatibility (matrix side equals message length). It executes mtrx.dot(keyMatrix, messageVector) to produce the cipher vector, converting each result back to a character via String.fromCharCode((item % englishAlphabetSize) + alphabetCodeShift).
import { hillCipherEncrypt } from './src/algorithms/cryptography/hill-cipher/hillCipher';
// Key must be perfect square length; 4 letters = 2×2 matrix
const key = 'HILL';
const message = 'HELP';
const cipher = hillCipherEncrypt(message, key);
console.log(cipher); // → encrypted string (e.g., "RFKT")
Decryption Status
The hillCipherDecrypt function exists only as a stub containing a TODO comment. Decryption requires calculating the modular multiplicative inverse of the key matrix determinant and applying matrix inversion modulo 26, which remains unimplemented in the current codebase.
Shared Dependencies and Matrix Utilities
Both implementations leverage modular architecture. The Hill cipher specifically depends on src/algorithms/math/matrix/Matrix.js, which exports generate and dot functions. This separation allows the cryptographic algorithm to focus on character encoding and validation while the matrix library handles two-dimensional array construction and multiplication operations.
Summary
- The Caesar cipher in
src/algorithms/cryptography/caesar-cipher/caesarCipher.jsusesgetCipherMapto create shift-based character mappings, supporting encryption and decryption via positive and negative shifts. - The Hill cipher in
src/algorithms/cryptography/hill-cipher/hillCipher.jsimplements polygraphic substitution using matrix multiplication via the sharedMatrix.jsutility, requiring perfect-square keys and letter-only input. - Both algorithms follow functional programming patterns, operate as pure functions without side effects, and accept custom alphabets (Caesar) or modular arithmetic mappings (Hill).
- Hill cipher decryption remains unimplemented (stub with
TODO), while Caesar cipher provides complete bidirectional functionality.
Frequently Asked Questions
How does the Caesar cipher handle negative shift values?
The getCipherMap function automatically accommodates negative shifts by adding alphabet.length to any negative intermediate result before applying the modulo operation. This ensures that shifting left (decrypting) works correctly without requiring separate logic for directionality.
Why does the Hill cipher require a key of perfect square length?
The Hill cipher treats the key as an N×N matrix to perform linear algebra operations. The implementation in hillCipher.js calculates matrixSize as the square root of keyString.length, throwing an error if the result is not an integer. This dimensional requirement ensures the key matrix can multiply against the message vector.
Can the Caesar cipher implementation work with non-English alphabets?
Yes. Both caesarCipherEncrypt and caesarCipherDecrypt accept an optional alphabet parameter that defaults to the English alphabet array. By passing a custom array of characters (e.g., Cyrillic, Greek, or extended ASCII), the cipher operates correctly on any defined symbol set using the same modular shift logic.
Is the Hill cipher decryption functional in the current codebase?
No. The hillCipherDecrypt function in src/algorithms/cryptography/hill-cipher/hillCipher.js exists only as a stub containing a TODO comment. Decryption requires calculating the modular multiplicative inverse of the key matrix determinant and applying matrix inversion modulo 26, which remains unimplemented.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →