Non ho provato personalmente, ma se usi SQlite come formato di file custom e non pensi di lavorare con grosse moli di dati tutte insieme (ovvero la tua casistica tipica è tanti file distinti di dimensioni accettabli, invece che un unico monolitico DB), allora una idea potrebbe essere combinare questo:
using(var source = new SQLiteConnection("Data Source=ActiveDb.db; Version=3;"))
using(var destination = new SQLiteConnection("Data Source=BackupDb.db; Version=3;"))
{
source.Open();
destination.Open();
source.BackupDatabase(destination, "main", "main", -1, null, 0);
}
con questo:
https://www.sqlite.org/inmemorydb.html
Il primo blocco è un semplice esempio di backup 'live' tra due database, una banale copia da A a B
Il secondo descrive la funzionalità già integrate di SQLite per poter usare database interamente in memoria, che possono anche essere applicati alla funzione di backup vista sopra
In sostanza quindi, l'idea sarebbe di tenere il file su disco criptato, decrittarlo al volo per copiarlo su un db in memoria con la funzione nativa di backup vista sopra, fare tutte le operazioni su questa seconda connessione, che viene vista a tutti gli effetti come un normale db, backup su disco alla fine, crittografia del nuovo file.
Chiaro che permangono sempre dei brevi momenti di vulnerabilità, il tempo in cui i file temporanei stanno per essere processati prima di essere cancellati, ma se serve solo un a forma di protezione "casual", e non a prova di bomba, può essere un idea
Per evitare problemi di perdite di dati in caso di crash del programma, puoi anche fare un salvataggio automatico ogni tot minuti, stile Office, sempre crittografato, visto che appunto la funzione di backup si può applicare anche a connessioni attive, senza dover chiudere/riaprire il db.
Come dicevo, ha un senso se l'overhead in memoria e in tempi di crittografia è entro limiti sensati, su db molto grandi non è l'ideale.