Database Encryption
Database Encryption
Mobile applications often use databases for structured data storage. Encrypting these databases is crucial for protecting sensitive information.
Cross-Platform SQLCipher Implementation:
// Android SQLCipher implementation
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SQLiteOpenHelper
class EncryptedDatabaseHelper(
context: Context,
private val password: CharArray
) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object {
private const val DATABASE_NAME = "encrypted.db"
private const val DATABASE_VERSION = 1
}
init {
SQLiteDatabase.loadLibs(context)
}
override fun onCreate(db: SQLiteDatabase) {
// Create tables with sensitive data
db.execSQL("""
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
email TEXT NOT NULL,
password_hash TEXT NOT NULL,
created_at INTEGER NOT NULL
)
""")
db.execSQL("""
CREATE TABLE secure_notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL,
encryption_iv BLOB NOT NULL,
created_at INTEGER NOT NULL,
modified_at INTEGER NOT NULL
)
""")
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// Handle database migrations securely
}
override fun getWritableDatabase(): SQLiteDatabase {
return super.getWritableDatabase(password)
}
override fun getReadableDatabase(): SQLiteDatabase {
return super.getReadableDatabase(password)
}
// Additional encryption for sensitive fields
fun insertSecureNote(title: String, content: String) {
val encryptedContent = encryptField(content)
val db = getWritableDatabase()
val values = ContentValues().apply {
put("title", title)
put("content", encryptedContent.cipherText)
put("encryption_iv", encryptedContent.iv)
put("created_at", System.currentTimeMillis())
put("modified_at", System.currentTimeMillis())
}
db.insert("secure_notes", null, values)
}
private fun encryptField(plainText: String): EncryptedData {
// Use AES encryption for individual fields
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val key = deriveKeyFromPassword(password)
cipher.init(Cipher.ENCRYPT_MODE, key)
val iv = cipher.iv
val cipherText = cipher.doFinal(plainText.toByteArray())
return EncryptedData(cipherText, iv)
}
}
// iOS Core Data encryption with SQLCipher
import SQLCipher
import CoreData
class EncryptedCoreDataStack {
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "DataModel")
let storeURL = container.persistentStoreDescriptions.first!.url!
let storeDescription = NSPersistentStoreDescription(url: storeURL)
// Configure SQLCipher encryption
storeDescription.setOption(
getEncryptionKey() as NSString,
forKey: "cipher_key"
)
storeDescription.setOption(
"cipher_page_size = 4096" as NSString,
forKey: NSSQLitePragmasOption
)
container.persistentStoreDescriptions = [storeDescription]
container.loadPersistentStores { _, error in
if let error = error {
fatalError("Failed to load encrypted store: \(error)")
}
}
return container
}()
private func getEncryptionKey() -> String {
// Derive key from Keychain-stored master key
guard let keyData = KeychainService.shared.getMasterKey() else {
// Generate new master key if not exists
let newKey = generateMasterKey()
KeychainService.shared.saveMasterKey(newKey)
return newKey
}
return String(data: keyData, encoding: .utf8) ?? ""
}
}