SQLCipher Database Key Material and Selection

By design, SQLCipher does not perform permanent storage of the database password and key material. This provides maximum flexibility, allowing an application to provide key material from any combination of sources (e.g. user-provided passphrase, random key wrapped by a hardware-backed keystore, external hardware tokens, server-issued credentials, etc.).

This cleanly separates the management of the key material from the implementation of the database encryption, allowing SQLCipher to address the widest possible set of requirements and use cases. It also means the integrating application is responsible for key management.

Application key management is a deep topic, with tradeoffs that depend on the application’s threat model, security requirements, and user experience constraints. Platform facilities for protecting key material have advanced significantly since SQLCipher was first released. Modern devices and operating systems now offer hardware-backed key storage that was not previously available. The selection of an appropriate approach is the responsibility of the integrating application developers, but some common approaches are described below.

Common Approaches

The security of key material is bounded by where and how it is held. Platform keystores vary in their behavior with respect to backups, cross-device sync, biometric enrollment changes, and rooted/jailbroken devices. Each application should carefully evaluate this behavior against its own security requirements. The following approaches are commonly used either alone or in combination with each other.

User-supplied passphrase. A passphrase entered by the user at unlock time keeps no portion of the key at rest on the device. SQLCipher converts the passphrase into the encryption key using PBKDF2-HMAC-SHA512 with a per-database random salt which protects against dictionary and brute-force attacks. However, key derivation is a deliberately slow operation, and security is still bounded by the entropy of what the user enters (i.e. short secrets like PINs, simple passwords, or unlock patterns offer less security).

Random key protected by a hardware-backed keystore. For applications that open the database without a passphrase prompt, a cryptographically random 256-bit key may be generated and provided to SQLCipher using the raw key syntax. In this model, the key itself is held in a platform “keystore”. Most keystores support access controls that require the user to authenticate with a fingerprint, face scan, secure PIN, or the device passcode before the stored key is released to the application. This allows an application to be unlocked behind a single system-managed prompt rather than an application-level passphrase. Specific facilities vary by platform:

  • Apple: Keychain, with access controls that can require device unlock, biometry, or the device passcode.
  • Android: Android Keystore, with options to require user authentication or invalidate keys on biometric enrollment changes.
  • Windows: Windows Hello, DPAPI, or TPM-backed key storage.
  • Linux: Secret Service API (gnome-keyring, KWallet), the kernel keyring, or TPM.
  • Server / embedded: HSM, cloud KMS, or managed environment secrets.

The strength of each approach depends on the configured access controls and the platform’s enforcement of them. For details on formatting random keys correctly, please see Technical Guidance: Using Random Values as SQLCipher Keys.

Remotely supplied key material. All or part of the key material can be retrieved from a remote service at unlock time, for example after the user authenticates to a server backend. This is conceptually similar to a user-supplied passphrase, except the key is held by the remote service rather than memorized by the user. This approach can be used to implement more advanced user management facilities such as account reset, escrow, multi-factor authentication, and access revocation. Because the key is not stored on the device, the application has no way to unlock the database when offline, and the overall security of the approach depends on the authentication flow, secure transport, server-side handling of the key material, and the server’s ability to verify device integrity and withhold the key from a compromised device.

Layered keys. Two or more of the above approaches can also be combined to increase security. For example, an application might encrypt the database with a randomly generated key protected by a keystore, combined or wrapped with a user-supplied passphrase or a server-issued secret. Layered security provides additional defense in depth, requiring attackers to potentially compromise multiple protections to gain access to a working key. However, this additional security comes at a cost of increased complexity and additional failure modes.

Reduced Protection

Some patterns offer meaningfully less protection than the approaches above. These are never appropriate for applications with strong confidentiality requirements. However, they might be intentionally used in conjunction with the more secure approaches described above, or for basic DRM, content distribution, or tamper-evident bundling. In those cases the goal is to raise the cost of casual access rather than to defend against a determined attacker. Whether the following are acceptable in a given application is a function of that application’s threat model and intended security properties:

  • Hardcoding the key in application source code, resources, or compiled binaries.
  • Deriving the key solely from non-secret values such as device identifiers, advertising IDs, MAC addresses, or an install UUID stored in plaintext.
  • Storing the key in plain text alongside the database, in general-purpose preference stores, environment variables, or configuration files without additional protection.

In each of these cases the keys can be recovered by a determined attacker, even if obfuscated, and used to decrypt the databases the application manages. As a result Zetetic does not recommend any of these patterns as the sole protection for sensitive data. Developers should carefully evaluate any use against their security requirements.

Finally, it is extremely important that applications prevent key material from being written to application logs, crash reports, analytics, or telemetry pipelines.

Hardening for Advanced Threat Models

The common approaches above are appropriate for the great majority of applications. If your threat model includes fully compromised devices, such as a rooted or jailbroken mobile device or a host under an attacker’s control, key material in memory can be intercepted. An attacker can hook the functions that supply the key, dump process memory, or repackage the application. No client-side technique provides absolute protection in this case. Where appropriate, the following measures add defense in depth:

  • Derive part of the key from a source that is not stored on the device, such as a user passphrase or a server-issued secret. This is the most effective measure, because it makes the database unusable without a secret the attacker does not already hold. See User-supplied passphrase and Remotely supplied key material above.
  • If you use a hardware-backed keystore, bind the key to user authentication so it cannot be read without the user being present.
  • If you retrieve key material from a server, verify device and application integrity on the server and refuse to release key material to a compromised device. Client-side root or jailbreak detection alone is not enough, because an attacker can remove the check from the application.
  • Close all database connections when the application goes to the background to reduce the time the key stays in memory.

Further Reading