DEV Community

saji1970
saji1970

Posted on

I DNA-encode my encrypted database before writing it to disk - here's why (and why it's not "quantum" anything)

Every value in my little embedded key-value store gets encrypted, then
its ciphertext gets encoded as a string of A/C/G/T characters before it
ever touches the filesystem. Open the file in a text editor and you'll
see actual DNA-looking text - not because it's a gimmick, but because
that's genuinely the storage format.

This is mdc-lite, a ~348KB embeddable encrypted key-value store I
built in Rust for places a server can't reach - a watch face, a phone
app, a background service. It's part of a larger repo, ModelDB,
that also includes MDC, a Python conversational data engine (query AI
models, databases, images, and documents in plain English, no SQL) with
its own DNA-inspired archival storage tier.

The actual storage format

Every put() call does this, in order:

  1. Pack [key_len][key_bytes][value_bytes] into one plaintext buffer.
  2. Encrypt the whole thing with XChaCha20-Poly1305 (a 256-bit key you supply - the crate never generates or stores key material itself; real key custody belongs to the platform's secure hardware, iOS Secure Enclave or Android Keystore).
  3. DNA-encode the resulting [nonce][ciphertext][tag] blob: 2 bits per base, 00→A 01→C 10→G 11→T. Every byte maps to exactly 4 bases, so there's no padding ambiguity on decode.
  4. Write the ACGT text to disk, atomically (temp file + rename).

Filenames are keyed BLAKE3 hashes of the logical key, not the key name
itself, so a directory listing alone leaks nothing - no key names, no
values, no way to tell how many distinct keys exist versus how many
files are on disk.


rust
pub fn put(&self, key: &str, value: &[u8]) -> Result<(), LiteStoreError> {
    let mut plaintext = Vec::new();
    plaintext.extend_from_slice(&(key.len() as u16).to_le_bytes());
    plaintext.extend_from_slice(key.as_bytes());
    plaintext.extend_from_slice(value);

    let nonce = XChaCha20Poly1305::generate_nonce(&mut OsRng);
    let ciphertext = self.cipher().encrypt(&nonce, plaintext.as_ref())?;

    let mut record = nonce.to_vec();
    record.extend_from_slice(&ciphertext);
    let acgt_text = dna::encode(&record); // <- the actual bytes on disk

    fs::write(tmp_path, &acgt_text)?;
    fs::rename(tmp_path, final_path)?;
    Ok(())
}
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
saji1970 profile image
saji1970

Hi HN,

I've been building two related but separate projects under one repo:

  • mdc-lite – a tiny (348KB) embeddable encrypted key-value store for
    iOS/watchOS/Android/Wear OS/desktop. Every value and key name is sealed
    with XChaCha20-Poly1305 before it touches disk, and then the resulting
    ciphertext is encoded as a DNA base sequence (2 bits/base, A/C/G/T)
    before being written to the file. So the actual bytes on disk are ACGT
    text, not raw binary - "DNA-inspired storage" isn't just a name here,
    it's literally what the file contains. (The DNA encoding itself is
    public/reversible on its own - it's the encryption underneath that
    makes it unreadable without the key, not the encoding on top. I try to
    be explicit about that distinction in the docs, since "DNA storage"
    invites some real misconceptions.)

  • MDC (Molecular Data Center) - a Python conversational data engine:
    query AI models, databases, images, and documents in plain English, no
    SQL. It has an archival storage tier that does the same DNA-encoding
    trick at a bigger scale, plus a real error-correction and
    corruption-simulation harness for it (not real synthesized DNA,
    obviously - a software simulation of the redundancy problem DNA storage
    research actually has).

Things I tried to be careful about, since this space attracts a lot of
hype:

  • No physical DNA synthesis or sequencing anywhere - it's a software encoding scheme, and the docs say so explicitly, repeatedly.
  • I wrote up an honest treatment of where quantum computing actually connects to any of this: harvest-now-decrypt-later for long-retention archives (not "quantum encryption" - that's QKD, a completely different, unrelated fiber-link technology). And separately, since people keep asking "can you just store the data as a quantum state instead": I ran a QuTiP Lindblad-equation simulation to check, rather than assume - decoherence erases a qubit's superposition within a handful of T2 lifetimes even completely unmeasured, verified against the closed-form analytic solution to ~1e-9 and confirmed grid-converged. So: no, and here's the physics for why.
  • Real, verified cross-platform builds (macOS/Windows/Android) published as GitHub releases, not just source you have to figure out building yourself.

Repo: github.com/saji1970/ModelDB
Docs/demo site: saji1970.github.io/ModelDB/
Whitepaper (the DNA + quantum honesty pass):
github.com/saji1970/ModelDB/blob/m...

Happy to answer questions about the encoding, the crypto choices, or
the conversational-query side.