Porta cipher
With the passphrase PORTA, “Hello, World!” becomes “Oytub, Chjuq!”, and the same passphrase turns it back. Letters move through thirteen paired alphabets while spaces, digits and punctuation stay where they are. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Text
- Hello, World!
- Key
- PORTA
- Result
- Oytub, Chjuq!
- Encoding
- porta
- Key letters
- PORTA
- Key length
- 5
The Porta cipher is a classical reciprocal polyalphabetic cipher invented by Giovanni Battista della Porta: each Latin letter is transformed against a repeating passphrase using one of thirteen paired alphabets, and because that table is its own inverse, encrypting ciphertext with the same key restores the original plaintext. You paste any text and a passphrase that contains at least one Latin letter; letters A through Z and a through z move under the key while digits, spaces, punctuation, and other characters stay put so readable structure survives.
How the Porta cipher transforms text with a passphrase
Porta is a polyalphabetic cousin of the Vigenère family, but its encryption table is different and reciprocal. The twenty-six key letters collapse into thirteen rows: A and B share one alphabet, C and D the next, and so on through Y and Z. For every alphabetic character in the message, take the next passphrase letter (the key repeats for as long as there are letters to transform), choose the row for that pair, and map the plaintext letter through that half-alphabet table.
Letters in the first half of the alphabet (A through M) land in the second half (N through Z) with a row-dependent rotation, and letters in the second half land in the first half; case is preserved so uppercase H becomes an uppercase cipher letter and lowercase stays lowercase. Characters outside A through Z and a through z—including spaces, commas, digits, emoji, and accented letters outside the basic Latin block—are copied unchanged and do not advance the passphrase pointer. That design matches textbook Porta tables used in classical cryptography courses.
Because the table is an involution, applying the same passphrase a second time undoes the first transform: encrypt and decrypt are the same operation, so this tool does not need a separate mode flag. Mathematically every step is integer modular arithmetic over a fixed thirteen-pair structure; there is no floating-point rounding of the key, no network call, no random seed, and no wall-clock timestamp.
Where Porta cipher tools show up in real work
Introductory cryptography courses introduce Porta after Caesar and alongside other polyalphabetic tables so students practice reciprocal maps that do not need a separate decrypt rule and see how key-letter pairs collapse twenty-six letters into thirteen alphabets. Capture-the-flag warm-ups and puzzle hunts still hide Porta or Porta-variant messages, and solvers want a fast, predictable passphrase transform rather than a general cryptanalysis suite. Support and content teams sometimes lightly obfuscate spoilers, quiz answers, or internal labels with a classical passphrase cipher and need the reverse path without installing a language-specific crypto library.
If you need a fixed single-letter Caesar shift, multi-alphabet Vigenère addition, Beaufort subtraction, strong authenticated encryption, Base32 or Base64 encoding, or automatic frequency-analysis key recovery, treat those as separate search intents and landings rather than overloading this classical Porta passphrase page.
What you can do with it
Classroom reciprocal polyalphabetic demos
Encrypt and decrypt sample sentences with a known passphrase so intro-crypto lessons show Porta’s thirteen paired alphabets without a separate decrypt mode.
Puzzle and CTF passphrase ciphers
Apply or reverse a Porta passphrase on challenge strings without writing a one-off script for every problem set.
FAQ
What is the Porta cipher?
A classical reciprocal polyalphabetic cipher that maps each letter through one of thirteen alphabets selected by key-letter pairs (A/B, C/D, …, Y/Z). The same operation encrypts and decrypts.
How do I decrypt Porta ciphertext?
Call the same capability again with the ciphertext as text and the original passphrase. Because Porta is self-inverse, a second pass restores the plaintext.
What happens if the key is missing or empty?
The passphrase must contain at least one Latin letter A–Z or a–z; missing, empty, or letter-free keys are rejected and not charged.
Are spaces and punctuation encrypted?
No. Only A–Z and a–z are transformed. Spaces, digits, punctuation, and other characters pass through and do not advance the key.
What does it cost?
The browser tool is free and runs locally.
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/porta \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Hello, World!","key":"PORTA"}'const res = await fetch("https://api.kit.forhosting.com/enc/porta", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "Hello, World!",
"key": "PORTA"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/porta",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "Hello, World!",
"key": "PORTA"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/porta", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"Hello, World!","key":"PORTA"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"Hello, World!","key":"PORTA"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/porta", 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": "Hello, World!",
"key": "PORTA"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.porta",
"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
A missing key, an empty key, or a key with no alphabetic characters is rejected immediately with invalid_input, so homework checkers and scripts never silently fall back to a default passphrase.
How the Porta cipher transforms text with a passphrase
Identical text and passphrase always produce identical JSON. This page implements classical Porta only—not Vigenère addition, not Beaufort subtraction, not AES, and not an automatic key-recovery cracker that tries every dictionary word for you. Those are separate tools and separate search intents with their own landings.
What you send and what you get back
Send a required string field named text and a required string field named key. Classic checks include transforming Hello, World! with passphrase PORTA, verifying that feeding the ciphertext and the same key returns the original phrase, and confirming that an empty key is rejected rather than treated as a no-op identity. The text must be a non-empty string of the message to transform; the key must not be empty after the alphabetic filter: whitespace-only strings and keys that contain only digits or symbols fail with invalid_input and a clear English message that mentions the missing or empty key requirement. On success the response includes result as the transformed string, encoding set to porta, key_letters as the uppercase A–Z stream actually used, key_length as how many alphabetic positions that stream has, input_length and output_length, shifted_chars as a count of how many alphabetic characters moved, reciprocal true, and a formula string describing the pair-table rule so clients can assert the profile they hit. Missing text, missing key, non-string objects for either field, empty text, and keys with no letters fail with invalid_input. Validation failures do not consume prepaid balance.
Where Porta cipher tools show up in real work
Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.
Integration use cases
Lightweight spoiler and label obfuscation
Scramble quiz answers or internal labels with a classical passphrase and restore them later with the same contract in browser or API.