Skip to content
DSA in JavaScript
Applied & Puzzles

Caesar Cipher Algorithm

Algorithm · Stretch

Level: Stretch

Complexity

Time Complexity

O(|n|)

Space Complexity

O(|n|)

In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of 3, D would be replaced by A, E would become B, and so on. The method is named after Julius Caesar, who used it in his private correspondence.

Example

The transformation can be represented by aligning two alphabets; the cipher alphabet is the plain alphabet rotated left or right by some number of positions. For instance, here is a Caesar cipher using a left rotation of three places, equivalent to a right shift of 23 (the shift parameter is used as the key):

Plain:    ABCDEFGHIJKLMNOPQRSTUVWXYZ
Cipher:   XYZABCDEFGHIJKLMNOPQRSTUVW

When encrypting, a person looks up each letter of the message in the "plain" line and writes down the corresponding letter in the "cipher" line.

Plaintext:  THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Ciphertext: QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD

Code

caesarCipher.js
// Create alphabet array: ['a', 'b', 'c', ..., 'z'].
const englishAlphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');

/**
 * Generates a cipher map out of the alphabet.
 * Example with a shift 3: {'a': 'd', 'b': 'e', 'c': 'f', ...}
 *
 * @param {string[]} alphabet - i.e. ['a', 'b', 'c', ... , 'z']
 * @param {number} shift - i.e. 3
 * @return {Object} - i.e. {'a': 'd', 'b': 'e', 'c': 'f', ..., 'z': 'c'}
 */
const getCipherMap = (alphabet, shift) => {
  return alphabet
    .reduce((charsMap, currentChar, charIndex) => {
      const charsMapClone = { ...charsMap };
      // Making the shift to be cyclic (i.e. with a shift of 1 - 'z' would be mapped to 'a').
      let encryptedCharIndex = (charIndex + shift) % alphabet.length;
      // Support negative shifts for creating a map for decryption
      // (i.e. with shift -1 - 'a' would be mapped to 'z').
      if (encryptedCharIndex < 0) {
        encryptedCharIndex += alphabet.length;
      }
      charsMapClone[currentChar] = alphabet[encryptedCharIndex];
      return charsMapClone;
    }, {});
};

/**
 * @param {string} str
 * @param {number} shift
 * @param {string[]} alphabet
 * @return {string}
 */
export const caesarCipherEncrypt = (str, shift, alphabet = englishAlphabet) => {
  // Create a cipher map:
  const cipherMap = getCipherMap(alphabet, shift);
  return str
    .toLowerCase()
    .split('')
    .map((char) => cipherMap[char] || char)
    .join('');
};

/**
 * @param {string} str
 * @param {number} shift
 * @param {string[]} alphabet
 * @return {string}
 */
export const caesarCipherDecrypt = (str, shift, alphabet = englishAlphabet) => {
  // Create a cipher map:
  const cipherMap = getCipherMap(alphabet, -shift);
  return str
    .toLowerCase()
    .split('')
    .map((char) => cipherMap[char] || char)
    .join('');
};

References

Spotted a mistake or something unclear? Report it on GitHub.

On this page