Running-key cipher
With the key passage It was the best of times, Attack at dawn becomes Impaud hx eeog: each letter is shifted by the next letter of a long text that never repeats, while spaces stay put. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Text
- Attack at dawn
- Key
- It was the best of times
- Calculation mode
- encrypt
- Result
- Impaud hx eeog
- Encoding
- running_key
- Key letters
- ITWASTHEBESTOFTIMES
- Key length
- 19
This running-key cipher tool encrypts or decrypts text with a classical polyalphabetic substitution that uses a long passage of key text as a non-repeating key stream, not a short keyword that wraps. Each alphabetic letter in the message is shifted by the next letter taken from the key passage, so the same plaintext letter can map to different ciphertext letters depending on position while the key never cycles back on itself. Only A–Z characters move: modular arithmetic on a twenty-six letter ring preserves case, and spaces, digits, punctuation, and other symbols pass through without consuming a key step. If the key passage has fewer letters than the message, the engine reports that the key is too short instead of silently wrapping like ordinary Vigenère.
What the running-key cipher is and what this tool returns
The running-key cipher is a member of the Vigenère family that replaces a short repeating keyword with a long external text stream—historically a page from a book, a newspaper column, or any agreed passage. You supply that key text; its alphabetic letters each define a Caesar shift from zero for A through twenty-five for Z. Plaintext letters are transformed in order: the first letter uses the first key letter, the second uses the next, and so on without wrapping when the stream would run out.
Encryption adds the key offset modulo twenty-six; decryption subtracts it with the same modular wrap so the two operations are exact inverses when the same passage is used. Non-letter characters never change and never advance the key index, which keeps phrase spacing and punctuation readable around the scrambled letters. This page always uses that textbook rule with case preservation and a strict length guard: the key stream must contain at least as many letters as the message.
Where a running key fits in lessons and puzzles
Developers and educators meet the running-key cipher in capture-the-flag warm-ups, textbook chapters on classical cryptology, and demos that contrast a non-repeating book passage with a short keyword that eventually leaks under Kasiski examination. Frontend teams can scramble sample phrases for screenshots without inventing a custom alphabet, then recover them with decrypt under the same passage. Backend services encode short challenge strings for puzzle APIs or teaching sandboxes where students must supply a long enough key text to unlock the next step.
Quality engineers generate deterministic encrypt and decrypt pairs for contract tests so a middleware that claims running-key support cannot silently wrap a short keyword. Contest organizers precompute answer keys for modest English phrases without trusting opaque web toys that change spacing rules or force uppercase-only output. Product and education tools use the transform when a learner pastes ciphertext and the UI must show the recovered plaintext under a documented passage, or when the UI must explain why a short key was rejected.
Pair it with other classical encoding helpers when you are building a small lab of free, deterministic text tools, and never treat running-key as a substitute for modern authenticated encryption.
What you can do with it
CTF and classical cipher practice
Encrypt and decrypt messages with a long key-text stream for puzzles, classrooms, and capture-the-flag warm-ups that teach non-repeating Vigenère.
History-of-crypto lessons
Demonstrate book-passage keying, case-preserving transforms, and why a key that is too short must fail instead of wrapping like keyword Vigenère.
FAQ
What does the running-key cipher tool cost?
It is free in your browser on this page.
How do I decrypt a running-key message?
Send the ciphertext as text, the same key-text passage as key, and set mode to decrypt (or dec, decode, d). Encryption is the default when mode is omitted.
What happens if the key is too short?
The running-key passage must contain at least as many A–Z letters as the message; shorter keys are rejected with a clear too-short message.
How is this different from keyword Vigenère?
Classic Vigenère wraps a short keyword forever. Running-key never wraps: each key letter is used once from a long passage, and an undersized key is an error.
Is running-key secure for real secrets?
No. It is a classical teaching cipher. Use modern authenticated encryption such as AES-GCM for real confidentiality.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/enc/running-key \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Attack at dawn","key":"It was the best of times"}'const res = await fetch("https://api.kit.forhosting.com/enc/running-key", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "Attack at dawn",
"key": "It was the best of times"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/running-key",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "Attack at dawn",
"key": "It was the best of times"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/running-key", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"Attack at dawn","key":"It was the best of times"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"Attack at dawn","key":"It was the best of times"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/running-key", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "Attack at dawn",
"key": "It was the best of times"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.running_key",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Use it free in the browser for CTF warm-ups, history-of-crypto lessons, and book-cipher style demos, or call the API at $0.002 per successful request when pipelines need reproducible running-key transforms.
What the running-key cipher is and what this tool returns
The JSON response includes result for the transformed string, encoding fixed to running_key, mode set to encrypt or decrypt, key_letters showing the full normalized uppercase stream extracted from your passage, key_length for that stream, key_used and key_used_length for the prefix actually consumed, message_letters, input_length and output_length which match because the transform is length-preserving, shifted_chars counting how many letters moved, and a formula string that restates the modular mapping and the no-wrap rule for documentation and tests. There is no silent fallback to keyword Vigenère or Autokey: either the key is long enough and the transform runs, or the request fails with invalid_input. If you need AES, classic repeating-keyword Vigenère, Autokey, or Base64, use those dedicated endpoints; this landing answers only the classical running-key contract that crypto history chapters and CTF warm-ups already describe.
How text, key, and mode are read and how short keys are rejected
The preferred payload fields are text for the message, key for the key-text passage, and optional mode for encrypt or decrypt. Text accepts aliases such as input, value, s, message, plaintext, and ciphertext so forms and SDK clients can reuse existing column names. Key accepts key_text, keytext, passage, book, keyword, and k; only alphabetic characters inside the key are kept and uppercased into key_letters, while digits and symbols in the passage are ignored. If after that filter no letter remains, the engine rejects the request. Mode defaults to encrypt when omitted and also accepts short aliases such as enc, encode, e for encrypt and dec, decode, d for decrypt; any other string fails validation. Missing text, empty text, non-string types, and unknown modes all raise invalid_input so a blank form does not look like a successful no-op. After parsing, the engine counts how many letters appear in the message and compares that count to key_length. When the key is too short, the response is invalid_input with an explicit message that names both counts and asks for a longer key text—exactly the failure mode this capability is designed to report, not a silent wrap that would reintroduce keyword Vigenère behavior. Every letter is processed with the fixed modular map and the key index advances only on letters and only forward, so encrypting then decrypting with the same passage always restores the original payload when the key was long enough. Pair the free browser run on this page with the priced API when you need the identical mathematical result inside an automated pipeline without re-implementing the non-wrapping stream yourself. Invalid inputs return invalid_input and are not charged, which keeps validation cheap while successful transforms remain a fixed item price.
Where running-key fits in lessons, puzzles, and test fixtures
On this page the work runs entirely in your browser; through the API each successful lookup costs $0.002, failed validation is not charged, and nothing is stored after the response returns. That split — free interactive exploration and a priced, identical API — matches the rest of the KIT tier-A catalog and lets you move from a classroom demo to an automated pipeline without changing the transformed result.
Integration use cases
Deterministic CI fixtures
Generate reproducible running-key ciphertext and plaintext pairs for unit tests, golden files, and contract checks, including short-key error cases.