mirror of
https://github.com/hanzoai/sqlite.git
synced 2026-10-30 18:22:26 +00:00
Converges the driver to ONE way, always encrypted, on every build. Encryption no
longer flips with a build tag: EncryptionAvailable() is always true and a keyed
store is never written as plaintext, because the pure-Go hanzoai/sqlcipher codec
is compiled into every build.
envelope.go (tag-neutral): a keyed open decrypts the SQLCipher file to a plaintext
copy on a RAM-backed filesystem (tmpfs), the database/sql engine (modernc or
csqlite) reads/writes that copy honouring the 80-byte reserve, and Close/Checkpoint
re-encrypts it to the real path under the file's salt via a temp+atomic-rename. The
real path is always SQLCipher ciphertext, byte-compatible with C libsqlcipher.
Routing:
- pure-Go (driver_nocgo): a key always routes to the envelope. The old
ErrEncryptionUnavailable dead-end is REMOVED — native Go now encrypts, it does
not reject keys.
- cgo (driver_cgo): the CodecLinked runtime probe now SELECTS the route — live
libsqlcipher when it is proven to encrypt (per-commit durability), otherwise the
pure-Go envelope. A broken/absent libsqlcipher degrades to the pure-Go codec,
never to plaintext, never to a dead end.
- EncryptionAvailable() is one tag-neutral value: true (detect.go).
Fail-closed confidentiality: the decrypted copy only ever lives on tmpfs/ramfs; if
no RAM-backed scratch dir exists the open fails closed rather than decrypt to
persistent storage (ramfsBase, isRAMBacked via statfs). Durability is at
Close/Checkpoint (documented); single writer per file.
Checkpoint(db) re-encrypts an open envelope mid-session to bound the crash-loss
window (no-op on the live-codec / unencrypted paths).
Tests: TestKeyedRoundTripAndCheckpoint, TestKeyedWrongKeyRejected,
TestEnvelopeFailsClosedWithoutRAMFS (tag-neutral); TestBrokenLibsqlcipherFalls\
BackToEnvelope and TestEnvelopeByteCompatWithLibsqlcipher (cgo: the envelope's
output and the live codec read each other's files, both directions, in one binary).
TestEncryptionProof now asserts ciphertext on every backend (no refuse branch).
Requires hanzoai/sqlcipher v0.1.1 (EmptyPlaintext seed); pinned to the sibling
checkout until that tag is published (see the replace in go.mod).
18 lines
581 B
Go
18 lines
581 B
Go
//go:build linux
|
|
|
|
package sqlite
|
|
|
|
import "golang.org/x/sys/unix"
|
|
|
|
// isRAMBacked reports whether dir resides on a memory-backed filesystem — tmpfs or
|
|
// ramfs — so a plaintext file written there lives in RAM and never reaches
|
|
// persistent storage. It is how the pure-Go SQLCipher envelope refuses to
|
|
// materialise a decrypted database anywhere it could be read from a disk snapshot.
|
|
func isRAMBacked(dir string) bool {
|
|
var st unix.Statfs_t
|
|
if err := unix.Statfs(dir, &st); err != nil {
|
|
return false
|
|
}
|
|
return st.Type == unix.TMPFS_MAGIC || st.Type == unix.RAMFS_MAGIC
|
|
}
|