Sqlite, Encryption, and Zig

I threw together an app for work in go, and I’m trying to port it to Zig, but I hit a snag with zig-sqlite, and need to find an alternative solution.

The Goal

The app tracks .env files in your project repositories and stores them in an encrypted sqlite database for easy backups.

The ideal process for this would be:

  1. Load the encrypted file from disk into a buffer.
  2. Decrypt the buffer and load the result into an in-memory database
  3. (After all queries) re-encrypt the database into either a file or buffer, if the latter, then write to disk.

I realize this level of security is academic, since all the source files exist unencrypted on disk anyway.

The Solution

The best solution I was able to get working in go was to decrypt to a temporary file, ATTACH the file to a :memory: database, and then VACUUM INTO another temp file when done. However, when attempting this with zig-sqlite, I got an error which I created an issue for (it works in go).

I chose to use the age encryption library as I’m faimilar with its use from NixOS, and because it supports multiple encryption keys.


I am happy to explore pretty much any answer at this point. I think it’s worth trying zqlite, and maybe using native sqlite encryption would be better, but I’m not familar enough with it to know how it affects queries and such.

Feeling a bit of analysis paralysis, any advice is welcome :slight_smile:

I’ve been working on a personal project which is a local password manager where the database file is a sqlite database, so I’ve explored encryption on it a bit. I even ended up writing my own zig wrapper for sqlite (although still a little incomplete - sqlite API is pretty big).

My design doesn’t encrypt the database file, but rather encrypts columns in the database. So something like e.g.

CREATE TABLE Data(
  salt BLOB,
  data BLOB
);

In this design, the data gets encrypted and decrypted in memory, and the database layer never sees unencrypted data. However, that might not be suitable for your usecase.

For transparent encryption, the other option I explored was to use the VFS Layer. I think this might be more suitable for you. Basically, you implement an interface that’s quite similar to std.Io, and that layer acts as a shim between the database pages and what’s stored on disk. It’s a really powerful feature of sqlite to learn.

1 Like

Have you considered using sqlcipher? Since it’s basically the same API as sqlite you can probably use zig-sqlite or any other sqlite bindings with little modification.

1 Like

Considering what unprecedented breaking decisions Filippo is making (although perhaps he is only a visible talking head) in Golang cryptography, I’m less and less trusting of any of his solutions.