TL;DR: I need a way for C/C++ code to detect whether SQLite is using SQLCipher or SEE. I cannot find any explicit way to do so; I can check SQLITE_HAS_CODEC
to see if encryption is enabled, but not which flavor of encryption.
I’m adding encryption support to my C++ SQLite wrapper library, sqnice. Basically I’m just adding two methods to my database
class: use_password
and change_password
, thin wrappers around sqlite3_key()
and sqlite3_rekey()
.
I’m presently using SQLCipher, but I have in the past used the SQLite Encryption Extension (SEE) at my day job. I’d like my library to be compatible with both. However, in looking into this I’ve found that, while the two share an API, the actual semantics of the two functions have diverged greatly:
- In SQLCipher, the key parameter defaults to being a password string (which will be run through a KDF). To pass a raw key you have to convert it to SQL hex-literal syntax.
- In SEE, the key defaults to being a raw key. To pass a password, you set
nKey
to a negative number; in that case thepKey
must be a NUL-terminated C string. - In SQLCipher, calling
sqlite3_key(db,NULL,0)
is illegal and will return an error. - In SEE,
sqlite3_key(db,NULL,0)
is a useful thing to do with a new database: it doesn’t encrypt it, but reserves space in every page which makes future encryption more efficient.
I would like my library to have both key- and password-oriented methods. However, doing this requires knowing which encryption library is present, since I have to encode the password or key differently. There doesn’t seem to be any explicit way to do so: SQLCipher doesn’t define any of its own macros nor identify itself in the SQLite version string.
The only solution I’ve come up with is to call sqlite3_key(db,NULL,0)
and check whether it returns SQLITE_ERROR
; if so, it’s SQLCipher. But that’s a kludge, and I’d much rather do something clearer and more reliable that won’t break in the future. Ideas?