Guide

Analysis

Brute force a Caesar with all 25 shifts. Read a histogram and the index of coincidence before guessing a key.

Brute force

A Caesar has 25 keys. The attack is all of them, then read:

ciphers brute "KHOOR ZRUOG"
  shift= 1 → JGNNQ YQTNF
  shift= 2 → IFMMP XPSME
  shift= 3 → HELLO WORLD
  ...

There is no dedicated function for this in the library, and there shouldn't be. It's create("caesar").decode(text, { shift }) in a loop from 1 to 25 - that's what the command, the cipher_brute_caesar tool and the landing panel run. Shift 0 is not on the list. It would be the input, and the library refuses it as a shift anyway.

Frequency

import { analyzeFrequency } from "@agntn/ciphers";

const analysis = analyzeFrequency("DWWDFN DW GDZQ", "en");
analysis?.counts; // [["D", 4], ["W", 3], ["F", 1], ...] sorted by count
analysis?.reference; // "ETAOINSHRDLCUMWFGYPBVKJXQZ"
analysis?.ic; // index of coincidence

analyzeFrequency(text, language) uppercases, drops everything outside A to Z and counts. No letters at all - undefined, not an empty table, so check before you read. The language picks the reference order, en or pl.

FieldMeaning
totalLetters counted
counts[letter, count] pairs, most frequent first
referenceExpected order for the language
icIndex of coincidence, missing with fewer than two letters

Reading the index of coincidence

The IC is the chance that two letters picked from the text are the same. English sits near 0.067, uniform random near 0.038. That one number tells you which family you are looking at before you try a single key:

  • Monoalphabetic substitution (Caesar, Atbash, Affine) keeps the histogram shape and only relabels the bars. IC stays high, and the tallest ciphertext letter is probably E.
  • Polyalphabetic (Vigenère, Alberti) spreads one plaintext letter over several ciphertext letters. IC drops toward 0.038 and the histogram goes flat. Time to look for a period.
  • Transposition (rail fence, columnar) moves letters without changing them. The histogram is the plaintext's, only the words are gone.

The Playground draws the histogram for any text, expected order next to actual.

The CLI

ciphers frequency "DWWDFN DW GDZQ"
ciphers frequency "ZAŻÓŁĆ GĘŚLĄ JAŹŃ" --lang pl

One bar per letter, expected and actual order, then the IC with the two reference values next to it so you don't have to remember them.

@agntn/ciphers·MIT license· Classical ciphers, for lessons and puzzles. Not for protecting anything, ever.