sqlcipher与Microsoft.Data.Sqlite.Core踩坑
sqlcipher可视化工具
SQLiteStudio 3.2.1
DB Browser for SQLite 3.12.0
都是Github上的开源项目
需要非常注意的一点是 sqlcipher数据库文件也是有版本区分的。
因为不同的版本有不同的默认缺省设置,缺省设置不对也打不开sqlcipher的数据文件。
可以通过
PRAGMA cipher_compatibility = 3;
启用sqlcipher3默认配置,可选的值有1,2,3,4
SQLiteStudio
SQLiteStudio 3.2.1 只支持 sqlcipher 3版本的数据库文件
DB Browser for SQLite
DB Browser for SQLite 3.12.0同时支持 sqlcipher3和sqlcipher4版本的文件
ADO.NET的使用
-
sqlcipher和sqlite是兼容的,没有密码的sqlcipher数据库就是sqlite数据库。
-
sqlite的一般方式是安装 SQLitePCLRaw.bundle_e_sqlite + Microsoft.Data.Sqlite.Core
或者直接安装它们的二合一整合包 Microsoft.Data.Sqlite
同理sqlcipher则是使用 1.SQLitePCLRaw.bundle_e_sqlcipher + 2.Microsoft.Data.Sqlite.Core
安装上面两个包就已经有Microsoft.Data.Sqlite.SqliteConnection
可以用了,
所谓的ADO.NET就是所有的实现都继承System.Data
下面那一套接口,比如IDbConnection,IDbCommand,IDbTransaction
等等 -
如果想用EF框架,那就在1,2的基础上安装Microsoft.EntityFrameworkCore.Sqlite.Core,
-
如果想用Linq2db这种轻量型的框架,就在1,2的基础上安装linq2db, 注意设置
providerName = ProviderName.SQLiteMS
SqlCipher加密参数设置
zetetic sqlcipher-api
此处巨坑 使用Microsoft.Data.Sqlite.SqliteConnection
如果需要修改 sqlcipher 的加密参数,
不能在连接字符串中直接放置密码, 需要通过下面的代码进行操作(在Microsoft.Data.Sqlite.Core 5.0.0以及之后的版本修复了这个问题,可以直接在连接字符串中放置密码)
var filePath = "test.db";
var pwd = "password";
using (var db = new SqliteConnection($"DataSource=\"{filePath}\";"))
{
db.Open();
using (var command = db.CreateCommand())
{
// 默认是基于sqlcipher4 的缺省配置上进行修改
command.CommandText = $"PRAGMA key = '{pwd}';"
command.ExecuteNonQuery();
command.CommandText = "PRAGMA cipher_memory_security = OFF;";
command.ExecuteNonQuery();
command.CommandText = "PRAGMA kdf_iter = '1000';";
command.ExecuteNonQuery();
command.CommandText = "PRAGMA cipher_page_size = 8192;";
command.ExecuteNonQuery();
}
}
var filePath2 = "test.db";
using (var db2 = new SqliteConnection($"DataSource=\"{filePath2}\";"))
{
db2.Open();
using (var command = db2.CreateCommand())
{
// 指定再sqlcipher3 的缺省配置上进行修改
command.CommandText = $"PRAGMA key = '{pwd}';"
command.ExecuteNonQuery();
command.CommandText = "PRAGMA cipher_compatibility = 3;"
command.ExecuteNonQuery();
command.CommandText = "PRAGMA cipher_memory_security = OFF;";
command.ExecuteNonQuery();
command.CommandText = "PRAGMA cipher_page_size = 8192;";
command.ExecuteNonQuery();
}
}
其它库
也可以通过 nuget 包 sqlite-net-sqlcipher 使用 sqlcipher,可惜的是,此库没有继承 System.Data
中那套接口,没什么扩展性。使用方法:
var db = new SQLiteConnection(new SQLiteConnectionString(file, true, pwd, null, new Action( _=>
{
_.Execute("PRAGMA cipher_memory_security = OFF;";
_.Execute("PRAGMA kdf_iter = '1000';";
_.Execute("PRAGMA cipher_page_size = 8192;";
})));