Show HN: Ariadne – A Rust implementation of aperiodic cryptography
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.
Looking at it naively - deriving a new key sounds similar to picking a new function within a family of possible functions?
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.
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.
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.
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.
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.
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.
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.
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.
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.