---
title: "aadhar.sh/lwe/vigenere · the Vigenère cipher & Kryptos"
description: "The Vigenère cipher and Kryptos at MSN-chat pace: keyed alphabets, autokeys, K1 to K3, the solved Paradigm PK recipes, and how to crank a Kryptos-shaped problem. Live workbench included."
path: "/lwe/vigenere"
section: "lwe"
kind: "content"
updated: "2026-06-21"
source: "https://aadhar.sh/lwe/vigenere"
---

> Site index: https://aadhar.sh/llms.txt
> Section index: https://aadhar.sh/lwe/llms.txt
> This is the Markdown twin of a page on aadhar.sh. The HTML at the source
> URL below is the original, and is hand-written and unminified on purpose.

# **Vigenère**Online, polyalphabetic ciphers & Kryptos

Learning With Errors  
keys & keystreams

**Heads up:** a **first-pass** walkthrough. **K1–K3** are the publicly-solved parts of [Kryptos](https://en.wikipedia.org/wiki/Kryptos) (Jim Sanborn, CIA HQ), so their mechanisms are public. Paradigm's ten Kryptos-style [PK puzzles](https://paradigm.xyz/kryptos-ctf/) are all solved too (the last two fell on 2026-10-02), so the back half opens our solver group's private notes: the PK1–PK8 recipes, PK7 as we solved it, and where we went wrong on PK8. The demos compute **real ciphertext and real statistics** live.

**aadharsh**23:01

every time I bring up **[Kryptos][kryptos]**, people go "oh, a Caesar cipher." it's so much more than a shift, right?

**Vigenère**23:01

Right. A **Caesar** cipher shifts every letter by *one fixed amount* (`A→D`, shift 3). That's **monoalphabetic**: the same [plaintext][plaintext] letter always maps to the same [ciphertext][ciphertext] letter, so a [frequency count][frequency-analysis] cracks it in seconds (E stays the most common letter, just relabeled).

A **Vigenère** cipher uses a *repeating key* of shifts: position 1 shifts by the 1st key letter, position 2 by the 2nd, and so on. The same plaintext letter lands as *different* ciphertext depending on its position. That's **polyalphabetic**, and it flattens the frequency signal.

Here's the unifying trick: a **Caesar is just a Vigenère with a one-letter key**. Key `J` repeats into the keystream `JJJJJJ…`, shifting every letter by the same 9, exactly a Caesar shift of 9. Key `JJJ` is identical, since it repeats into the same stream. A Caesar is the period-1 case; Vigenère is what you get once the key has more than one letter. Try it:

**Vigenère**23:02

Vigenère shared a demo: keystream workbench

Type a plaintext, a key, and an **alphabet** (the cipher uses the alphabet's *order*, so a keyed alphabet scrambles it). See the keystream and the ciphertext, computed live.

presets:

**aadharsh**23:04

and Kryptos K1–K3 are these?

**Vigenère**23:04

**K1** and **K2** are Vigenère on a **keyed alphabet**: the [tableau][tabula-recta] is built on the keyword `KRYPTOS`, so the alphabet becomes `KRYPTOSABCDEFGHIJLMNQUVWXZ` instead of `A…Z`. K1's key is `PALIMPSEST` and K2's is `ABSCISSA`, each repeated end to end. Hit the **Kryptos K1** preset above and it reproduces the real sculpture ciphertext EMUFPHZLRFAXYUSDJKZLD…; decrypt that and you get Sanborn's line ending in the deliberate misspelling *"…the nuance of iqlusion."*

**K3** plays a different game: it's a **transposition**. The letters are all correct, just rearranged by a route or columnar scheme. That split, substitution versus transposition, becomes the whole game once you reach the unsolved parts.

**aadharsh**23:05

plain Vigenère gets broken through the repeating key though, right? what's an **autokey**?

**Vigenère**23:05

Exactly: a repeating key has a **period**, and that period is its weakness. [Kasiski spacing][kasiski-examination] and the Friedman test recover the key length, and then it's one little Caesar per key letter, each solved separately. An **autokey** kills the period by *extending* the key with the message itself (the key, then the plaintext). No repeat means no period to find. Switch the demo's mode to *autokey* and watch the keystream stop repeating.

**aadharsh**23:06

ok, the Kryptos-style puzzles. how do you even *start* when you don't know anything?

**sidekick**23:07

AI · the general method

you treat it as a **search over a pipeline**, because you don't know the alphabet, the key, *or* the order of operations. the toolkit, in the abstract:

• **transposition**: columnar, route, rotation, skip-reads (rearrange the letters)  
• **substitution**: Vigenère and the **Quagmire I–IV** family, which differ in *which* of the plaintext, ciphertext, or key alphabets are keyed (QIII is the Kryptos one; **QIV** keys all three)  
• **running keys**: a long text used as the key, plus **autokeys**  
• **order**: transpose-then-Vig, Vig-then-transpose, "Vig first" versus "Vig last," stacked stages

you compose a candidate *pipeline* from those, run the text through it, and **score the output**. then crank the next combination. (the real PK pipelines, public now, close out this conversation.)

**aadharsh**23:07

let me actually try that, stack a couple of those ops, paste a ciphertext, and crank it by hand.

**Vigenère**23:07

Here's the workbench. Each **stage** is one operation (a **transposition**, a **substitution**, a **Vigenère**, or a plain **Caesar** shift) set to encrypt or decrypt. The pipeline runs top to bottom, so the *order* is yours: a Vigenère above a transposition is "Vig first," below it is "Vig last," and the two give different ciphertext. Watch a **transposition** keep every letter but shuffle the order, and a **substitution** swap the letters but keep the order.

Vigenère shared a demo: the cranking workbench

Stack operations, paste text, and run it. To **decode**, set every stage to *dec* and list them in the reverse of how it was encoded. Set the right recipe and a Kryptos-shaped ciphertext falls out as plaintext. The **PK** presets load real Paradigm ciphertext with its published recipe, already set to decode.

presets:

**aadharsh**23:08

"score the output," sure, but every candidate is just a wall of letters. how do you tell signal from noise?

**Vigenère**23:08

By the **statistical shape** of the letters. Random, polyalphabetic text reads *flat*, every letter roughly equally likely. Real language reads *lumpy*, with E, T, A spiking. The single number that captures this is the **Index of Coincidence**: the chance two random letters of the text match. English ≈ **0.067**; uniform random ≈ **0.038**. A correct (mono-alphabetic) decrypt jumps to ~0.067; a wrong, polyalphabetic one sits near 0.04. Paste candidates in and watch the noise:

**Vigenère**23:08

Vigenère shared a demo: the statistical shape of noise

Drop in any text. The **Index of Coincidence** and the frequency **shape** tell you how language-like it is, exactly the score you'd crank candidate decrypts against.

presets:

**Index of Coincidence**—English ≈ .067 · random ≈ .038 · **letters scored**—χ² vs English: —

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

—

**aadharsh**23:09

ok but I'm scoring these by hand. a machine should crank the whole search. can it just *break* one? give it something of mine, don't tell it the key, and let me watch.

**Vigenère**23:10

It can, and the whole attack is four steps. **One:** find the **period**. Slice the ciphertext into every-*k*th letter for each candidate key length and measure each slice's Index of Coincidence. At the wrong length the slices are still polyalphabetic and read flat (~.038); at the *right* one each slice is a single Caesar, so it reads English-lumpy (~.067). The period pops out of the chart. **Two:** at that length the Vigenère splits into *k* independent Caesars, so solve each one by picking the shift whose [χ²][chi-squared-test] against English letter frequencies is lowest. That gets most of the key. **Three:** [hill-climb][hill-climbing] the rest, because χ² only sees one column at a time and can't tell that column 3's guess makes `THEQ` where `THER` was available. Try all 26 shifts at each position, keep any that improves the **[quadgram][n-gram] score of the whole plaintext**, repeat until nothing improves. Cross-column context is what recovers the last letters. **Four:** report a verdict, because a solver that always answers is useless. Type your own message and key:

**Vigenère**23:10

Vigenère shared a demo: the cracker

Write a message, pick a key, and the top half encrypts it. The bottom half is handed the **ciphertext only** and has to find your key from scratch. Watch the four steps run, then compare what it recovered against what you chose.

you · you know the key

presets:

the cracker · ciphertext only, no key

**1 · period**

**2 · seed each column by χ²**

**3 · hill-climb on quadgrams**

**4 · verdict**

**sidekick**23:10

AI · where this one came from

the solver above is a JavaScript port of the periodic-cipher attack in [buttcrack](https://github.com/0xdiid/buttcrack) (MIT, © 2026 diid), a classical-cipher cracker built for *agents* to drive: every command is non-interactive and emits JSON, across 78 cipher types. its whole Vigenère family lives in one ~100-line file, `_periodic.py`, and the two ideas worth stealing are both in there. **seed by χ², then climb on the full text**, because per-column analysis alone can't recover a short key. and **dedupe candidates by resulting plaintext, keeping the shortest key**, so a 5-letter key and its 10-letter repeat collapse into one answer instead of competing.

what the port *doesn't* carry is the model. the real thing scores against 46,040 quadgrams with counts; this page ships the top **4,000 in rank order only**, 16 KB raw, **7.9 KB** over the wire, fetched the first time you press the button. measured cost of that cut: nothing above 100 letters, but it misses the 61-letter K1-shaped case that the full table gets.

**aadharsh**23:11

it nailed mine, then I shortened the message and it fell apart. what's the actual floor?

**Vigenère**23:11

Letters **per column** are what run out. A key of length *k* splits your text into *k* separate Caesars, and each one is solved from only its own slice, so 200 letters under a 4-letter key is a comfortable 50 per column while the same 200 under a 20-letter key is a starved 10. Measured on this exact solver and this exact table: at **20+ per column it solved every test**, at 12 it got 10 of 12, at 8 it got 6 of 12. That's the gauge under your message. It's also why **Kryptos K1 resists this** for two independent reasons at once. First, 63 letters under a 10-letter key is 6 per column. Second, the alphabet isn't `A–Z` anyway, so even a correct key decrypts to nothing. Short text starves the statistics; a keyed alphabet moves the target.

**aadharsh**23:11

back up to the **transposition** stage for a sec. K3 of Kryptos is pure transposition, no substitution at all, right? show me **columnar** specifically, and the double version.

**Vigenère**23:12

Right: in K3 every letter keeps its identity and only its *position* moves. Columnar is the workhorse. Write the message into a grid **row by row** under a keyword, then read it back **column by column**, taking the columns in the **alphabetical order of the keyword's letters**. `KRYPTOS` ranks its seven columns `1 4 7 3 6 2 5`, so you read the **K** column first, then **O**, then **P**, and so on. Same letters, new order, and a ragged last row is the only bookkeeping. **Double** columnar just runs that twice, the first ciphertext poured into a fresh grid under a second keyword. The two passes scramble the column structure enough that the hand version resisted [cryptanalysis][cryptanalysis] for decades. There's a clean step-by-step [walkthrough here](https://mathweb.ucsd.edu/~crypto/Projects/KarlWang/index2.html). Drag the grid:

**Vigenère**23:12

Vigenère shared a demo: columnar transposition

In by rows, out by columns. The keyword numbers the columns by alphabetical order and you read them **lowest number first**. Flip **double** to pour the first ciphertext into a second grid under a second keyword, the way K3-style ciphers stack stages.

presets:

**aadharsh**23:12

ok, the Paradigm puzzles. all ten are solved now (PK9 and PK10 fell on 2026-10-02), so we can open the notes. what were they actually?

**Vigenère**23:12

Mostly the toolkit on this page, stacked. The ten puzzles tell one story, a narrator chasing a legendary needle "fine enough to split a hair," and every substitution in the first eight is the same move: a Vigenère on the KRYPTOS alphabet (Quagmire III), each letter worth its index in `KRYPTOSABCDEFGHIJLMNQUVWXZ`. A test that runs in A–Z never sees it. The recipes, in encryption order:

• **PK1**: one Vigenère, `PROVENANCE`  
• **PK2**: one columnar, width 7, `MARGINS`  
• **PK3**: two Vigenères, `ORDINATE` + `PENTIMENTO`  
• **PK4**: columnar `UNDERLAY`, then `OCHRE` + `VERDIGRIS`  
• **PK5**: columnar `TWOYEARS`, then a running key that is all 224 letters of PK4's plaintext  
• **PK6**: two width-9 columnars, `HANDIWORK` and `SMITHWORK`, then `PORTAL`  
• **PK7**: `ANNEAL`, then a 3×3 matrix spelled by `ALCHEMIST`  
• **PK8**: four Vigenères, `METE`, `METER`, `METIER`, `MASTERY`

PK9 and PK10 fell after our shared notes stop, so their recipes aren't here. Two house rules held. The keys name the scene they hide in: `ALCHEMIST` encrypts PK7, whose whitesmith shows "his technique for purifying his metal." And every grid divides its text exactly: 350 = 7 × 50, 224 = 8 × 28, 272 = 8 × 34, 315 = 9 × 35, 279 = 3 × 93. No ragged last row anywhere, so the length hands you the admissible widths before you search.

**aadharsh**23:13

wait, PK3 puts two keys on the same letters. doesn't that just add up to one key?

**Vigenère**23:13

It does, and that's the trick. Add two repeating keys letter by letter and you get one repeating key whose period is their **least common multiple**. `ORDINATE` is 8 and `PENTIMENTO` is 10, so the sum repeats every 40, and collapsed it reads `BFPNBZITCSGKFENPJQHQVMWIQNUBWFAVXOZATKBJ`. That buys the setter two things. The period gets long: 280 letters over 40 columns is 7 per column, under the 8 where the cracker above got 6 of 12. And a solver who does recover the stream tends to throw it out, because no dictionary has it.

Our notes split PK3's stream back into its two words, and PK4's period-45 stream into `OCHRE` + `VERDIGRIS` (5 × 9). The rule we wrote down: never reject a recovered key for failing to be a word. Press **PK3** in the cranking workbench: two stages, real ciphertext in, "SEVENTH MONTH. I WROTE TO FIFTEEN CORRESPONDENTS" out.

**aadharsh**23:14

so PK8 is the same move with four words?

**Vigenère**23:14

Four words, and four is where the attack on this page dies. The periods are 4, 5, 6 and 7, their least common multiple is 420, and PK8 is 153 letters long. The summed key never repeats inside the text, so the cracker's step one has no period to find. Four short words built a running key. They're one word family, too: `METER`, drop a letter for `METE`, add one for `METIER` (a trade, a calling; PK8 ends on "the archive is my true calling"), then `MASTERY`.

The instruction sat in PK7's plaintext the whole time: "He has me repeat the same step four times with slight variations." Our group read that as structure, a period of 28 or four interleaved lanes. The solver who cracked it on 2026-09-06 read it as a recipe: the series' one substitution, four times, with keys that vary slightly. Press **PK8** in the workbench and watch "I LEAVE AT MIDNIGHT" fall out of four stages.

**aadharsh**23:15

how close did we get?

**sidekick**23:15

AI · from our PK8 notes, 2026-07-02 to 2026-09-06

close on the family, wrong on the word bank. word-sum Vigenère was on our list from the day PK3 came apart. we ran every pair from a 4,375-word thematic bank, three-word sums, and every subset of one to five of the keys harvested from PK1–PK7, in both alphabets. all cold, and correctly cold: `METER` was the only one of the four words in any bank, and nobody had tried four at once.

the instrument that misled us was a real one. we measured a faint period 7 in PK8 (column IC 0.0536, at the 99th percentile of a fixed-period null) and spent weeks on period-7 substitution under a transposition. the post-mortem found the signal at lags 28, 35 and 42, where `MASTERY` and one shorter word cancel at once, and found lags 7, 14 and 21, where `MASTERY` cancels alone, dead. every number we measured was right, and the model we built on them was wrong. forward-model the candidate keys before you trust what a period count implies.

**aadharsh**23:16

and PK7, the one we cracked ourselves?

**Vigenère**23:16

PK7 is a Vigenère hidden under a [Hill cipher][hill-cipher]. Encrypt with `ANNEAL` (period 6), cut the result into 3-letter blocks, and multiply each block by the matrix `ALCHEMIST` spells in KRYPTOS indices, `[[7,17,9],[14,11,18],[15,6,4]]`, mod 26.

Each layer blinds the other's detector. The Hill's input is Vigenère-of-English, so every Hill attack scoring against English frequencies read noise. The Vigenère sits under a three-letter mix, so Kasiski, the IoC period chart and every word-sum test read flat. We validated each single-layer attack on a planted cipher first, and each was correctly cold on PK7. What broke it was arithmetic, from a nudge by another solver in the group: 279 is odd, 279 = 3 × 93, so take the 3 literally. Solved 2026-07-02, and the re-encryption matched the official ciphertext on all 279 letters.

The cleanest lesson came on 2026-07-22. A Hill is linear, so `M(p + k) = Mp + Mk`, which makes Vigenère-then-Hill the same cipher as Hill-then-a-different-period-6-Vigenère (its key is the matrix applied to `ANNEAL`). For any linear layer, substitution-inside and substitution-outside are one family, and testing both spends the budget twice.

**sidekick**23:16

AI · the false positive worth stealing

our general-Hill attack once returned a "plaintext" scoring −5.16 per letter on quadgrams, about what English scores, and it was `WOLLASTONITE` repeated end to end: the Vigenère key it had guessed. a quadgram model rewards real words, and a key spelled over and over is wall-to-wall real words. two checks before calling anything solved: the decrypt isn't the key repeated, and it re-encrypts to the exact official ciphertext. it's the same reason the cracker above ends on a verdict instead of its best guess.

**aadharsh**23:17

so cranking Kryptos really means searching the space of (transposition × substitution × key × order), then ranking every candidate by how English-shaped its stats are, and re-encrypting before you believe any of them. thanks, Vigenère.

→ [Paradigm's Kryptos CTF](https://paradigm.xyz/kryptos-ctf/) · [Kryptos](https://en.wikipedia.org/wiki/Kryptos) ·[Vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) · [Index of coincidence](https://en.wikipedia.org/wiki/Index_of_coincidence) · [columnar transposition (Karl Wang, UCSD)](https://mathweb.ucsd.edu/~crypto/Projects/KarlWang/index2.html) · [back to Learning With Errors](https://aadhar.sh/lwe)

end of conversation (first pass)

This is a recorded conversation. Crank the workbench and stats above.

[kryptos]: https://en.wikipedia.org/wiki/Kryptos "A sculpture at CIA headquarters, made by Jim Sanborn in 1990, that carries four encrypted passages."
[plaintext]: https://en.wikipedia.org/wiki/Plaintext "The readable message before it is encrypted, or after it is decrypted."
[ciphertext]: https://en.wikipedia.org/wiki/Ciphertext "The scrambled output of encryption, unreadable without the key."
[frequency-analysis]: https://en.wikipedia.org/wiki/Frequency_analysis "Breaking a cipher by counting how often each letter appears and matching those counts to a language's known letter frequencies."
[tabula-recta]: https://en.wikipedia.org/wiki/Tabula_recta "A 26 by 26 table of alphabets, each row shifted one letter from the last, used to encrypt and decrypt Vigenère-style ciphers by lookup."
[kasiski-examination]: https://en.wikipedia.org/wiki/Kasiski_examination "A way to find a repeating key's length by measuring the gaps between repeated chunks of ciphertext; the key length usually divides those gaps."
[chi-squared-test]: https://en.wikipedia.org/wiki/Chi-squared_test "A statistic that measures how far a set of observed counts sits from the counts you'd expect; smaller values mean a closer match."
[hill-climbing]: https://en.wikipedia.org/wiki/Hill_climbing "A search that starts from a guess and keeps any small change that improves a score, stopping when no change helps."
[n-gram]: https://en.wikipedia.org/wiki/N-gram "A run of n letters in a row; a quadgram is four. Scoring text by how common its quadgrams are in English measures how language-like it reads."
[cryptanalysis]: https://en.wikipedia.org/wiki/Cryptanalysis "The study and practice of breaking ciphers and recovering secrets without being given the key."
[hill-cipher]: https://en.wikipedia.org/wiki/Hill_cipher "A cipher that turns each block of letters into numbers and multiplies the block by a key matrix, mod 26, so every output letter depends on the whole block."

Source: https://aadhar.sh/lwe/vigenere
