Skip to content
Also from us: TypologyOnline.com · Free personality tests

Advanced Bacon's Cipher: Hiding A/B Patterns in Plain Sight

How Bacon's biliteral cipher turns letters into five-symbol patterns, then hides those patterns inside custom symbols, case changes, and ordinary-looking cover text.

Try the Advanced Bacon's Cipher tool
Illustration of Advanced Bacon cipher hiding A and B patterns inside styled text
Advanced Bacon separates the underlying A/B pattern from its visible representation, opening the door to simple steganographic hiding.

Simple Bacon's Cipher is easy to see. A message becomes visible A/B groups: HELLO turns into AABBB AABAA ABABA ABABA ABBAB. That is the teaching version.

The advanced version asks a more interesting question: what if the A and B symbols do not look like A and B at all? They could be 0 and 1, X and Y, . and -, or lowercase and uppercase letters hidden inside a harmless-looking sentence.

That is where Bacon's Cipher becomes more than a simple alphabet code. It becomes a bridge between encoding and steganography. Encoding changes the form of a message; steganography hides the existence of the message.

Bacon's great idea was that each letter could be represented by a pattern of two possible forms. Those forms might be written directly as A and B, but they could also be disguised as two fonts, two cases, two styles, two shapes, or two visual treatments.

The message does not have to look encrypted. It can look like ordinary writing. The visible sentence says one thing, while the pattern underneath says another.

Advanced Bacon's Cipher at a glance

Feature Advanced Bacon's Cipher
Type Biliteral cipher / steganographic encoding system
Main idea Map each plaintext letter to a five-symbol two-state pattern
Default variant 24-letter classical Bacon alphabet
Modern option 26-letter educational extension with distinct I/J and U/V
Code length 5 symbols per plaintext letter
Default pair A / B
Custom pairs 0 / 1, X / Y, . / -, or other distinct symbols
Classical merges I/J and U/V share codes in 24-letter mode
Direct mode Writes the Bacon pattern visibly
Case-based mode Hides the pattern using uppercase/lowercase styling
Raw stream Continuous clean symbol output without visible separators
Carrier requirement Each hidden letter needs 5 carrier letters
Security Not modern encryption; concealment depends on disguise quality
Best use Learning biliteral encoding, representation layers, steganography, and format fragility

The advanced tool is best understood as two layers working together.

Layer What it does
Bacon alphabet Turns plaintext letters into five-symbol A/B patterns
Representation mode Decides how those patterns are shown or hidden

The Bacon alphabet creates the pattern. The representation mode decides whether the pattern is obvious or concealed.

What makes this advanced?

Simple Bacon's Cipher shows the Bacon alphabet directly. Advanced Bacon's Cipher explores what else can be done with the same underlying pattern.

Simple Bacon Advanced Bacon
Shows A/B groups directly Can disguise the A/B pattern
Usually uses one visible output style Supports multiple representation modes
Uses A and B Can use custom pairs such as 0/1, X/Y, or . / -
Mostly teaches the alphabet Teaches representation and concealment
Easy to decode when seen Harder to notice if hidden well

The key idea is:

AABBB, 00111, XXYYY, and ..--- can all mean the same thing.

They are different costumes for the same underlying Bacon group. The advanced version separates the message pattern from its visible form.

What is Advanced Bacon's Cipher?

Advanced Bacon's Cipher is a flexible form of the Baconian, or biliteral, cipher. The word biliteral means that the system uses two signs, forms, or symbol classes.

In the simplest version, those signs are just:

A and B

But they do not have to be literal letters. The same Bacon pattern can be rendered using many different pairs.

Canonical Bacon Custom pair example
A 0
B 1

So:

AABBB

can be shown as:

00111

or, with . and -:

..---

The meaning is still the same Bacon pattern. Only the representation changes.

The Bacon alphabet

The classical Bacon alphabet uses five-symbol patterns. In 24-letter mode, I/J share one code and U/V share one code.

Letter Bacon group
A AAAAA
B AAAAB
C AAABA
D AAABB
E AABAA
F AABAB
G AABBA
H AABBB
I/J ABAAA
K ABAAB
L ABABA
M ABABB
N ABBAA
O ABBAB
P ABBBA
Q ABBBB
R BAAAA
S BAAAB
T BAABA
U/V BAABB
W BABAA
X BABAB
Y BABBA
Z BABBB

Now take the word:

HIDE

Using the classical 24-letter table:

Plain letter Bacon group
H AABBB
I ABAAA
D AAABB
E AABAA

So the canonical Bacon stream is:

AABBB ABAAA AAABB AABAA

The advanced tool can then render that same stream in several ways.

Direct custom symbols

Direct custom-symbol mode writes the pattern visibly, but replaces A and B with another pair.

If:

A = 0
B = 1

then:

AABBB ABAAA AAABB AABAA

becomes:

00111 01000 00011 00100

If:

A = .
B = -

the same message becomes:

..--- .-... ...-- ..-..

The message can change costume without changing its underlying pattern.

Worked example: direct custom symbols

Let us encode the hidden message:

HIDE

First, build the classical Bacon stream:

Plain letter Canonical Bacon
H AABBB
I ABAAA
D AAABB
E AABAA

So:

HIDE -> AABBB ABAAA AAABB AABAA

Now render with the custom pair 0/1:

Canonical Custom
AABBB 00111
ABAAA 01000
AAABB 00011
AABAA 00100

The final visible output is:

00111 01000 00011 00100

That output is still not modern encryption. It is simply the Bacon pattern written in a different alphabet.

Hiding a message in case

Case-based hiding uses lowercase and uppercase as the two Bacon forms.

Case Bacon value
lowercase A
uppercase B

A visible carrier text is modified so its casing carries the hidden pattern.

For example, the hidden message:

HIDE

has the Bacon stream:

AABBB ABAAA AAABB AABAA

That stream needs 20 carrier letters, because each hidden letter needs 5 visible letters.

Using the carrier:

the quick brown fox jump

the case-based output becomes:

thE QUiCk brown FOx jUmp

The readable cover text still says "the quick brown fox jump". The hidden casing pattern says HIDE.

Worked example: hiding a message in case

Start with the secret:

HIDE

Use the canonical Bacon stream:

AABBB ABAAA AAABB AABAA

Now apply the rule:

Bacon symbol Carrier case
A lowercase
B uppercase

Apply that pattern to the letters of:

the quick brown fox jump

The result is:

thE QUiCk brown FOx jUmp

To extract the hidden message, read the case pattern from the carrier letters, convert lowercase to A and uppercase to B, group the stream into fives, and decode the Bacon groups.

Carrier length

Case-based hiding consumes visible text. Each hidden plaintext letter needs five alphabetic carrier letters.

Hidden message length Required carrier letters
1 letter 5 carrier letters
5 letters 25 carrier letters
10 letters 50 carrier letters
20 letters 100 carrier letters

If the carrier is too short, the whole hidden message cannot fit.

The hidden message consumes visible text. That is why carrier length is one of the most important practical limits in Baconian steganography.

24-letter and 26-letter variants

The classical Bacon alphabet uses 24 positions. It combines:

I/J
U/V

So J is encoded as I, and V is encoded as U.

The 26-letter version gives every modern English letter its own pattern.

Variant Treatment
24-letter classical I/J and U/V are merged
26-letter modern I, J, U, and V are distinct

The 24-letter version is historically closer. The 26-letter version is more convenient for modern text, but it is best treated as a modern educational extension.

Using the CipherRegister Advanced Bacon's Cipher tool

The Advanced Bacon's Cipher tool lets you experiment with several representation layers.

Control What it does
Alphabet variant Switches between 24-letter classical and 26-letter modern modes
Direct symbols Writes the Bacon stream directly using A/B or a custom pair
Hidden mode Applies the stream to carrier text
Custom pair Uses symbols such as 0/1, X/Y, or . / -
Raw stream Shows the continuous Bacon pattern without separators
Carrier text Provides visible text for case-based hiding
Carrier length status Warns when the carrier is too short

The tool is not only encoding text. It is helping you see the difference between the underlying Bacon pattern and the way that pattern is represented.

What can go wrong?

Advanced Baconian hiding is fragile. It depends on formatting surviving.

Risk Why it matters
Case normalisation Converting text to lowercase destroys case-based hiding
Font changes Replacing fonts may erase font-based hiding
Copy and paste Some platforms strip formatting
Carrier too short The hidden message cannot fit
Wrong alphabet variant 24-letter and 26-letter mappings disagree
Ambiguous custom symbols Similar-looking symbols can be misread
Visible pattern If the A/B structure is obvious, decoding is easy

For example:

thE QUiCk brown FOx jUmp

contains a hidden pattern. But:

the quick brown fox jump

does not. The hidden data has been erased.

Security and limitations

Advanced Bacon's Cipher is not modern encryption.

Its concealment depends on the hidden pattern not being noticed and not being destroyed. Once the two-state pattern is suspected, extracting it is usually straightforward.

Limitation Why it matters
No strong secret key The table is usually known
Formatting is fragile Hidden patterns can be stripped or normalised
Pattern may be detectable Unusual casing or styling can draw attention
Low capacity Five carrier letters are needed per hidden letter
Not authenticated Changes may go undetected

The system is educational and historically fascinating. It is not suitable for protecting passwords, private messages, financial information, API keys, or sensitive personal data.

Cipher or system Relationship
Simple Bacon's Cipher Shows the visible A/B alphabet directly
Binary Also represents information with two possible states
Base32 Uses fixed-size groups in a modern encoding context
Morse code Uses two signal types, though with variable-length patterns
Tap Code Hides letters in counted physical signals
Steganography Hides messages inside another carrier

Advanced Bacon sits at the boundary between code and concealment.

A simple Python Advanced Bacon example

Advanced Bacon is a good programming example because the implementation has two layers: build the canonical Bacon stream, then render that stream using a chosen representation.

Python exampleShow code
BACON_24 = {
    "A": "AAAAA",
    "B": "AAAAB",
    "C": "AAABA",
    "D": "AAABB",
    "E": "AABAA",
    "F": "AABAB",
    "G": "AABBA",
    "H": "AABBB",
    "I": "ABAAA",
    "K": "ABAAB",
    "L": "ABABA",
    "M": "ABABB",
    "N": "ABBAA",
    "O": "ABBAB",
    "P": "ABBBA",
    "Q": "ABBBB",
    "R": "BAAAA",
    "S": "BAAAB",
    "T": "BAABA",
    "U": "BAABB",
    "W": "BABAA",
    "X": "BABAB",
    "Y": "BABBA",
    "Z": "BABBB",
}

BACON_26 = {
    letter: format(index, "05b").replace("0", "A").replace("1", "B")
    for index, letter in enumerate("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
}


def get_table(variant="24"):
    if variant == "24":
        return BACON_24

    if variant == "26":
        return BACON_26

    raise ValueError("Variant must be '24' or '26'.")


def normalise_letter(char, variant="24"):
    char = char.upper()

    if variant == "24":
        if char == "J":
            return "I"

        if char == "V":
            return "U"

    return char


def plaintext_to_bacon_stream(text, variant="24"):
    table = get_table(variant)
    groups = []

    for char in text:
        if char.isalpha():
            letter = normalise_letter(char, variant)
            groups.append(table[letter])

    return "".join(groups)


def render_stream(stream, symbol_a="A", symbol_b="B", group_size=5):
    rendered = []

    for char in stream:
        if char == "A":
            rendered.append(symbol_a)
        else:
            rendered.append(symbol_b)

    groups = []
    joined = "".join(rendered)

    for index in range(0, len(joined), group_size):
        groups.append(joined[index:index + group_size])

    return " ".join(groups)


def encode_direct(text, variant="24", symbol_a="A", symbol_b="B"):
    stream = plaintext_to_bacon_stream(text, variant)
    return render_stream(stream, symbol_a, symbol_b, group_size=5)


def decode_direct(encoded, variant="24", symbol_a="A", symbol_b="B"):
    table = get_table(variant)
    reverse_table = {value: key for key, value in table.items()}
    canonical = []

    for char in encoded:
        if char == symbol_a:
            canonical.append("A")
        elif char == symbol_b:
            canonical.append("B")

    stream = "".join(canonical)

    if len(stream) % 5 != 0:
        raise ValueError("Encoded stream must contain complete five-symbol groups.")

    output = []

    for index in range(0, len(stream), 5):
        group = stream[index:index + 5]
        output.append(reverse_table.get(group, "?"))

    return "".join(output)


def hide_in_case(secret_text, carrier_text, variant="24"):
    stream = plaintext_to_bacon_stream(secret_text, variant)
    carrier_letters = [char for char in carrier_text if char.isalpha()]

    if len(carrier_letters) < len(stream):
        raise ValueError("Carrier text does not contain enough letters.")

    output = []
    stream_index = 0

    for char in carrier_text:
        if char.isalpha() and stream_index < len(stream):
            if stream[stream_index] == "A":
                output.append(char.lower())
            else:
                output.append(char.upper())

            stream_index += 1
        else:
            output.append(char)

    return "".join(output)


def extract_from_case(carrier_text, hidden_letters, variant="24"):
    table = get_table(variant)
    reverse_table = {value: key for key, value in table.items()}
    needed_symbols = hidden_letters * 5
    stream = []

    for char in carrier_text:
        if char.isalpha() and len(stream) < needed_symbols:
            if char.isupper():
                stream.append("B")
            else:
                stream.append("A")

    if len(stream) < needed_symbols:
        raise ValueError("Carrier text does not contain enough letters.")

    output = []
    joined = "".join(stream)

    for index in range(0, len(joined), 5):
        group = joined[index:index + 5]
        output.append(reverse_table.get(group, "?"))

    return "".join(output)


# Example
secret = "HIDE"
carrier = "the quick brown fox jump"

direct = encode_direct(secret, symbol_a="0", symbol_b="1")
decoded = decode_direct(direct, symbol_a="0", symbol_b="1")
hidden = hide_in_case(secret, carrier)
extracted = extract_from_case(hidden, hidden_letters=4)

print("Secret         :", secret)
print("Direct 0/1     :", direct)
print("Decoded direct :", decoded)
print("Carrier        :", carrier)
print("Hidden carrier :", hidden)
print("Extracted      :", extracted)

Expected output:

Secret         : HIDE
Direct 0/1     : 00111 01000 00011 00100
Decoded direct : HIDE
Carrier        : the quick brown fox jump
Hidden carrier : thE QUiCk brown FOx jUmp
Extracted      : HIDE

The important distinction is that plaintext_to_bacon_stream creates the meaning-bearing pattern, while render_stream or hide_in_case decides how that pattern appears.

Common questions about Advanced Bacon's Cipher

Is Advanced Bacon's Cipher secure?

No. It is not modern encryption. It can hide a message from casual view if the representation is subtle, but once the pattern is suspected, extraction and decoding are usually straightforward.

Why does each letter use five symbols?

Because five positions with two choices gives:

2^5 = 32

possible patterns. That is enough for 24 letters, 26 letters, and some reserved patterns if a tool defines them carefully.

Can A and B be replaced with other symbols?

Yes. If A = 0 and B = 1, then AABBB becomes 00111. If A = . and B = -, then AABBB becomes ..---.

The underlying Bacon group is the same. Only the rendering changes.

How does case-based Bacon hiding work?

Case-based hiding uses lowercase and uppercase as the two Bacon forms. A visible carrier text is modified so its casing carries the hidden pattern.

The reader extracts the casing, converts it back to A/B, groups it into fives, and decodes the hidden message.

Why can case-based hiding be destroyed?

Because many systems normalise text case. If a hidden message depends on lowercase and uppercase, then any process that converts the text to all-lowercase or all-uppercase destroys the A/B pattern.

How long does the carrier text need to be?

Each hidden plaintext letter requires five carrier letters. A 10-letter hidden message requires 50 alphabetic carrier letters.

What is the raw symbol stream?

The raw symbol stream is the continuous Bacon pattern without visible separators, punctuation, or formatting.

For HIDE, the grouped form is:

AABBB ABAAA AAABB AABAA

and the raw stream is:

AABBBABAAAAAABBAABAA

Why Advanced Bacon's Cipher still matters

Advanced Bacon's Cipher should not be used to protect serious secrets. Not passwords. Not private messages. Not financial information. Not API keys. Not personal data. Not recovery phrases.

It is too fragile, too recognisable once suspected, and too far from modern authenticated encryption.

But it still earns its place.

It shows how letters can become five-symbol binary-style patterns. It shows how the same underlying message can be rendered as A/B, 0/1, X/Y, dots/dashes, or case changes. It shows why representation and meaning are not the same thing.

It also shows why formatting can carry information, and why that information can vanish when formatting is normalised.

Simple Bacon says: here is an A/B code, decode it. Advanced Bacon says: look closer. The real message may be in the pattern underneath.

That is why Advanced Bacon's Cipher still matters. Not because it is secure by modern standards. Because it teaches the difference between visible text, encoded data, and hidden communication.

Try the Advanced Bacon's Cipher tool

Open the Advanced Bacon's Cipher tool and try a short hidden message:

HIDE

Render it as direct A/B:

AABBB ABAAA AAABB AABAA

Then switch to a custom pair such as 0/1:

00111 01000 00011 00100

Then try a case-based carrier:

the quick brown fox jump

and watch it become:

thE QUiCk brown FOx jUmp

Use the tool to switch between 24-letter classical and 26-letter modern alphabets, render Bacon patterns with custom pairs, inspect the raw stream, test carrier text length, and see how fragile hidden formatting can be.

Sources and further reading

Try the Advanced Bacon's Cipher Tool

Want to experiment with the idea in practice? Open the matching tool and try your own text.

Open Advanced Bacon's Cipher
Signal acquired

A note from the team

We build these tools because we love cryptography, encoding, and making difficult ideas easier to explore. If they've helped you, even a small coffee means the world to the project. Thank you!

Say thanks on Ko-fi

Read next

Baconian Simple Bacon's Cipher: Turning Letters into A/B Patterns How Francis Bacon's five-symbol alphabet turned messages into binary-looking groups, and why the real trick was not the A and B, but how they could be hidden. Signalling Ciphers Tap Code Cipher: When Letters Became Knocks How a 5×5 square turned the alphabet into row-and-column tap groups, and made communication possible through walls, pipes, floors, and silence. Binary-to-Text Encoding Base32: The Encoding That Makes Binary Easier to Read, Copy, and Survive How a 5-bit alphabet became a quiet helper in authenticator apps, DNS-safe strings, recovery codes, identifiers, and text-shaped software systems.
Back to all articles