Documentation
¶
Overview ¶
Package sqlcipher implements the SQLCipher 4 on-disk page format in pure Go.
It is a port of the SQLCipher codec (https://github.com/sqlcipher/sqlcipher, v4.5.6, BSD-3, Copyright (c) ZETETIC LLC) — see NOTICE. It knows nothing about database/sql or SQLite drivers: it is the format, and only the format. Anything that must read or write SQLCipher files — a driver, a backup or replication path, a migration or a forensic tool — uses this package directly.
The format ¶
A SQLCipher database is a SQLite database whose pages are individually encrypted, with per-page reserve bytes carrying the IV and authentication tag:
page N on disk: [ ciphertext | IV (16) | HMAC-SHA512 (64) ] page 1 on disk: [ salt (16) | ciphertext | IV (16) | HMAC-SHA512 (64) ]
Pages are independent: no cross-page state, no chaining. The salt is the first SaltSize bytes of page 1 and is stored in the clear — it is the only part of the file that is not ciphertext. Because page 1's first SaltSize bytes hold the salt instead of SQLite's "SQLite format 3\x00" magic, page 1 encrypts only the bytes after that offset; Decrypt restores the magic, which is what SQLite's pager expects to see.
The ciphertext is AES-256-CBC with no padding, so its length is always a multiple of the AES block size. The IV is fresh on every page write. The HMAC covers ciphertext || IV || page number (little-endian uint32), which authenticates the page contents, the IV, and the page's position in the file — so pages cannot be reordered, and a modified IV is detected.
Keying ¶
A Key is either a raw 32-byte key (no KDF — SQLCipher's x'HEX' form) or a passphrase (PBKDF2-HMAC-SHA512, 256000 iterations by default). Either way the page-authentication key is a second, distinct key derived from the page encryption key using the salt masked with 0x3a and 2 PBKDF2 iterations.
Failing closed ¶
Decrypt authenticates before it decrypts and returns ErrKey on any HMAC mismatch. A wrong key errors; it never returns garbage plaintext.
Index ¶
Constants ¶
const ( SaltSize = 16 // KDF salt: the first bytes of page 1, stored in the clear KeySize = 32 // AES-256 IVSize = 16 // AES block size HMACSize = 64 // SHA-512 digest // Reserve is the per-page trailer SQLite must leave free at the end of every // page: IV || HMAC, rounded up to a multiple of the AES block size (it is // already a multiple, so 16+64=80). SQLite records it in byte 20 of the // database header, so a database carries its own reserve size. Reserve = IVSize + HMACSize // DefaultPageSize and DefaultIter are SQLCipher 4's defaults. DefaultPageSize = 4096 DefaultIter = 256000 )
Format sizes, all fixed by SQLCipher 4.
Variables ¶
var ErrKey = errors.New("sqlcipher: wrong key or corrupted page")
ErrKey reports that a page did not authenticate: the key is wrong, or the page was corrupted or tampered with. The two are deliberately indistinguishable.
Functions ¶
func DecryptFile ¶
DecryptFile decrypts a whole database, writing a plaintext SQLite database that any SQLite build can open without a key. The salt is read from the source's page 1.
The result keeps the source's per-page Reserve trailer — SQLite records the reserve in byte 20 of the header, so the plaintext database describes itself and stays a lossless round-trip back through EncryptFile.
func EncryptFile ¶
EncryptFile encrypts a whole plaintext SQLite database.
The source must already reserve Reserve bytes per page (header byte 20), which is what a database DecryptFile produced does; otherwise there is no room for the IV and tag and this returns an error rather than truncating data. A nil salt draws a fresh random one, which is what a new database wants; pass a salt only to rewrite a database under its existing one.
Types ¶
type Codec ¶
type Codec struct {
// contains filtered or unexported fields
}
Codec encrypts and decrypts the pages of one database. It is immutable and safe for concurrent use.
func NewCodec ¶
NewCodec binds key material to a database salt. salt is SaltSize bytes, read from the first bytes of page 1 of an existing database (see FileSalt), or freshly random for a new one.
Deriving from a passphrase runs Params.Iter PBKDF2 iterations and is deliberately slow; do it once per database, not once per page.
func (*Codec) Decrypt ¶
Decrypt decrypts one on-disk page and returns its plaintext. page must be exactly PageSize bytes; the result is a fresh slice of the same length.
The page is authenticated before it is decrypted, so a wrong key returns ErrKey rather than plausible-looking garbage. pgno is 1-based, as SQLite numbers pages.
Decrypting page 1 restores SQLite's "SQLite format 3\x00" magic over the salt, which is what SQLite's pager expects to read. The reserve trailer is carried through unchanged; SQLite ignores it.
func (*Codec) Encrypt ¶
Encrypt encrypts one plaintext page and returns the bytes to store on disk. page must be exactly PageSize bytes, of which only the first PageSize-Reserve carry data — SQLite guarantees that by reserving Reserve bytes per page.
Every call draws a fresh IV, so encrypting the same page twice yields different ciphertext. Encrypting page 1 writes the database salt over SQLite's magic.
type Key ¶
type Key struct {
// contains filtered or unexported fields
}
Key is database key material: a raw key or a passphrase. It is inert until bound to a database salt by NewCodec.
func Passphrase ¶
Passphrase derives the page encryption key from pass via PBKDF2-HMAC-SHA512.
type Params ¶
type Params struct {
PageSize int // cipher_page_size; 0 means DefaultPageSize
Iter int // kdf_iter, passphrase keying only; 0 means DefaultIter
}
Params are the format parameters that vary between databases. The zero value means SQLCipher 4 defaults; set a field only to interoperate with a database that was written with a non-default PRAGMA.