Conversation Stenography: LLM Cover Text for Encrypted Chat, Built in Go
Use LLMs to hide messages inside normal looking conversations
At a glance
- What is it?
- A proof-of-concept Go tool that encrypts a message with AES-SIV and hides the ciphertext in the token choices of locally generated cover text, so the messaging app only sees an ordinary conversation. It is a demonstration, not a hardened transport.
- Who is it for?
- Adopt it for what the README says it is: a local demonstration of LLM steganography for two people who can meet in person to agree on a shared secret phrase, a conversation name, and the same model. Do not adopt it as a transport for messages that matter, because the author labels it a proof of concept with multiple issues and notes that detection techniques are already being developed.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 59 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem this solves is metadata, not ciphertext
Ordinary end-to-end encryption already protects message contents. What it does not hide is that an encrypted conversation is happening, and the README frames the motivation around exactly that: governments moving toward scanning private messages, and the risk that sending normal encrypted messages flags you on the basis of suspicion. Conversation Stenography attacks the outer layer. The ciphertext is not sent as ciphertext. It is encoded into the token choices of text that reads like ordinary chat, so a reader of the WhatsApp or Telegram thread sees a conversation about pasta, not a blob.
The intended user is narrow. The README's own personal note says the author is 18 and that LLM-based steganography has existed for years, with GPT-2 (the local model this project uses) released in 2019. That self-description matters for adoption: this is a working demonstration of a technique, aimed at people who want to see the technique run end to end on their own hardware, not at anyone who needs a dependable covert channel. The caution block says educational and research purposes, and the warning block says proof of concept with multiple issues.
AES-SIV in, token choices out
The pipeline in the README is short and worth reading literally. Your secret message goes through AES-SIV encryption. The resulting bytes are then encoded by a local AI model, which generates innocent text whose token choices carry those bytes. That cover text is what you paste into the messaging app. On the receiving side the same model recovers the encrypted bytes from the token choices, and AES-SIV decryption returns the original message.
The security properties listed are four. AES-SIV is described as authenticated encryption. A conversation chain cryptographically links every message to the previous one, so tampering, deletion, or reordering is detected. The model runs entirely on the device, with nothing sent to the cloud. The shared secret phrase is derived with PBKDF2 at 600,000 rounds and is never stored on disk.
The design consequence is that the model is not a convenience, it is part of the channel. Encoding and decoding depend on the same model producing and interpreting the same token choices on both ends. That is why the setup instructions insist both people pick the same model, and why a version mismatch is not a cosmetic problem.
Build, first run, and the simulate command
The README gives a three-command build. Clone the repository, change into it, then run go build -o conversation-stenography ./cmd/conversation-stenography. Note that the clone URL in the README points at github.com/nethical/conversation-stenography while the repository is nethical6/conversation-stenograpy on GitHub; if the clone fails, adjust the path.
Running the binary with no arguments starts a setup wizard on first run. According to the README it lets you pick an AI model with recommendations for your system, downloads the model automatically, and creates your config file. It does not name the config file path or its keys, so there is nothing to document there from the supplied material.
You do not need two devices to see it work. After setup, ./conversation-stenography simulate runs a two-person simulation in one terminal. You enter the shared secret phrase, the prompt starts as Alice, and each turn uses two independent protocol participants: one generates the cover text, the other decodes it, then the prompt switches users. The README states this exercises the same encryption, model encoding, decoding, and conversation chain used between separate devices. Simulation commands are /switch to change the active user without sending, /show to print the simulated plaintext conversation, /help, and /quit, which exits without saving state. Names and the conversation can be set with flags: ./conversation-stenography simulate -user-a Alex -user-b Samir -conversation test-chat.
For real use, the binary prompts for a conversation name and your name, then drops you into a chat prompt. Typing a message generates cover text to copy. The /paste SENDER command takes a message you received, and you terminate the paste with /end on its own line.
The conversation chain makes order a hard requirement
Because every message is cryptographically linked to the previous one, the two sides must process messages in the exact same order they appear in the messaging app. The README marks this as important and tells you what to do if you fall behind: use /paste to process the missed message before sending your next reply. This is a real operational constraint, not a note. A dropped message, a message read out of order, or a reply sent before you have processed an incoming one will break the chain, and the stated failure mode is detection of the mismatch rather than silent recovery. For a two-person chat that is manageable. For a group, or for anyone who reads messages across two devices at different times, it is a source of friction that the tool does not appear to smooth over.
There is a second constraint in the same area. Both people need the exact same configuration: the same secret phrase, the same conversation name, and the same model. The README's setup section says to meet in person to agree on these. The secret phrase is not stored on disk, which is good for exposure and bad for recovery. If you lose it, there is no reset path described. That is a deliberate trade, and it should shape how you pick the phrase: the README suggests six or more random words, with the example purple elephant dances under crimson moonlight.
Where the documentation stops
Several things you would want before relying on this are absent from the supplied material. There is no description of the config file format, so you cannot hand-edit model paths or parameters. There is no statement of how many bits per token the encoding carries, which determines how long a cover message has to be for a given plaintext length. There is no threat model beyond the two warning blocks, and no note on what happens when the model produces text that a human reader finds odd. The README warns that detection techniques are already being developed, which is the honest position for a project like this, but it does not say which ones or how they would apply here.
The author's own framing is the most useful documentation on the page. Calling it a proof of concept with multiple issues, and noting that the idea predates the project by years, sets the expectation correctly. Anyone reading the pipeline diagram and concluding they have a production covert channel has read past the two admonition blocks at the top.
What you give up compared with PGP over a normal channel
The obvious alternative is to skip steganography and send an encrypted file or PGP message through the same app. That approach is simpler in every operational respect: no shared local model, no token-level encoding, no strict ordering chain, and no dependence on a 2019-era model behaving identically on two machines. It also fails differently. A PGP block is visibly encrypted, which is the exact signal the README wants to avoid, and the tool's premise is that this signal is the risk.
A second comparison is worth naming because the README invites it: the local model. Running GPT-2 locally means no cloud inference, no API keys, and no network dependency for the encoding step. The cost is that quality of the cover text is bounded by that model, and both sides are tied to the same weights. A cloud LLM would produce better cover text and would also mean sending your encoded traffic to a third party, which defeats the point. The project's choice of a local model is the right one for its threat model, and it is also the source of most of its brittleness.
Licence and maintenance cost
The repository is GPL-3.0. If you fork it or ship a modified binary to other people, the copyleft terms apply to the distributed work, and that is a real consideration for anyone thinking of wrapping this in a product. This is not legal advice; read the licence text or ask a lawyer if the distribution matters to you.
On maintenance, the material is thin. There are no retrieved releases, so there is no versioned artifact to pin and no changelog to read. The last push date in the repository metadata is 2026-07-18, which tells you the project is not archived but says nothing about the cadence of fixes. The README's own warning about multiple issues is the only maintenance signal available. If you build on this, budget for reading the Go source rather than waiting for a tagged release, and expect the model download performed by the setup wizard to be the largest moving part in your setup.
Editorial conclusion
Adopt it for what the README says it is: a local demonstration of LLM steganography for two people who can meet in person to agree on a shared secret phrase, a conversation name, and the same model. Do not adopt it as a transport for messages that matter, because the author labels it a proof of concept with multiple issues and notes that detection techniques are already being developed. Before trusting anything, verify three things on your own machines: that both builds produce byte-identical cover text for the same input and model, that the conversation chain rejects a reordered or deleted message, and that the model file downloaded by the setup wizard matches on both sides.
Community notes