Show HN: Ariadne – A Rust implementation of aperiodic cryptography

30 ciphernomad-org 26 6/23/2025, 3:54:06 AM codeberg.org ↗
Hello HN, we're CipherNomad, the research initiative behind this project.

The Ariadne Protocol is our exploration of a different cryptographic model. The work began with an observation of primitives like the Lion transform, which use a static, hardcoded sequence of operations. This led us to ask: What if the cryptographic "program" wasn't a constant, but a dynamic, history-dependent variable?

Our first step was a "Cryptographic Virtual Machine" that took an explicit list of operations (a "Path"). This worked, but required sharing the Path object—an explicit dependency that needed to be managed.

The Ariadne Protocol is the maturation of that idea. It eliminates the explicit Path by making it implicit and emergent.

The core design is:

The Labyrinth: A large, deterministically-generated binary tree of cryptographic rounds.

The Thread: The secret path taken through the Labyrinth. This path is not stored or transmitted. It's rediscovered for each block of data by computing a keyed hash of the CVM's secret state and the public ciphertext chunk: hash(key, state, chunk).

This makes the cipher aperiodic: because the state ratchets forward after every block, the sequence of operations is guaranteed to never repeat. It also creates inherent tamper evidence—any modification to the ciphertext "snaps the thread" and turns subsequent output into noise.

This is experimental, unaudited alpha software. We are publishing it under CC0 because we believe foundational work like this should be an unrestricted public good.

Comments (26)

Medea · 1h ago
I am having trouble understanding the main purpose of this protocol. After looking at your code example, I want to ask: what is the benefit of using this instead of an AEAD (Authenticated Encryption with Associated Data) that is already available in Rust? What specific security guarantee does this give me that would help when I am building protocols?
bilekas · 55m ago
It's just a privacy-preserving network layer communication protocol, think onion router. Removing the dependency on third party verification.

Some further reading : https://netsec.ethz.ch/publications/papers/ariadne.pdf

it's generally seen as more secure and in cases more efficient.

> Ariadne enhances previous approaches to preserve communication privacy by introducing two novelties. First, the source route is encoded in a fixed size, sequentially encrypted vector of routing information elements, in which the elements' positions in the vector are pseudo-randomly permuted. Second, the temporary keys used to process the packets on the path are referenced using mutually known encrypted patterns. This avoids the use of an explicit key reference that could be used to de-anonymize the communications.

kennethallen · 4h ago
I have a few questions after reading the README.

First, if it uses PRNG with a fixed-size state, it isn't accurate to say it never repeats, correct? It will be periodic eventually, even if that takes 2^256 operations or more.

Second, can you go more into the potential practical or theoretical advantages? Your scheme is certainly more complicated, but I don't see how it offers better tamper protection or secrecy than a block cipher operating in an authenticated mode (AES+GCM, for instance). Those have a number of practical advantages, like parallel encryption/decryption and ubiquitous hardware support.

ciphernomad-org · 4h ago
You are correct. The probability of a state collision is cryptographically negligible, on the order of breaking a 256-bit hash function.

You're also right that AES-GCM is faster and has hardware support. Ariadne explores a different trade-off. Its primary advantage is its architectural agility.

Instead of a fixed algorithm, the sequence of operations in Ariadne is dynamic and secret, derived from the key and data history. An attacker doesn't just need to break a key; they have to contend with an unknown, ephemeral algorithm.

This same flexible structure allows the core CVM to be reconfigured into other primitives. We've built concepts for programmable proofs-of-work, verifiable delay functions, and even ring signatures.

jeroenhd · 4h ago
FYI your comments seem to be showing up as dead (dead comments don't show up by default, only when people logged into HN have them enabled), I think something may have triggered a shadowban on your account. Might want to send a message to the moderators.

I hit 'vouch' for the comment I'm responding to so it should be visible, but the other response you gave (https://news.ycombinator.com/item?id=44353277) is still listed as dead.

conradludgate · 2h ago
Hi, interesting project. Looking into the code, it seems that when the random round is Hash, you're not encrypting half of the chunk:

https://codeberg.org/CipherNomad/Ariadne/src/branch/main/cra...

You split the chunk in half, use right to derive the cipher material and then only apply it to left. This leaves right unchanged.

ciphernomad-org · 2h ago
This is a classic Feistel network round: L_new = L_old ^ F(key, R_old). It's a deliberate design.

The security of the Labyrinth relies on the composition of many rounds, not any single one. The unchanged right half from a Hash round is fully encrypted if the next round is a Stream round. Since the Labyrinth is a deep, aperiodic mix of both round types, the entire block is guaranteed to be diffused and encrypted.

willvarfar · 3h ago
Could some of the paths result in insecure ciphers and those moments of insecurity lead to a broader compromise?

E.g. the program goes through a state that is effectively 2DES which enables a meet-in-the-middle attack which allows an attacker to jump into the path at that point and dramatically reduce the search space for the next or preceding block etc?

ciphernomad-org · 3h ago
The security does not depend on the path's structure. It depends on the CVM's state ratchet.

The key and IV for every single round are derived from a keyed hash of the CVM's current state. This state is a cryptographic digest of the entire operational history up to that point.

So, even if a path structurally resembled a weak cipher like 2DES, the rounds would not have related keys. Each step is effectively a fresh cipher instance with a unique, unpredictable key. A meet-in-the-middle attack is not possible because there is no "middle" with a key relationship to exploit.

vintermann · 4h ago
Any algorithm can be recast as being "self-modifying", "aperiodic" etc. We don't gain any security by doing so. It's just a choice of how to model what the algorithm does which makes it harder to analyse. Sure, it makes it harder for an adversary to analyse too, but only if they stick to the author's way of modeling what the algorithm does - as opposed to finding a more concise description of what it does.
ciphernomad-org · 4h ago
That's the key distinction. This isn't just a complex function, but a programmable machine that enables new capabilities.

For example: verifiable, time-locked proof of computation on a secret program. A standard hash or ZK-SNARK can't prove the when or how long of a simulation. Our model can.

The execution of the secret program leaves an irreversible "scar" on a one-time-use Labyrinth. The final state of this scarred structure is a commitment to the entire computational history, which is then time-locked by a Verifiable Delay Function (VDF).

The proof isn't just an output; it's the final, mutated state of the Labyrinth itself. An adversary can't find a more concise model because the history of the computation is inseparable from the proof.

CharlieTrip · 4h ago
Hi, cryptography researcher here!

I'm sorry, but not having a mathematical formulation makes it extremely tedious to look into the protocol and get a feeling if it is secure or not (or if what you are doing makes even sense). If you plan to do some additional work, focus on clearly defining what you are doing for a (maths-)cryptography audience. This would definitely help!

But, I can try and give you my 2-cents after skimming the code: as far as I understand, the primitive is intrinsically sequential and encrypts chunk by chunk. Depending on the "type", you either use a stream-cipher or some OTP-like (with pad related to the hash of part of the message). You have a public way to decide (from the current chunk ciphertext?) which encryption method you use for the next chunk. Am I getting it correctly?

If this is the case, I have to admit that the OTP-like part looks weird and definitely would be the first place where to look into. Especially how the secret key is effectively expanded for the different "rounds", and if there might be some weird property for when the encryption scheme selects twice the same path.

ciphernomad-org · 4h ago
A formal spec is the next priority. We released the implementation first as the protocol is novel and we invite direct scrutiny of the work.

The path selection is secret, not public. It is determined by `hash(key, state, chunk)`. An attacker lacks the secret `key` and internal CVM `state` and cannot compute the path.

The key expansion and path collision mechanisms are as follows: 1. A round's key is derived from the master key, the CVM's state, and the unique nonce of the Labyrinth node being processed. 2. The CVM state ratchets forward after every block, making path collision negligible.

CharlieTrip · 3h ago
Despite it might sound weird, the format spec is exactly what is needed to scrutiny any cryptographic primitive. It should be the first output during the design of a security-oriented primitive/protocol. See it in this way, if you soon publish the specs and there is a massive cheese-hole, your implementation is kaput! And since security products (sometimes sadly) live in reputation-system, your product lost all the reputation regardless if it will be secure or not.

So, the path is determined step by step taking into account the initial chunk or the output chunk? I'm confused on what this "CVM state" is. Your primitive has a secret key and that it, right? Or is this state yet another secret that must be shared to use the primitive? Again, without a formal specification, it is tricky for me to understand what that "chunk" effectively is and why should allow a decryption. If chunk is the "input chunk", how can you reconstruct the same path if you do not have the input?

Wait, the "CVM state" is the "round" key? Why do you care about "path collision"? This "property" does not make any sense without some appropriate context.

ciphernomad-org · 3h ago
Let's clarify.

1. CVM State: It's an internal 32-byte register, not pre-shared. For each operation, it's initialized from a unique nonce (e.g., enc_nonce). This nonce is transmitted publicly with the ciphertext as part of a structured payload. The CVM's subsequent state evolution is secret, as it depends on the master key and operational history. It's an input to the round key derivation, not the round key itself.

2. Path Determination: The path is determined by the ciphertext chunk. During decryption, the ciphertext is used with the key and current state to find the path before it's decrypted.

3. Path Collision: This is critical because it implies a state collision. Since round keys are derived from the state, a state collision at the same Labyrinth node would cause catastrophic key reuse. The state ratchet is designed to make this negligible.

CharlieTrip · 3h ago
1. Sorry, without a formal specification what I see are too many "pieces" with non-standard names that play too many roles.

0. You know that all your replies, code and webpage look extremely like AI outputs? If this is the case, it would be way better if you are open about using such tools.

2. Meaning that encryption is way slower than decryption.

3. You are making this concept quite confusing. Path collision is inevitable because you only have two options to choose from, making it easy to get collisions. Round-key collisions are something different and merely depends on how you effectively derive such keys. I might be wrong because I would need time to think about, but I believe that to get a "catastrophic key reuse" you would have to get the same state, the same inputs for the round key derivation function, the same ciphertext to be used and, most probably, some additional information a-la chosen-plaintext to effectively get something out that would break that specific chunk. Since you claim you have some ratcheting mechanism, push the attack to other rounds might not even be possible. If not, then you might not really achieve forward secrecy.

ciphernomad-org · 1h ago
1. Formal Spec: You're right. A formal specification is the top priority. We released the code first as a concrete artifact to invite this exact kind of direct scrutiny.

0. Process: Our focus is on the technical merits of the work itself.

2. Encryption Speed: The process is computationally symmetric. Encryption is not slower than decryption. For each block, both operations perform one permutation and the navigation/state-update hashes.

3. Collisions & Key Reuse: This is the crucial distinction. A geometric path collision (e.g., L-R-L) is common and harmless. A catastrophic round key collision is what we prevent. The key for each round is derived from (master_key, state, node_nonce). Since the state is a cryptographic ratchet of the entire history and the node_nonce is unique to the position in the Labyrinth, a key-reusing state collision is cryptographically negligible.

ramchip · 4h ago
How does this differ from the KDF chain in Signal?

Looking at it naively - deriving a new key sounds similar to picking a new function within a family of possible functions?

ciphernomad-org · 3h ago
The core difference is what is being ratcheted.

Signal's Double Ratchet evolves the keys for a static algorithm like AES.

In Ariadne, the ratchet evolves the algorithm itself. The path through the Labyrinth, the sequence of cryptographic permutations, is a function of the CVM's state. The state ratchets, so the algorithm ratchets.

Signal gives you a new key for the same lock. We use a new key to build a new lock for every message, and the shape of that lock depends on the history of every one opened before it. This architectural difference is what allows the CVM to be reconfigured for other tasks like VDFs or cooperative proofs-of-work, where the "program" itself must be dynamic.

Asraelite · 4h ago
Is this or could this be adapted to be post-quantum?
ciphernomad-org · 4h ago
Yes. The core architecture is crypto-agile. Its foundation is quantum-resistant because it's built on symmetric primitives like hashing and stream ciphers.

We used X25519 and Ed25519 in the transport layer examples for clarity, as they are well-understood, not as a production baseline.

A post-quantum implementation would swap these out. The key exchange would use a hybrid model, combining X25519 with a PQC KEM like CRYSTALS-Kyber. The signature would be replaced with a PQC scheme like CRYSTALS-Dilithium.

This modularity is a fundamental part of the design.

fguerraz · 4h ago
I don’t think this is a public key algorithm, so it’s most likely quantum safe.
Asraelite · 4h ago
Oh, I got excited that there might be a novel approach to asymmetric cryptography.
ur-whale · 3h ago
The claim "This makes the cipher aperiodic" should be justified.

As an immediate counter, I would say that if your code runs on a physically finite machine (an however large, yet finite number of bits to store state), this strikes me as very unlikely to be theoretically true.

ciphernomad-org · 3h ago
You are correct from a formal perspective. Any finite state machine is periodic.

In cryptography, "aperiodic" means the period is computationally unreachable. We use a 256-bit state, making the probability of a collision negligible (on the order of 2^256). This is a parameter of the CVM; it could be increased to 512 bits or more if required.

This is the standard security model for all modern hash-based constructions.

stop50 · 6h ago