Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

classical-ciphers

test license: MIT

Tiny, dependency-free TypeScript implementations of the classic pen-and-paper ciphers — Caesar / ROT13 / ROT47, Vigenère / Autokey / Beaufort, and Atbash.

Every transform preserves letter case and passes non-letters (digits, spaces, punctuation, other scripts) through untouched, so each function is a total function over arbitrary text — safe to run over a whole document without mangling its shape.

🔐 Prefer an interactive version? Each cipher here has a free in-browser tool at textmachine.org — paste text, tweak the key, and copy the result. No sign-up, nothing leaves your device: Caesar / ROT · Vigenère · Atbash

🔎 Not sure which cipher you're looking at? Paste it into the Cipher Identifier — it analyses the text (letter frequency, Index of Coincidence, χ² shift tests) and ranks the likely ciphers, each with a one-click link to its decoder.

Install

npm install classical-ciphers

Usage

import {
  caesarShift, caesarEncode, caesarDecode, rot47, rotateDigits,
  applyVigenere,
  atbash,
} from "classical-ciphers";

// Caesar — shift within each case, punctuation untouched
caesarEncode("Hello, World!", 3);   // "Khoor, Zruog!"
caesarDecode("Khoor, Zruog!", 3);   // "Hello, World!"

// ROT13 is just a shift of 13 — and its own inverse
caesarShift("Attack at dawn", 13);  // "Nggnpx ng qnja"

// ROT47 over printable ASCII (also self-inverse)
rot47("Hello");                      // "w6==@"

// ROT5 over the digits 0–9
rotateDigits("Order 2026", 5);       // "Order 7571"

// Vigenère — a repeating keyword supplies a different shift per letter
applyVigenere("ATTACKATDAWN", "LEMON", "vigenere", "encode"); // "LXFOPVEFRNHR"
applyVigenere("LXFOPVEFRNHR", "LEMON", "vigenere", "decode"); // "ATTACKATDAWN"

// Autokey (key never repeats) and Beaufort (reciprocal — decode === encode)
applyVigenere("ATTACKATDAWN", "LEMON", "autokey",  "encode"); // "LXFOPKTMDCGN"
applyVigenere("ATTACKATDAWN", "LEMON", "beaufort", "encode"); // run again to decode

// Atbash — A↔Z mirror, self-inverse
atbash("Hello, World!");             // "Svool, Dliow!"

API

Function Signature Notes
caesarShift (text, shift) => string Rotate letters by shift (mod 26; negative/large normalised).
caesarEncode / caesarDecode (text, shift) => string Convenience wrappers (decode = shift by -shift).
rotateDigits (text, shift) => string ROT-N over the digits 0–9 only.
rot47 (text) => string Rotate printable ASCII (33–126) by 47; self-inverse.
applyCipher (text, cipher, direction) => string Dispatch {kind:"caesar",shift} | {kind:"rot5"} | {kind:"rot47"}.
normalizeKey (key) => number[] Reduce a keyword to its A–Z letters as 0–25.
applyVigenere (text, key, variant, direction) => string variant: "vigenere" | "autokey" | "beaufort". Empty/letterless key = identity.
atbash (text) => string A↔Z mirror; self-inverse.

Types Cipher, Direction ("encode" | "decode") and Variant are exported.

Design notes

  • No dependencies, no side effects — pure string→string functions.
  • Case-preserving and total — non-A–Z characters are emitted unchanged and, for Vigenère, do not advance the keystream, so message structure survives.
  • Self-inverse ciphers (ROT13, ROT47, Atbash, Beaufort) use the same call to encode and decode.
  • These ciphers are of historical / educational interest and are not secure — don't use them to protect real secrets.

License

MIT © 2026 Text Machine — built alongside the free text tools at textmachine.org.

About

Tiny dependency-free TypeScript classic ciphers — Caesar/ROT13/ROT47, Vigenère/Autokey/Beaufort, Atbash. Powers the free tools at textmachine.org

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages