2.6 KiB
Database Encryption
Secure SQLite databases with SQLCipher encryption using DataLiteCore.
DataLiteCore provides a clean API for applying and rotating SQLCipher encryption keys through the connection interface. You can use it to unlock existing encrypted databases or to initialize new ones securely before executing SQL statements.
Applying an Encryption Key
Use ConnectionProtocol/apply(_:name:) to unlock an encrypted database file or to initialize
encryption on a new one. Supported key formats include:
Connection/Key/passphrase(_:)— a textual passphrase processed by SQLCipher’s key derivation.Connection/Key/rawKey(_:)— a 256-bit (32-byte) key supplied asData.
let connection = try Connection(
location: .file(path: "/path/to/sqlite.db"),
options: [.readwrite, .create, .fullmutex]
)
try connection.apply(.passphrase("vault-password"), name: nil)
The first call on a new database establishes encryption. If the database already exists and is
encrypted, the same call unlocks it for the current session. Plaintext files cannot be encrypted in
place. Always call ConnectionProtocol/apply(_:name:) immediately after opening the connection
and before executing any statements to avoid SQLITE_NOTADB errors.
Rotating Keys
Use ConnectionProtocol/rekey(_:name:) to rewrite the database with a new key. The connection
must already be unlocked with the current key via ConnectionProtocol/apply(_:name:).
let newKey = Data((0..<32).map { _ in UInt8.random(in: 0...UInt8.max) })
try connection.rekey(.rawKey(newKey), name: nil)
Rekeying touches every page in the database and can take noticeable time on large files. Schedule
it during maintenance windows and be prepared for SQLITE_BUSY if other connections keep the file
locked. Adjust ConnectionProtocol/busyTimeout or coordinate access with application-level
locking.
Attached Databases
When attaching additional databases, pass the attachment alias through the name parameter.
Use nil or "main" for the primary database, "temp" for the temporary one, and the alias for
others.
try connection.execute(sql: "ATTACH DATABASE 'analytics.db' AS analytics")
try connection.apply(.passphrase("aux-password"), name: "analytics")
All databases attached to the same connection must follow a consistent encryption policy. If an attached database must remain unencrypted, attach it using a separate connection instead.
- SeeAlso:
ConnectionProtocol/apply(_:name:) - SeeAlso:
ConnectionProtocol/rekey(_:name:) - SeeAlso: SQLCipher Documentation