Skip to content

kiloscheffer/jiddra

Repository files navigation

Jiddra

Jiddra is a language-mimicking involutory cipher. Its output looks and reads like the language it encrypts; about half the words come out as real words. And it is an involution: encrypt something twice and you get the original back, so encrypting and decrypting work the same way. It supports multiple languages and uses two types of context.

How it works

As Jiddra encrypts each letter, it tracks the last three characters in both the original and encrypted text. At every step, it ranks all possible letters by their likelihood in both contexts, first using groups of three letters, then two, then one. It then applies the Hungarian assignment to find the best one-to-one match, making sure no letter is mapped to itself.

The likelihood scores are smoothed: when the exact context is rare or missing, the cipher blends in statistics from shorter contexts and letter positions instead of falling back to plain letter frequency. This keeps rare contexts from producing letter combinations that never occur in the language.

Before ranking, a pair-frequency penalty weighs each candidate by how naturally it follows the previous letter. The smoothed scores already carry that information mid-word, so for most languages the penalty now applies only at the last letter, where it keeps word endings realistic. Word length also conditions the first and last letters, and at the second-to-last position letters that commonly sit just before a word ending get a push. All of this is tuned per language.

For words up to six letters, the scores also lean on the wordlist itself: letters that continue what has been written so far into a real word of the right length get a strong push, with each side following its own text. And letters that would leave the next position with only one natural follower are demoted (after a q, almost nothing but u can come), since whatever gets assigned there would usually read as a typo.

All context adjustments (pair-frequency, length weighting, wordlist blending, continuation demotion, ending preparation, vowel boost, and streak-break) are applied the same way to both the original and encrypted text rankings. This, along with the symmetric cost matrix, makes the cipher a perfect involution.

As a result, the encrypted text statistically resembles the original language. Letter frequencies, letter pairs, and word endings stay close to natural patterns, and roughly half of the words in typical text come out as real words of the language.

Word-length strategy

Word length Method
1 letter Kept as-is. Real one-letter words are so few (I and a in English) that any substitute would stick out as a letter that is not a word, and a fixed one-letter mapping hides nothing anyway
2+ letters Letter-by-letter cipher using three letters of context from both texts, with adjustments applied the same way to both rankings

Web

You can try it out at https://jiddra.xyz. Simply type or paste your text, and it will be encrypted instantly. Click the arrow to switch the output back to the input and see your original text again.

Usage

# Cipher (same operation encrypts and decrypts)
uv run python cipher.py --lang en "it was a dark and stormy night"

# Cipher files
uv run python cipher.py --lang en -i input.txt -o ciphered.txt
uv run python cipher.py --lang en -i ciphered.txt -o original.txt

# Pipe from stdin
echo "hello there" | uv run python cipher.py --lang en

Setup

Make sure you have Python 3.10 or later and uv. You can find all the required packages in uv.lock.

Run uv sync to create a .venv/ folder and install numpy, scipy, and flask.

Build the data files

uv run python build_wordlist.py --lang en   # text collection -> filtered word list
uv run python build_markov.py --lang en     # word list -> pairs and triplets of letter transitions

The pipeline loads the text collection from languages/{lang}/corpus/ and creates the data files the cipher needs in data/{lang}/. The text collections are not part of the repository. Download them using the links under Supported languages. To see the expected filename and format for each, check languages/{lang}/parse_corpus.py.

Deploy to a server

Flask runs under systemd and uses Python from the virtual environment. You only need uv during deployment to set up the virtual environment from uv.lock.

The generated files in data/ are not part of the repository, but the cipher needs them at runtime. Copy data/ from a machine that has run the build pipeline, or download the text collections and run the pipeline on the server.

# One-time
curl -LsSf https://astral.sh/uv/install.sh | sh
cd ~/git/jiddra && uv sync
sudo cp web/jiddra.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now jiddra

# After git pull
uv sync && sudo systemctl restart jiddra

Caddy manages secure connections at / and forwards requests from /api/* to Flask, which runs on 127.0.0.1:5000.

Supported languages

Languages are listed in order of how common they are on the web, following Languages used on the Internet.

Code Language Corpus Download On disk License
en English Google Books n-grams (gwordlist) 18 MB 18 MB CC-BY 3.0
es Spanish OpenSubtitles 2018 (FrequencyWords) 15 MB 15 MB CC-BY-SA 4.0
de German OpenSubtitles 2018 (FrequencyWords) 17 MB 17 MB CC-BY-SA 4.0
fr French OpenSubtitles 2018 (FrequencyWords) 10 MB 10 MB CC-BY-SA 4.0
sv Swedish PAROLE (Språkbanken) 8 MB 40 MB CC-BY 4.0
no Norwegian (Bokmål) NB Digital n-grams 2022 ~1 GB ~5 GB CC0
la Latin LatinISE v6 (LINDAT) 216 MB 216 MB CC BY-NC-SA 4.0

Quality metrics

The scores use the complete wordlists for each language, and the results take word frequency into account.

Metric English Spanish German French Swedish Norwegian Latin
Letter frequency MSE 0.91 0.60 0.21 0.15 0.32 0.27 0.49
Real words in output 64% 67% 71% 68% 67% 72% 48%
Top-50 bigram overlap 40/50 36/50 37/50 34/50 40/50 39/50 38/50
Roundtrip correctness 100% 100% 100% 100% 100% 100% 100%
Trigram context hit rate 57.8% 54.8% 55.8% 52.3% 58.0% 53.9% 61.7%
Letter pairs unseen in corpus 0.04% 0.02% 0.06% 0.12% 0.01% 0.01% 0.30%
Zero-corpus word endings 0.00% 0.01% 0.00% 0.03% 0.00% 0.00% 0.01%

License

Released under the MIT License © 2026 Kilo Scheffer.

The corpora listed under Supported languages are distributed by third parties under their own licenses (see that table); this project ships only code and configuration, not the corpus data.

About

Language-mimicking involutory cipher: encrypts text into natural-looking words of the same language, where encrypting twice restores the original.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Contributors