SQLCipher for Android, Raw Keys, and BLOB Key Content

Referring back to Technical Guidance: Using Random Values as SQLCipher Keys, you point out Raw Key syntax and indicate that a 32-byte key without zero byte values offers performance benefits. SQLiteDatabase does not appear to use Raw Key syntax directly, insofar as it does not use PRAGMA key. However, you do have the zero-byte-value check in place.

So… is a 32-byte key beneficial when using SQLCipher for Android? Or is it going to be treated the same as any other binary key length?

And, are the other key limitations described in that page relevant for SQLCipher for Android? For example, the second-to-last paragraph starts off “If it is not possible for an application to use the Raw Key syntax for some reason…”, and it is unclear if those restrictions apply to SQLCipher for Android, given that you are not using PRAGMA key directly.

Thanks!

Hi @commonsguy

SQLiteDatabase does not appear to use Raw Key syntax directly, insofar as it does not use PRAGMA key

Users are welcome to provide a raw key within SQLCipher for Android, however, they will need to format the input material manually. The raw key format usage is less common as it generally require additional key management both in terms of generation and storage. The raw key format works with either PRAGMA key, or via the C API of sqlite3_key directly.

An example of usage may be found in the test suite here where a database is rekeyed using a raw key. Of course a raw key may be used to initiate a SQLCipher database as well.

However, you do have the zero-byte-value check in place.

If you are referring to this, that was introduced to address an encoding issue (usage here) where the library allowed invalid encoding for the key material. When that situation presents, the library will rekey the database using modified UTF-8 encoding.

So… is a 32-byte key beneficial when using SQLCipher for Android? Or is it going to be treated the same as any other binary key length?

Yes, the performance benefit of providing a raw key to SQLCipher is that key derivation is not performed to compute an encryption key. The key derivation process is slow by design. Please note that while the key material for a raw key is 32 bytes, the total payload in bytes would be 67 bytes to address the SQLite BLOB format. Without adhering to the BLOB format, simply providing a 32 byte key would undergo key derivation. An example is below for reference:

byte[] rawKey = new byte[] {
  0x78, // x
  0x27, // '
  0x97, // a
  0x33, // 3
  0x30, // 0
  0x30, // 0
  0x39, // 9
  0x66, // f
  // ... 56 more ASCII hex values
  0x65, // e
  0x35, // 5
  0x27 // '
}

And, are the other key limitations described in that page relevant for SQLCipher for Android? For example, the second-to-last paragraph starts off “If it is not possible for an application to use the Raw Key syntax for some reason…”, and it is unclear if those restrictions apply to SQLCipher for Android, given that you are not using PRAGMA key directly.

This guidance is not specific to SQLCipher for Android, but rather SQLCipher as a whole.
It is important to note that a raw key should only be used when the key material is already of high quality (e.g. it is random, and should never be used with a passphrase). Thus it is not beneficial to use a raw key by default, only in specific cases where the key is “managed” externally (e.g. keystore, keychain, keyfile, external service) not via user input.
At this time there is no additional guidance specific to SQLCipher for Android which is not addressed via that document.

Ah, OK, that test case helps me see how this would work. I will see if I can apply that through the SupportFactory API. Thanks!

No problem, happy to help clarify!