SQLite加密需第三方扩展(如SQLCipher),原生System.Data.SQLite不支持;必须使用预编译的加密版DLL,连接字符串首次建库时带Password参数,密钥丢失则数据永久不可恢复。

SQLite加密需要第三方扩展,原生System.Data.SQLite不支持
SQLite官方不提供加密功能,C#里直接用 System.Data.SQLite(哪怕带“Encryption”后缀的NuGet包)默认也无法打开AES加密的数据库。真正起作用的是 sqlite3.dll 编译时是否启用了 SQLITE_HAS_CODEC 或使用了第三方加解密扩展(如SEE、SQLCipher)。常见错误是以为装了某个NuGet包就自动支持——实际运行时仍会报错:file is encrypted or is not a database。
实操建议:
- 用
Microsoft.Data.Sqlite无法加密,它底层不支持 codec 插件机制,只能读取未加密库 - 必须用
System.Data.SQLite+ 预编译的加密版 DLL(比如从 system.data.sqlite.org 下载带“x64/Win32/See”标识的二进制包) - 加密 DLL 必须和程序架构一致(x86/x64),且需在运行时通过
AppDomain.CurrentDomain.AssemblyResolve或SQLiteConnection.SetDefaultDirectory显式指定路径,否则加载失败
创建加密数据库:连接字符串里必须带 Password 参数
加密不是建库后追加的属性,而是在首次创建时由连接字符串触发的。如果先用无密码方式建库,再试图加密码,SQLite 会拒绝——它不支持 ALTER DATABASE ENCRYPTION 这类语句。
实操建议:
- 首次打开连接时,连接字符串必须含
Password=your_key,例如:"Data Source=test.db;Password=abc123;" - 密码长度影响加密强度:
SQLCipher要求至少 1 字节,但推荐 16 字节以上;SEE对密码长度更敏感,过短可能静默降级为弱加密 - 创建成功后,该文件即被 AES-256 加密,用普通 SQLite 工具(如DB Browser)打开会直接报错,必须输入相同密码
打开已加密数据库:Password 必须完全一致,且不能漏掉任何空格
密码比对是字节级的,"abc123" 和 "abc123 " 是两个完全不同的密钥,会导致 file is encrypted or is not a database。这不是权限问题,而是解密失败后 SQLite 无法识别文件头。
实操建议:
- 连接字符串中的
Password值建议硬编码或从受保护配置读取,避免用户输入时带不可见字符(如全角空格、BOM) - 若用变量拼接连接字符串,务必调用
.Trim(),尤其从ConfigurationManager或环境变量读取时 - 调试时可用
PRAGMA cipher_version;或PRAGMA cipher_provider;(需加密 DLL 支持)验证是否真进了加密流程,而不是被忽略
加密后性能下降明显,高频小事务要权衡
每次读写都涉及加解密运算,尤其在大量 INSERT/UPDATE 场景下,CPU 占用上升 20%~40%,单次操作延迟增加 0.1–0.5ms(取决于密钥长度和硬件)。这不是 bug,是加密的必然开销。
实操建议:
- 避免在循环里反复打开/关闭加密连接,复用
SQLiteConnection实例并配合事务批量提交 - 不要对日志表、缓存表这类高频写入但低敏感度数据启用加密,可拆分数据库:敏感数据进加密库,其他进普通库
- 若用 SQLCipher,可通过
PRAGMA cipher_page_size = 4096;提升吞吐,但需在首次建库前设置,之后不可改
最常被忽略的一点:加密密钥一旦丢失,数据彻底无法恢复。没有后门,没有重置选项,连 SQLite 官方也无能为力。


















