Inspecting the code of the latest SQLCipher version I see that the HMAC for page 1 of a database does not include the first 16 bytes that hold the key salt. Is this on purpose? Wouldn’t it have been better to include it in the HMAC calculation?
Maybe it is unlikely to happen, but if someone would tamper with the first 16 bytes of an opened database file from the outside, the application using SQLCipher would not be able to detect this by checking the HMAC.
Hello @utelle - Thanks for getting in touch about SQLCipher. The first 16 bytes of the database, which hold the salt, don’t need to be included in the HMAC calculation because they are used as input to PBKDF2-HMAC-SHA1 to derive the key material used for the per-page HMAC. Any outside modification to the first 16 bytes will therefore cause the HMAC check on the first page (and all subsequent pages) to fail.
thanks for the explanation. Maybe it really doesn’t matter, since SQLCipher rewrites the key salt every time page 1 is encrypted. There is still a chance that a change from the outside could make the database file inaccessible when opening it for the next time, if page 1 is not rewritten after the change of the database header. However, there is no way for SQLCipher (or any other encryption scheme) to detect this situation anyway.
Storing the key salt only in the database header seems to make the system quite vulnerable, since the database user knows only his passphrase, but not the random salt. So a modification to the first 16 bytes of the database file makes the database unusable without a chance to restore it - unless there is a backup copy available…
Hello @utelle thanks for getting back to us. I believe I understand what you’re saying, but I’m not sure how including the salt data in the HMAC would change things. A privileged external process could still come along and write to / obliterate that data if it were included in the 1st page HMAC. Either way, it would cause the HMAC check to fail.
Likewise, if a rogue process has the ability to write to the first 16 bytes, it would also be able to write elsewhere in the file, meaning it could easily corrupt data anywhere in the file.
Finally, it’s worth noting that if an application wants to manage it’s own salt and key data (e.g. in some other external secure storage like Android Keystore or iOS keychain), that is already possible via raw key semantics introduced in SQLCipher version 3.
On a related note there are also improvements to SQLCipher on prerelease that allow you to selectively query and set the salt (overriding the header) via a new PRAMGA cipher_salt.
you are right: the HMAC can’t help in such a situation. So it is irrelevant whether the HMAC of page 1 includes the salt bytes or not. Obviously it was decided to not include them long ago (although it would not have done any harm to include them), and changing the behaviour would break compatibility.
Being able to use one’s own raw key and salt is certainly a useful option. And I appreciate that you are adding the PRAGMA cipher_salt. Great.