Refactor entire codebase and rewrite documentation

This commit is contained in:
2025-10-10 18:06:34 +03:00
parent b4e9755c15
commit 8e471f2b9f
74 changed files with 3405 additions and 4149 deletions

View File

@@ -0,0 +1,61 @@
# 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 SQLCiphers key derivation.
- ``Connection/Key/rawKey(_:)`` — a 256-bit (`32`-byte) key supplied as `Data`.
```swift
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:)``.
```swift
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.
```swift
try connection.execute(raw: "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](https://www.zetetic.net/sqlcipher/documentation/)