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

C++项目SQLCipher版本不匹配求助:无法适配SQLCipher 4加密库

问题:C++程序无法适配SQLCipher 4.6.0,仍调用3.4.1版本

系统环境

  • Ubuntu系统,已安装SQLCipher 4.6.0 Community版本

问题现象

  • C++程序运行时通过PRAGMA cipher_version检测到SQLCipher版本为3.4.1,而非系统安装的4.6.0
  • 程序可正常读取采用HMAC_SHA1加密的SQLCipher 3数据库,但无法打开采用HMAC_SHA512加密的SQLCipher 4数据库
  • 尝试自行编译SQLCipher 4.6.0和4.6.1源码后重新编译程序,问题依旧

程序源码

#define DSQLITE_HAS_CODEC = 1
#include <iostream>
#include <sqlcipher/sqlite3.h>
using namespace std;

void executeSQL(sqlite3* db, const char* sql) 
{
    char* errMsg = nullptr;
    int rc = sqlite3_exec(db, sql, nullptr, nullptr, &errMsg);
    
    cout << "SQL CMD: " << sql << endl;
    
    if (rc != SQLITE_OK) 
    {
        cerr << "SQL error: " << errMsg << endl;
        sqlite3_free(errMsg);
    } 
    else 
    {
        cout << "SQL command executed successfully." << endl;
    }
}

int main() {
    sqlite3 *db;
    sqlite3_stmt *stmt;
    int rc;
    
    rc = sqlite3_open("enc_Dev.db", &db);

    const char *sql_cipher_key = "PRAGMA key = '<64-byte key>'";
    executeSQL(db, sql_cipher_key);
    
    const char *sql_cipher_ver = "PRAGMA cipher_default_compatibility = 4;";
    executeSQL(db, sql_cipher_ver);

    const char *sql_cipher_page_size = "PRAGMA cipher_page_size = 4096;";
    executeSQL(db, sql_cipher_page_size);

    const char *sql_cipher_kdf_iter = "PRAGMA kdf_iter = 256000;";
    executeSQL(db, sql_cipher_kdf_iter);
    
    const char *sql_cipher_hmac_algo = "PRAGMA cipher_hmac_algorithm = HMAC_SHA512;";
    executeSQL(db, sql_cipher_hmac_algo);
    
    const char *sql_cipher_kdf_algo = "PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;";
    executeSQL(db, sql_cipher_kdf_algo);
    
    const char *sql_cipher_pt_hsize = "PRAGMA cipher_plaintext_header_size = 0;";
    executeSQL(db, sql_cipher_pt_hsize);

    if (sqlite3_exec(db, "SELECT count(*) FROM input_records;", NULL, NULL, NULL) != SQLITE_OK)
    {
        cerr << "Open encrypted database fail!" << endl;
    }

    const char *sql_ck = "PRAGMA cipher_version;";
    rc = sqlite3_prepare_v2(db, sql_ck, -1, &stmt, 0);
    int i = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW) 
    {
        const unsigned char *output = sqlite3_column_text(stmt, i);
        cout << "PRAGMA cipher_version;\nResult: " << output;
        i++;
    }
    cout <<endl;

    const char *sql_prvdck = "PRAGMA cipher_provider_version;";
    rc = sqlite3_prepare_v2(db, sql_prvdck, -1, &stmt, 0);
    i = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
        const unsigned char *output = sqlite3_column_text(stmt, i);
        cout << "PRAGMA cipher_provider_version;\nResult: " << output;
        i++;
    }
    cout <<endl;

    sqlite3_finalize(stmt);
    sqlite3_close(db);

    return 0;
}

程序运行输出

SQL CMD: PRAGMA key = '<64-byte key>';
SQL command executed successfully.
SQL CMD: PRAGMA cipher_default_compatibility = 4;
SQL command executed successfully.
SQL CMD: PRAGMA cipher_page_size = 4096;
SQL command executed successfully.
SQL CMD: PRAGMA kdf_iter = 256000;
SQL command executed successfully.
SQL CMD: PRAGMA cipher_hmac_algorithm = HMAC_SHA512;
SQL command executed successfully.
SQL CMD: PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;
SQL command executed successfully.
SQL CMD: PRAGMA cipher_plaintext_header_size = 0;
SQL command executed successfully.
Open encrypted database fail!
PRAGMA cipher_version;
Result: 3.4.1
PRAGMA cipher_provider_version;
Result: OpenSSL 3.0.0 7 sep 2021

系统已安装SQLCipher版本

SQLite version 3.45.3 2024-04-15 13:34:05 (SQLCipher 4.6.0 community)
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>

解决方案

1. 确保编译时链接正确的SQLCipher 4.6.0库

程序编译时可能默认链接了系统中旧版的SQLCipher库,需明确指定新版库的路径:

  • 编译命令示例(假设新版库安装在/usr/local):
g++ -o sqlcipher_test sqlcipher_test.cpp -I/usr/local/include/sqlcipher -L/usr/local/lib -lsqlcipher -lcrypto
  • 检查系统可用库:执行ldconfig -p | grep sqlcipher,确认4.6.0的库路径优先级高于旧版本。若旧版库在/usr/lib,可通过设置LD_LIBRARY_PATH=/usr/local/lib让程序优先加载新版库。

2. 修正宏定义错误

代码中#define DSQLITE_HAS_CODEC = 1是错误的,正确写法为:

#define SQLITE_HAS_CODEC 1

错误的宏定义会导致程序无法启用SQLCipher的加密模块,甚至链接到无加密的原生SQLite库。

3. 调整PRAGMA设置顺序

必须先设置加密参数,再设置密钥。当前代码先设置密钥的逻辑错误,因为密钥生成依赖于KDF算法、迭代次数等参数,正确顺序如下:

rc = sqlite3_open("enc_Dev.db", &db);

// 先设置兼容性及加密参数
const char *sql_cipher_ver = "PRAGMA cipher_default_compatibility = 4;";
executeSQL(db, sql_cipher_ver);

const char *sql_cipher_page_size = "PRAGMA cipher_page_size = 4096;";
executeSQL(db, sql_cipher_page_size);

const char *sql_cipher_kdf_iter = "PRAGMA kdf_iter = 256000;";
executeSQL(db, sql_cipher_kdf_iter);

const char *sql_cipher_hmac_algo = "PRAGMA cipher_hmac_algorithm = HMAC_SHA512;";
executeSQL(db, sql_cipher_hmac_algo);

const char *sql_cipher_kdf_algo = "PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512;";
executeSQL(db, sql_cipher_kdf_algo);

const char *sql_cipher_pt_hsize = "PRAGMA cipher_plaintext_header_size = 0;";
executeSQL(db, sql_cipher_pt_hsize);

// 最后设置密钥
const char *sql_cipher_key = "PRAGMA key = '<64-byte key>'";
executeSQL(db, sql_cipher_key);

4. 验证修复效果

编译程序后运行,检查PRAGMA cipher_version输出是否为4.6.0,再尝试执行数据库查询,确认是否能正常打开SQLCipher 4数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:09:52