diff --git a/vfs/adiantum/README.md b/vfs/adiantum/README.md new file mode 100644 index 00000000..b037954c --- /dev/null +++ b/vfs/adiantum/README.md @@ -0,0 +1,29 @@ +# Go `"adiantum"` SQLite VFS + +This package wraps an SQLite VFS to offer encryption at rest. + +> [!WARNING] +> This work was not certified by a cryptographer. +> If you need vetted encryption, you should purchase the +> [SQLite Encryption Extension](https://sqlite.org/see), +> and either wrap it, or seek assistance wrapping it. + +The `"adiantum"` VFS wraps the default SQLite VFS using the +[Adiantum](https://github.com/lukechampine/adiantum) +tweakable and length-preserving encryption. + +In general, any HBSH construction can be used to wrap any VFS. + +The default Adiantum construction uses XChaCha12 for its stream cipher, +AES for its block cipher, and NH and Poly1305 for hashing. +It uses Argon2id to derive keys from plain text. + +> [!IMPORTANT] +> Adiantum is typically used for disk encryption. +> The standard threat model for disk encryption considers an adversary +> that can read multiple snapshots of a disk. +> The security property that disk encryption provides is that +> the only information such an adversary can determine is +> whether the data in a sector has or has not changed over time. + +The VFS encrypts database files, rollback and statement journals, and WAL files. \ No newline at end of file diff --git a/vfs/adiantum/adiantum.go b/vfs/adiantum/adiantum.go index 6e08ec37..13d1bdd6 100644 --- a/vfs/adiantum/adiantum.go +++ b/vfs/adiantum/adiantum.go @@ -8,7 +8,7 @@ import ( "lukechampine.com/adiantum/hbsh" ) -const salt = "github.com/ncruces/go-sqlite3/vfs/adiantum" +const pepper = "github.com/ncruces/go-sqlite3/vfs/adiantum" type adiantumCreator struct{} @@ -21,7 +21,7 @@ func (adiantumCreator) KDF(text string) []byte { return key[:] } - key := argon2.IDKey([]byte(text), []byte(salt), 1, 64*1024, 4, 32) + key := argon2.IDKey([]byte(text), []byte(pepper), 1, 64*1024, 4, 32) keyCachePut(text, (*[32]byte)(key)) return key } diff --git a/vfs/adiantum/api.go b/vfs/adiantum/api.go index f18a7fb5..c5c7db92 100644 --- a/vfs/adiantum/api.go +++ b/vfs/adiantum/api.go @@ -1,11 +1,34 @@ +// Package adiantum wraps an SQLite VFS to offer encryption at rest. +// +// The "adiantum" [vfs.VFS] wraps the default VFS using the +// Adiantum tweakable length-preserving encryption. +// +// Importing package adiantum registers that VFS. +// +// import _ "github.com/ncruces/go-sqlite3/vfs/adiantum" +// +// To open an encrypted database you need to provide key material. +// This is done through [URI] parameters: +// +// - key: key material in binary (32 bytes) +// - hexkey: key material in hex (64 hex digits) +// - textkey: key material in text (any length) +// +// [URI]: https://sqlite.org/uri.html package adiantum -import "github.com/ncruces/go-sqlite3/vfs" +import ( + "github.com/ncruces/go-sqlite3/vfs" + "lukechampine.com/adiantum/hbsh" +) func init() { Register("adiantum", vfs.Find(""), nil) } +// Register registers an encrypting VFS, wrapping a base VFS, +// and possibly using a custom HBSH cipher construction. +// To use the default Adiantum construction, set cipher to nil. func Register(name string, base vfs.VFS, cipher HBSHCreator) { if cipher == nil { cipher = adiantumCreator{} @@ -15,3 +38,13 @@ func Register(name string, base vfs.VFS, cipher HBSHCreator) { hbsh: cipher, }) } + +// HBSHCreator creates an [hbsh.HBSH] cipher, +// given key material. +type HBSHCreator interface { + // KDF maps a secret (text) to a key of the appropriate size. + KDF(text string) (key []byte) + + // HBSH creates an HBSH cipher given an appropriate key. + HBSH(key []byte) *hbsh.HBSH +} diff --git a/vfs/adiantum/hbsh.go b/vfs/adiantum/hbsh.go index f870a795..8d40d334 100644 --- a/vfs/adiantum/hbsh.go +++ b/vfs/adiantum/hbsh.go @@ -12,16 +12,6 @@ import ( "lukechampine.com/adiantum/hbsh" ) -// HBSHCreator creates an [hbsh.HBSH] cipher, -// given key material. -type HBSHCreator interface { - // KDF maps a secret (text) to a key of the appropriate size. - KDF(text string) (key []byte) - - // HBSH creates an HBSH cipher given an appropriate key. - HBSH(key []byte) *hbsh.HBSH -} - type hbshVFS struct { vfs.VFS hbsh HBSHCreator