SQLCipher文档(未完待续)

文章目录

  • 概要
    • 关于
    • SQLCipher设计
      • 安全性
      • 数据库加密和临时文件
      • 包装
    • SQLCipher API
      • 设置key
        • PRAGMA key——设置数据库密码或密钥
        • sqlite3_key()和sqlite3_key_v2()——设置数据库密码或密钥
      • 更改key
        • PRAGMA rekey——重新设置数据库密码或密钥
        • sqltie3_rekey()和sqltie3_rekey_v2()——重新设置数据库密码或密钥
      • 关键选项
        • PRAGMA cipher_plaintext_header_size——设置以明文形式保留的的文件头的字节数
        • PRAGMA cipher_salt——设置数据库盐值
        • PRAGMA kdf_iter——设置PBKDF2生成密钥的迭代数
        • PRAGMA cipher_kdf_algorithm——设置/输出密钥派生算法
      • 加密配置
        • PRAGMA cipher_use_hmac——开启/禁用对每页的HMAC检查
        • PRAGMA cipher_memory_security——开启/禁用内存擦写功能
        • PRAGMA cipher_add_random——设置外部熵值
      • 升级和兼容性
        • PRAGMA cipher_migrate——升级SQLCipher
        • ATTACH——使用特定的密钥attach一个新的数据库或者已经存在的数据库到主数据库。
        • sqlcipher_export()——可以将数据库内容复制到一个具有不同配置的attached的数据库。
        • PRAGMA cipher_compatibility——强制SQLCipher使用某主版本号对应的默认设置。
      • 性能
        • PRAGMA cipher_page_size——更改页大小
        • PRAGMA cipher_profile——调试性能问题时,记录查询的执行时间。
      • 工具
        • PRAGMA cipher_settings——输出当前设置
        • PRAGMA cipher_integrity_check——对每页做HMAC校验
        • PRAGMA cipher_hmac_algorithm——设置、输出使用的HMAC算法
        • PRAGMA cipher_provider——输出编译用的加密provider名字
        • PRAGMA cipher_provider_version——输出编译用的加密provider版本号
        • PRAGMA cipher_version——输出SQLCipher版本号
      • 默认值
        • PRAGMA cipher_default_kdf_iter——更改利用PBKDF2生成密钥的默认迭代数
        • PRAGMA cipher_default_settings——输出ATTACH数据库时的默认设置
        • PRAGMA cipher_default_compatibility——设置当前进程使用目标主版本号对应的默认设置
        • PRAGMA cipher_default_kdf_algorithm——设置/输出密钥派生默认算法
        • PRAGMA cipher_default_hmac_algorithm——设置/输出默认HMAC算法
        • PRAGMA cipher_default_plaintext_header_size——以明文形式保留的的文件头的默认字节数。
        • PRAGMA cipher_default_page_size——设置attach数据库时使用的非默认页面大小。
        • PRAGMA cipher_default_use_hmac——更改之后打开加密数据库时是否检查HMAC的默认行为。

概要

关于

SQLCipher是一个利用256bit AES加密SQLite文件的开源库。

SQLCipher设计

SQLCipher使用内部的SQLite Codec API来插入回调函数到Pager管理中,在写入数据库页到磁盘或者从磁盘读取中读取数据库页的过程中加密。SQLCipher加密有两个特点。

  • 透明。应用无需了解数据库安全方面的知识。应用只需使用SQL操作数据表,调用的是标准的SQLite API。SQLCipher库在后台静默着工作。
  • 即时。SQLCipher按需加、解密一个页,不会一次加密整个数据库。这意味着SQLCipher
    • 启动、关闭迅速;
    • 对于大数据库来说,性能良好;
    • 与SQLite索引联合工作。加密数据库取一条数据记录的花销只比非加密数据库增加了5%。

安全性

  1. 加密算法是CBC模式的256bit AES算法。
  2. 每一页独立加、解密。默认的页大小是4KB,可在运行时调整。
  3. 每一页有自己的随机 Initialization Vector。IV由随机数生成器(比如OpenSSL的RAND_bytes。)生成,存储在页的末尾。IV在每次写入时重新生成,这样对于相同的页后面写入时也不会重复使用IV。
  4. 每一页写入时都在页尾包含了密文的Message Authetication Code(HMAC-SHA512)和IV。从磁盘中读取页时会校验MAC,如果密文或者IV被篡改或损坏,SQLCipher会向上报告问题。
  5. 当使用密码时,SQLCipher使用PBKDF2-HMAC-SHA512产生密钥。每个数据库在文件的前16个字节会使用一个唯一的随机数初始化——盐值。盐值用来生成密钥,这样即使两个数据库是使用相同的密码创建的,他们的密钥也不相同。生成密钥的过程默认要经历256000次迭代。这个参数可以通过PRAGMA kdf_iter更改。
  6. 用于计算页的HMAC的密钥和加密数据库的密钥不同。它由后者、2次迭代的PBKDF2、盐值变化而来。
  7. 如果不希望使用密码,应用可以提供密钥。
  8. 加密后,数据库文件看上去是随机产生的数据。
  9. SQLCipher申请的数据尽可能锁住(利用mLock或者VirtualLock),在释放前会被擦除。
  10. SQLCipher没有自己实现算法。它使用了流行的加密库中的加密算法,比如OpenSSL、libcrypto、LibTomCrypt、CommonCrypto。具体使用哪个,应用自己决定。

数据库加密和临时文件

主数据库文件内的所有数据都会被加密,日志文件中的数据也会被加密。如果您禁用了数据库临时存储(配置时--enable-tempstore=yes,构建时定义了SQLITE_TEMP_STORE=2),以下几点需要考虑:

  • 回滚日志。回滚日志中的页和主数据库文件使用相同的key加密。回滚日志的文件头是没被加密的,未完待续。。。

包装

SQLCipher是SQLite的扩展,但是由于多种原因它不能做成SQLite的插件。SQLCipher修改了SQLite,独立于SQLite的源码,单独维护。在SQLite的特定版本后SQLCipher基线。SQLCipher对SQLite的核心代码尽可能的少做改动,避免SQLite合入侵入式修改时产生问题。

SQLCipher之所以这样做,基于以下几点原因:

  • 使能SQLite codec需要在编译时定义SQLITE_HAS_CODEC,标准的SQLite没有这个。
  • 即使SQLite有SQLITE_HAS_CODEC,SQLite也不会将codec作为插件。尽管SQLite提供了一个加载扩展的函数,它也不能扩展其他系统的内部函数(它主要是用来允许自定义用户函数的)。
  • SQLCipher不止调用了公共的SQLite API,也调用了一些SQLite的内部函数。有时这些内部API会变化,即使是低版本的SQLite也可能变化。这样的话,SQLCipher每一次合入都需要经过严密的检查、测试。SQLCipher的可移植性无法保证。SQLCipher也做不到只用公共的SQLite API(比如说,第一个关键步骤,注册codec回调函数到pager中去就调用了内部API)。
  • SQLCipher为了增加特殊的Pragma,修改了支持函数(比如PRAGMA cipher_*)。利用SQLite提供的加载扩展函数也做不到这一点。
  • SQLCipher的测试套依赖testfixture的测试API和内部检查(比如内存的引用计数)。
  • 即便能做到加载插件的方式,也不是所有的平台都支持动态链接库。比如iOS不支持。

SQLCipher API

SQLCipher是基于SQLite的,大多数API和SQLite3的C/C++接口相同。然而,SQLCipher也以PRAGMA、SQL语句、C函数的方式增加了一些安全相关的扩展。

设置key

PRAGMA key——设置数据库密码或密钥

创建一个新的加密数据库的过程叫做"keying"。在第一次操作数据库时才生成密钥(懒汉式)。这意味着在第一次操作数据库之前需要设置好密码或者密钥。一旦操作了数据库(例如SELECT, CREATE TABLE, UPDATE),需要读取或者写入页时,密钥应该已经生成完毕,随时可用。

示例一:密码加密

key可以是密码,然后利用PBKDF2密钥生成算法将密码转换成密钥。

sqlite> PRAGMA key = 'passphrase';

示例二:密钥加密(没有密钥加密的过程)

可以使用一个blob作为原始密钥。这种方法要求应用提供一个包含64字符的16进制序列,该序列会被转化成32B(256bit)的密钥。

sqlite> PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";

示例三:带盐值的密钥加密(没有密钥加密的过程)

可以使用一个blob作为原始密钥,同时可以自己指定盐值。通常盐值由SQLCipher自动生成,存储在数据库文件的前16字节中。这种方式要求应用提供一个包含96字符的16进制序列。前64个字符(32B)作为原始的密钥,剩下的32字符(16B)作为盐值。

PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648101010101010101010101010101010101'";

测试key

打开一个已经存在的数据库时,如果key不对的话,PRAGMA key语句不会立即报错。想要测试数据库是否能用这个key打开,可以做一些操作做实验。
最简单的方式就是查询sqlite_master表,这个操作会查询数据库的第一页数据并且会解析schema。

sqlite> PRAGMA key = 'passphrase';
sqlite> SELECT count(*) FROM sqlite_master; -- if this throws an error, the key was incorrect. If it succeeds and returns a numeric value, the key is correct;

用C代码实现

sqlite3_key(database, "test123", 7);
if (sqlite3_exec(database, "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
  // key is correct.
} else {
  // key is incorrect
}

要点

  • PRAGMA key应该是数据库的第一个操作。

sqlite3_key()和sqlite3_key_v2()——设置数据库密码或密钥

可以通过编码的方式设置密钥或者密码。实际上PRAGMA key正是通过调用sqlite3_key()实现的。sqlite3_key_v2()sqlite3_key()的区别在于,前者可以指定数据库名字,后者指定主数据库。

int sqlite3_key(
  sqlite3 *db,                   /* Database to be keyed */
  const void *pKey, int nKey     /* The key, and the length of the key in bytes */
);
int sqlite3_key_v2(
  sqlite3 *db,                   /* Database to be keyed */
  const char *zDbName,           /* Name of the database */
  const void *pKey, int nKey     /* The key */
);

更改key

PRAGMA rekey——重新设置数据库密码或密钥

想要更改一个加密数据库的密码或者密钥,需要先用旧的key解密。只要数据库可写可读,PRAGMA rekey可以以新的方式加密数据库。

示例

sqlite> PRAGMA key = 'old passphrase';
sqlite> PRAGMA rekey = 'new passphrase';

要点

  • PRAGMA rekey一定要在PRAGMA key之后使用,数据库可读时就可调用。
  • PRAGMA rekey不能用来加密非加密数据库。它只能用于更改密码/密钥。使用sqlcipher_export()来加密明文数据库。

sqltie3_rekey()和sqltie3_rekey_v2()——重新设置数据库密码或密钥

可以通过编码的方式重新设置密钥或者密码。实际上PRAGMA rekey正是通过调用sqlite3_rekey()实现的。sqlite3_rekey_v2()sqlite3_rekey()的区别在于,前者可以指定数据库名字,后者指定主数据库。

int sqlite3_rekey(
  sqlite3 *db,                   /* Database to be rekeyed */
  const void *pKey, int nKey     /* The new key, and the length of the key in bytes */
);
int sqlite3_rekey_v2(
  sqlite3 *db,                   /* Database to be rekeyed */
  const char *zDbName,           /* Name of the database */
  const void *pKey, int nKey     /* The new key */
);

关键选项

PRAGMA cipher_plaintext_header_size——设置以明文形式保留的的文件头的字节数

可以设置不加密数据库文件头的块的大小,以便对数据库做一些校验。这个大小一定要大于0,一定是加密的数据块的倍数,并且小于第一个数据库页的可用空间。可以这样设置:

PRAGMA cipher_plaintext_header_size = 32;

这个功能主要用于iOS将要把WAL模式数据库文件存入shared container场景。这种场景下iOS需要判断数据库文件是否是WAL模式,如果是,iOS会给应用分配特殊权限,允许应用在后台时对数据库持有文件锁。如果数据库文件被整体加密,iOS也就无法判断文件类型,iOS在后台应用持有文件锁的时候会杀掉这个进程。

为了这个场景,iOS开发者应该告知SQLCipher保留一部分数据库文件头不加密。推荐的偏移量是32B——这不算太大,schema和数据等敏感信息不会暴露;也不算太小,足够iOS读取文件头的段信息,"SQLite Format 3\0"和数据库标识日志模式的读写版本号(0-19B),这足够iOS辨别文件,可以保留后台应用不被杀死。

注意:SQLCipher通常在数据库文件头的前16个字节保留数据库盐值,如果使能了这个命令,就不再有位置保留数据库盐值。因此,应用应该在外部保留、传入盐值。
PRAGMA cipher_salt命令可以用来设置、输出盐值。例如,第一次创建数据库时可以键入该命令来打印SQLCipher自己生成的盐值,然后保留这个盐值。然后下次再打开数据库时,可以键入该命令输入盐值,16进制的16字节数据。

PRAGMA key = 'test';
PRAGMA cipher_plaintext_header_size = 32;
PRAGMA cipher_salt = "x'01010101010101010101010101010101'";

盐值的另一个应用就是和密钥一起加密使用。应用可以提供96字符、16进制的BLOB,前64字符用作密钥,后32字符用作盐值。

PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648101010101010101010101010101010101'";

注意,PRAGMA cipher_plaintext_header_size一旦使用,每一次打开加密数据库都需要重新执行该命令。同样,每一次也都需要提供盐值。

PRAGMA cipher_salt——设置数据库盐值

取出、设置数据库盐值。32字符的16进制数字,会被转化成16B数据。

PRAGMA cipher_salt;
PRAGMA cipher_salt = "x'01010101010101010101010101010101'";

注意:正常场景下,不需要使用该命令,SQLCipher自己生成数据库盐值并把它存入数据库文件的前16字节中。这个命令一定是跟PRAGMA cipher_plaintext_header_size一起用的。

PRAGMA kdf_iter——设置PBKDF2生成密钥的迭代数

SQLCipher使用PBKDF2加强密钥,抵御暴力匹配、字典攻击。默认256000次迭代(512000次SHA512操作)。该命令可以重设置迭代数。

sqlite> PRAGMA key = 'blue valentines';
sqlite> PRAGMA kdf_iter = '10000';

要点

  • 该命令一定要在PRAGMA key命令之后、在其他操作之前。
  • 一旦使用了该命令,每一次打开加密数据库都需要重新执行该命令。
  • 如果使用密码加密,不建议减少迭代数。

PRAGMA cipher_kdf_algorithm——设置/输出密钥派生算法

输出、设置KDF算法。默认是PBKDF2_HMAC_SHA512,也支持PBKDF2HMAC_SHA256、PBKDF2_HMAC_SHA1 。

PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA256;

加密配置

PRAGMA cipher_use_hmac——开启/禁用对每页的HMAC检查

SQLCipher2.0增加了校验每页HMAC的特性。默认情况下,SQLCipher2.0的数据库检查HMAC,这一特性导致SQLCipher2.0无法打开SQLCipher1.1.X的数据库。因此,为了保证SQLCipher1.1.X的数据库能相后兼容,可以输入该命令禁用HMAC检查。

示例

sqlite> PRAGMA key = 'blue valentines';
sqlite> PRAGMA cipher_use_hmac = OFF;

要点

  • 该命令一定要在PRAGMA key命令之后、在其他操作之前。
  • 一旦使用了该命令,每一次打开加密数据库都需要重新执行该命令。

PRAGMA cipher_memory_security——开启/禁用内存擦写功能

为了性能考虑可以禁用内存擦写功能。默认开启。

PRAGMA cipher_memory_security = OFF;

PRAGMA cipher_add_random——设置外部熵值

可以设置外部熵值到crypto provider,需要是一个16进制序列的blob。

PRAGMA cipher_add_random = "x'deadbaad'";

升级和兼容性

PRAGMA cipher_migrate——升级SQLCipher

SQLCipher不同版本有不同的默认设置,因此现存的数据库经常需要从老版本升级到新版本。该命令就是为了方便升级。

> ./sqlcipher 2xdatabase.db
> PRAGMA key = 'YourKeyGoesHere';
> PRAGMA cipher_migrate;

如果该命令执行成功,会返回0,升级后的数据仍是打开状态,文件名不变。

该命令能让SQLCipher从1.x、2.x或者3.x直接升级到第四代SQLCipher。如果数据库使用的不是默认设置,需要使用sqlcipher_export手动升级。

这一命令代价昂贵,因为它试着使用每一个版本默认设置打开数据库,才能最终决定合适的设置。因此应用不该在每一次打开数据库时都执行该命令。推荐应用采用如下步骤打开、升级数据库:

  1. 正常打开数据库:执行PRAGMA key,然后尝试一次简单的查询。
  2. 如果第1步返回异常,关闭数据库。然后重新打开,执行PRAGMA cipher_migrate,尝试升级数据库。
  3. 检查第2步的返回值。
  4. 如果返回0,数据库升级成功,应用可以继续使用该数据库连接。
  5. 如果返回非0,意味着key不正确或者数据库使用的不是默认配置。如果数据库使用的不是默认配置,可以执行手动升级。

这一流程在数据库已经是版本最新时可以保证性能最好。如果key不正确,性能会有略微下降,因为尝试升级时可能多次派生key。但是这一流程在大多数场景下表现都不错。

如果经常发生key不对的情况,那么第2步的性能就太差了。应用可以通过选项或者其他方式来跟踪SQLCipher版本。

注意:当打开数据库连接运行PRAGMA cipher_migrate时,应该置位SQLITE_OPEN_CREATE标志位,因为升级过程会attach新的数据库。

ATTACH——使用特定的密钥attach一个新的数据库或者已经存在的数据库到主数据库。

在ATTACH语句可以加上特殊的key参数,这样可以使用指定的key来附加数据库。这在数据库间复制、转移数据时非常有用。

示例一:附加加密数据库到明文数据库

$ ./sqlcipher plaintext.db
sqlite> ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'testkey';

示例二:使用16进制key,附加加密数据库

$ ./sqlcipher plaintext.db
sqlite> ATTACH DATABASE 'test2.db' AS db2 KEY "x'10483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";

示例三:附加明文数据库到加密数据库

$ ./sqlcipher encrypted.db
sqlite> ATTACH DATABASE 'plaintext.db' AS plaintext KEY ''; -- empty key will disable encryption

要点:

  • 如果没有指定key参数,这样ATTACH时使用和主数据库相同的key和盐值。
  • 实际上,对于可能使用不同的盐值的已经存在的数据库,应用应该在ATTACH语句中提供密钥。

sqlcipher_export()——可以将数据库内容复制到一个具有不同配置的attached的数据库。

sqlcipher_export可以很方便的从主数据库中复制数据到附加数据库中,包括schema、触发器、虚表和数据表。它主要的功能是可以方便的从加密数据库转移到非加密数据库,或者从非加密数据库转移到加密数据库,或者从两个有着不同配置的加密数据库间转移数据。更多的信息可以看how to encrypt a plaintext database using SQLCipher。

使用sqlcipher_export非常简单,只需执行一个SELECT语句,传入想导出到的目标数据库的名字就可以。

额外有一个可选参数,可以设置导出的源数据库。如果不使用该参数,默认源数据库是主数据库。该参数也可以用来复制附加数据库到主数据库。

示例一:加密明文数据库

$ ./sqlcipher plaintext.db
sqlite> ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'testkey';
sqlite> SELECT sqlcipher_export('encrypted');
sqlite> DETACH DATABASE encrypted;

示例二:导出加密数据库到明文数据库

$ ./sqlcipher encrypted.db
sqlite> PRAGMA key = 'testkey';
sqlite> ATTACH DATABASE 'plaintext.db' AS plaintext KEY '';  -- empty key will disable encryption
sqlite> SELECT sqlcipher_export('plaintext');
sqlite> DETACH DATABASE plaintext;

示例三:从3.X转换到4.X

$ ./sqlcipher 1.1.x.db
sqlite> PRAGMA key = 'testkey';
sqlite> PRAGMA cipher_page_size = 1024;
sqlite> PRAGMA kdf_iter = 64000;
sqlite> PRAGMA cipher_hmac_algorithm = HMAC_SHA1;
sqlite> PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;
sqlite> ATTACH DATABASE 'sqlcipher-4.db' AS sqlcipher4 KEY 'testkey';
sqlite> SELECT sqlcipher_export('sqlcipher4');
sqlite> DETACH DATABASE sqlcipher4;

示例四:更改加密设置

$ ./sqlcipher encrypted.db
sqlite> PRAGMA key = 'testkey';
sqlite> ATTACH DATABASE 'newdb.db' AS newdb KEY 'newkey';
sqlite> PRAGMA newdb.cipher_page_size = 4096;
sqlite> PRAGMA newdb.cipher = 'aes-256-cfb';
sqlite> PRAGMA newdb.kdf_iter = 10000;
sqlite> SELECT sqlcipher_export('newdb');
sqlite> DETACH DATABASE newdb;

示例五:复制附加的明文数据库到新的空加密数据库

$ ./sqlcipher encrypted.db
sqlite> PRAGMA key = 'testkey';
sqlite> ATTACH DATABASE 'plain.db' AS plain KEY '';
sqlite> SELECT sqlcipher_export('main', 'plain');
sqlite> DETACH DATABASE plain;

要点:

  • sqlcipher_export命令不会修改目标数据库的user_version,不限制用户自己操作。

PRAGMA cipher_compatibility——强制SQLCipher使用某主版本号对应的默认设置。

调用该命令,参数可以设置为1、2、3、4,这样强制SQLCipher使用目标主版本号对应的默认设置。比如下面的命令会让SQLCipher把当前的数据库当成SQLCipher3.X数据库来处理。

PRAGMA cipher_compatibility = 3;

性能

PRAGMA cipher_page_size——更改页大小

SQLCipher2数据库增加该特性,可以更改数据库的页大小。默认的页大小是4KB,可以更改使用更大的页大小来提升数据库性能。最近的测试数据表明,在数据库页调整变大后,在操作大量的数据库页面时,数据库性能可以明显提升(5-30%)(例如:不带index的查询、一个事务内大量插入、大量的删除)。

想要调整页大小,需要在每次设置key后立刻执行该命令。页大小必须是512和65535间的2的指数。

示例

sqlite> PRAGMA KEY = 'testkey';
sqlite> PRAGMA cipher_page_size = 8192;

要点

  • 该命令一定要在PRAGMA key命令之后、在其他操作之前。
  • 一旦在创建数据库时使用了该命令,每一次打开加密数据库都需要重新执行该命令。

PRAGMA cipher_profile——调试性能问题时,记录查询的执行时间。

这一命令可以分析多个查询和它们各自的执行时间,毫秒级。可以有四个参数:stdout、stderr、要记录到的文件名、off。示例:

$ ./sqlcipher example.db
sqlite> PRAGMA cipher_profile='sqlcipher.log';
sqlite> CREATE TABLE t1(a,b);
sqlite> INSERT INTO t1(a,b) VALUES('one for the money', 'two for the show');
sqlite> PRAGMA cipher_profile=off;

工具

PRAGMA cipher_settings——输出当前设置

PRAGMA cipher_settings;

PRAGMA cipher_integrity_check——对每页做HMAC校验

对每页做HMAC校验,输出非法页、错误的报告。如果某页被标记为非法,那么大概率在SQLCipher将其写入到磁盘后该页被篡改过。该命令想要生效,需要提前使能过HMAC,而且输入的密码或者密钥必须正确。每一个错误输出一行,如果没有返回任何信息,可以认为数据库是完整的、一致的。

sqlite> pragma key = 'testkey';
sqlite> pragma cipher_integrity_check;
HMAC verification failed for page 4
HMAC verification failed for page 9
page 240 has an invalid size of 1 bytes

PRAGMA cipher_hmac_algorithm——设置、输出使用的HMAC算法

默认值是HMAC_SHA512,还可以设置成HMAC_SHA256、HMAC_SHA1 。

PRAGMA cipher_hmac_algorithm = HMAC_SHA256;

PRAGMA cipher_provider——输出编译用的加密provider名字

数据库一定是加密的,才能有输出信息。

PRAGMA cipher_provider_version——输出编译用的加密provider版本号

数据库一定是加密的,输出信息才有意义。

PRAGMA cipher_version——输出SQLCipher版本号

$ ./sqlcipher example.db
sqlite> PRAGMA cipher_version;
3.3.1

默认值

PRAGMA cipher_default_kdf_iter——更改利用PBKDF2生成密钥的默认迭代数

如果想更改密钥派生的默认迭代次数,又不想每次打开数据库都执行PRAGMA cipher_kdf_iter,可以执行该命令,该命令会针对所有的数据库生效。

示例

./sqlcipher sqlcipher2.0.db
sqlite> PRAGMA cipher_default_kdf_iter = 4000;
sqlite> PRAGMA key = 's3cr37';

要点

  • 该命令可在任何时间调用,打开数据库之前、之后均可。但是只对该命令执行后才打开的数据库生效。

PRAGMA cipher_default_settings——输出ATTACH数据库时的默认设置

PRAGMA cipher_default_settings;

PRAGMA cipher_default_compatibility——设置当前进程使用目标主版本号对应的默认设置

调用该命令,参数可以设置为1、2、3、4,这样对当前进程强制SQLCipher使用目标主版本号对应的默认设置(对该命令执行后才打开的数据库有效)。比如下面的命令会让SQLCipher之后打开的数据库当成SQLCipher2.X数据库来处理。

PRAGMA cipher_default_compatibility = 2;

PRAGMA cipher_default_kdf_algorithm——设置/输出密钥派生默认算法

输出、设置下次ATTACH数据库时使用的KDF算法。默认是PBKDF2_HMAC_SHA512,也支持PBKDF2HMAC_SHA256、PBKDF2_HMAC_SHA1 。

PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA256;

PRAGMA cipher_default_hmac_algorithm——设置/输出默认HMAC算法

输出、设置下次ATTACH数据库时使用的HMAC算法。默认值是HMAC_SHA512,还可以设置成HMAC_SHA256、HMAC_SHA1 。

PRAGMA cipher_default_hmac_algorithm = HMAC_SHA256;

PRAGMA cipher_default_plaintext_header_size——以明文形式保留的的文件头的默认字节数。

可以设置不加密数据库文件头的块的大小,以便对数据库做一些校验。这个大小一定要大于0,一定是加密的数据块的倍数,并且小于第一个数据库页的可用空间。和PRAGMA cipher_plaintext_header_size功能相同,作用域是之后的所有SQLCipher操作。

PRAGMA cipher_default_plaintext_header_size = 32;

PRAGMA cipher_default_page_size——设置attach数据库时使用的非默认页面大小。

想要ATTACH一个已经更改了页大小的数据库,一定要先执行该命令。该值是512和65536间的2的指数。

示例

$ ./sqlcipher foo.db
sqlite> PRAGMA key = 'foo';
sqlite> PRAGMA cipher_page_size = 8192;
sqlite> CREATE TABLE t1(a,b);
sqlite> INSERT INTO t1(a,b) values('one for the money', 'two for the show');
sqlite> .q

$ ./sqlcipher bar.db
sqlite> PRAGMA cipher_default_page_size = 8192;
sqlite> PRAGMA key = 'bar';
sqlite> ATTACH DATABASE 'foo.db' as foo KEY 'foo';
sqlite> SELECT count(*) FROM foo.t1;

PRAGMA cipher_default_use_hmac——更改之后打开加密数据库时是否检查HMAC的默认行为。

有时不可能每次都在打开数据库时执行PRAGMA cipher_use_hmac。例如,想要ATTACH一个1.1.x的数据库到主数据库。这种情况下可以执行该命令更改全局配置。

示例

./sqlcipher sqlcipher2.0.db
sqlite> PRAGMA key = 's3cr37'; -- opens using default setting, with HMAC on
sqlite> PRAGMA cipher_default_use_hmac = OFF;
sqlite> ATTACH DATABASE '1.1.x.db' AS remote key 's3cr37'; -- next open operation, the default for HMAC is off, and this database will be keyed with password 's3cr37'

要点

  • 该命令可在任何时间调用,打开数据库之前、之后均可。但是只对该命令执行后才打开的数据库生效。

你可能感兴趣的:(数据库,sqlite)