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) ?? ""
    }
}