You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用rusqlite连接SEE加密SQLite数据库?含静态链接方案

问题描述

持有SQLite Encryption Extensions(SEE),尝试在Rust程序中通过rusqlite操作加密SQLite数据库,但在Linux工作站及Docker生产环境均无法正常工作。程序可成功构建,但执行查询时返回file is not a database错误。

测试代码如下:

main.rs

use rusqlite::{Connection, Result};

fn main() {
    let cn = Connection::open("test.db").unwrap();
    cn.pragma_update(None, "key", "aes256:mysupersecretkey").unwrap();

    // 执行任何查询都会返回“file is not a database”错误。
    // ...
}

Cargo.toml

[package]
name = "sqlite_encryption"
version = "0.1.0"
edition = "2021"

[dependencies]
rusqlite = "0.30.0"

自定义构建脚本(用于指定库和头文件路径):

#!/bin/bash

# Contains libsqlite3.so
export SQLITE3_LIB_DIR=pathto/sqlitelibs
export SQLITE3_INCLUDE_DIR=pathto/see-sources

cargo run

需求:不使用rusqlite的bundled选项,自行提供带SEE的SQLite(而非SQLCipher),需解决连接问题,或提供静态链接自定义SQLite的示例。


解决方案

1. 确保SQLite SEE编译正确

首先要确认编译的SQLite库已正确集成SEE扩展,编译时需启用加密相关宏:

  • 编译静态库示例:
# 进入see-sources目录
cd pathto/see-sources
# 编译目标文件,启用SEE
gcc -c sqlite3.c -o sqlite3.o -DSQLITE_HAS_CODEC -fPIC
# 生成静态库
ar rcs libsqlite3.a sqlite3.o
# 复制静态库到指定目录(比如pathto/sqlitelibs)
cp libsqlite3.a pathto/sqlitelibs/
  • 编译动态库示例:
gcc -shared -fPIC sqlite3.o -o libsqlite3.so -DSQLITE_HAS_CODEC
cp libsqlite3.so pathto/sqlitelibs/

2. 调整rusqlite依赖配置

修改Cargo.toml,禁用rusqlite默认的bundled特性,避免自动拉取标准SQLite:

[package]
name = "sqlite_encryption"
version = "0.1.0"
edition = "2021"

[dependencies]
rusqlite = { version = "0.30.0", default-features = false }

3. 修正密钥设置逻辑

file is not a database错误通常是因为打开加密数据库时未及时提供密钥,导致SQLite无法识别文件格式。需在打开数据库时就传入密钥,或打开后立即执行密钥设置并验证:

方法1:打开时通过pragma指定密钥

use rusqlite::{Connection, OpenFlags, Result};

fn main() -> Result<()> {
    // 打开数据库时指定密钥
    let mut conn = Connection::open_with_flags_and_pragma(
        "test.db",
        OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_CREATE,
        &[("key", "aes256:mysupersecretkey")],
    )?;

    // 测试查询
    let count: i32 = conn.query_row("SELECT 1", [], |row| row.get(0))?;
    println!("Query result: {}", count);

    Ok(())
}

方法2:打开后立即设置密钥(适用于已加密数据库)

use rusqlite::{Connection, Result};

fn main() -> Result<()> {
    let conn = Connection::open("test.db")?;
    // 立即设置密钥
    conn.pragma_update(None, "key", "aes256:mysupersecretkey")?;
    
    // 验证连接有效性
    let _: i32 = conn.query_row("SELECT 1", [], |row| row.get(0))?;

    Ok(())
}

4. 静态链接自定义SQLite的示例

如果需要静态链接你编译的带SEE的SQLite库,可通过build.rs实现:

新建build.rs文件

use std::env;
use std::path::Path;

fn main() {
    // 指定头文件目录
    let include_dir = env::var("SQLITE3_INCLUDE_DIR").unwrap_or_else(|_| "./see-sources".to_string());
    // 指定库文件目录
    let lib_dir = env::var("SQLITE3_LIB_DIR").unwrap_or_else(|_| "./sqlitelibs".to_string());

    // 告诉rustc头文件路径
    println!("cargo:include={}", include_dir);
    // 告诉rustc库路径
    println!("cargo:rustc-link-search=native={}", lib_dir);
    // 静态链接libsqlite3.a
    println!("cargo:rustc-link-lib=static=sqlite3");
    // 若依赖系统库(如dl),需额外链接
    println!("cargo:rustc-link-lib=dylib=dl");
}

调整构建脚本

确保环境变量指向正确路径:

#!/bin/bash

export SQLITE3_LIB_DIR=pathto/sqlitelibs
export SQLITE3_INCLUDE_DIR=pathto/see-sources

cargo run

内容的提问来源于stack exchange,提问作者CTaylor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:05:54