opaquedb/opaquedb
GitHub: opaquedb/opaquedb
基于全同态加密的抗量子分布式隐私数据库,支持在不泄露查询内容的前提下对加密数据执行 SQL 等值查询。
Stars: 1 | Forks: 0
## 它是什么
OpaqueDB 处理针对数据的 SQL 查询,但不会知道您查询了什么。客户端使用自己的密钥对其要搜索的值进行加密。服务器在加密数据上评估匹配,并返回一个加密结果,只有客户端才能解密。操作员运行查询,但永远看不到查询值或密钥。
这是一个基于 Microsoft SEAL 和 BFV 方案构建的计算型私有信息检索(PIR)系统。其隐私保证非常明确:
- 隐私依赖于 Ring-LWE,这是一种目前没有已知量子攻击的格假设。
- 它可以抵御半诚实操作员。服务器之间没有非串谋假设,因此整个集群是一个单一的信任域。
- 目前系统是 QueryPrivate(查询隐私)的:操作员永远无法得知查询值。DataPrivate(数据隐私)模式(即操作员也永远无法得知存储的数据)将在后续版本中发布。
部署单元是一个由相同节点组成的分片集群。分片将 PIR 所需的线性扫描分散到多台机器上执行。
有关其适用场景,从私有凭证检查到机密查询,请参阅文档网站上的[用例](https://docs.opaquedb.io/use-cases/)。
### 匹配的工作原理
匹配键被二值展开为每条记录 `key_bits` 个 SIMD 插槽,许多记录被打包到一个密文的插槽中。对于每次查询,服务器在整个批次中并行计算:
1. `diff = query - key`,然后 `sq = diff * diff`,得到 `(q-k)^2`,在位匹配时为 0,不同时为 1;
2. `eq = 1 - sq`,即按位 XNOR,然后通过深度为 `log2(key_bits)` 的旋转乘树对每条记录的所有位进行 AND 操作,留下每条记录的相等指示符;
3. 明文掩码检索:将指示符与打包的 payload 相乘并求和,因此只有匹配记录的 payload 会被保留,外加一个加密的存在计数,这样无匹配的查询将返回空结果。
无论该批次包含多少条记录,此操作每批次仅需 `1 + log2(key_bits)` 次密文与密文相乘(这是 FHE 的主要开销),因此昂贵的乘法开销会被分摊到数千行数据上。参数是通过与 `examples/crypto_bench` 对比测量得出的:默认采用 `poly_modulus_degree` 16384(这是在噪声预算中容纳乘法深度所必需的)、349 位系数模数以及 `key_bits` 16(均可配置)。查询以单个密文的形式进行传输。
辅助 `INDEX` 列重用了这个完全相同的 pipeline。每个可搜索列的键在磁盘上的一条记录中并排打包,服务器提取出查询所指定的列,因此对索引的匹配与单键评估完全相同,没有额外的加密乘法开销。由于数据是按主键进行分片的,索引查询只需扇出到每个分片并对部分结果求和,这与键查询的路径相同。
## 快速开始
构建二进制文件(参见[构建](#building)),然后声明表、加载 CSV、启动服务并运行私有查询。
使用 `CREATE TABLE` 声明 schema。只能有一列作为主 `KEY`(它是可搜索的,并对数据进行分片)。任何列也可以标记为 `INDEX` 使其也可搜索;其余的是有类型的 payload 列,它们会被返回但不参与匹配:
```
-- weather.sql
CREATE TABLE weather (
id INT KEY,
city TEXT INDEX,
country TEXT INDEX,
temperature INT,
humidity INT,
conditions TEXT INDEX
);
```
查询会根据其 `WHERE` 指定的列进行匹配,因此可以通过 `id`、`city`、`country` 或 `conditions` 查找此表。`KEY` 或 `INDEX` 列必须是 `INT` 或 `TEXT`(不能是 `REAL`)。`INDEX` 列既作为搜索键又作为 payload 存储,因此它也会被返回;`KEY` 列是唯一的例外,它参与匹配但不返回。
CSV 的表头指定了列名:
```
id,city,country,temperature,humidity,conditions
1,Amsterdam,NL,18,72,Cloudy
2,Tokyo,JP,27,61,Clear
```
加载它,启动一个节点,并按键查询。示例文件位于 `examples/` 中:
加载示例数据并启动节点(本地不安全开发模式):
```
opaquedb run --set auth.mode=none --set auth.enable_insecure=true &
opaquedb load --schema examples/weather.sql --csv examples/weather.csv
```
然后打开交互式 shell,通过任何可搜索的列(主 `KEY` 或任何 `INDEX`)运行私有查询:
```
$ opaquedb repl --schema examples/weather.sql
OpaqueDB shell. \help for commands, \quit to exit.
opaquedb(default)> SELECT city, temperature, conditions FROM weather WHERE id = 1
city=Amsterdam temperature=18 conditions=Cloudy
opaquedb(default)> SELECT city, temperature FROM weather WHERE country = "JP"
city=Tokyo temperature=27
opaquedb(default)> SELECT city, country FROM weather WHERE conditions = "Clear" LIMIT 5
city=Tokyo country=JP
city=Santiago country=CL
opaquedb(default)> SELECT country FROM weather WHERE city = "Atlantis"
(no rows)
opaquedb(default)> \quit
```
无论您匹配哪一列,查询值都会被加密;在辅助 `INDEX` 上进行匹配,不会向操作员泄露更多信息,其加密往返过程也与在键上匹配完全相同。
一次性查询的工作方式相同,并会打印出解码后的行:
```
$ opaquedb query 'SELECT country, temperature, conditions FROM weather WHERE city = "Amsterdam"' \
--schema examples/weather.sql
country=NL temperature=18 conditions=Cloudy
```
`"Amsterdam"` 在离开客户端之前就已加密。节点在加密状态下扫描每一行,并仅返回加密后的匹配项。
### 多重匹配:LIMIT 和 OFFSET
一个可搜索的值可以匹配多行。默认值为 `LIMIT 1`,因此单纯的查询只会返回一行:
```
$ opaquedb query 'SELECT city, country, temperature FROM weather WHERE conditions = "Sunny"' \
--schema examples/weather.sql
city=Nairobi country=KE temperature=24
```
添加 `LIMIT n` 可获取更多行。有两个城市的 `conditions = "Sunny"`,它们会在一次查询中一并返回:
```
$ opaquedb query 'SELECT city, country, temperature FROM weather WHERE conditions = "Sunny" LIMIT 5' \
--schema examples/weather.sql
city=Nairobi country=KE temperature=24
city=Cairo country=EG temperature=33
```
`OFFSET m` 可对匹配结果进行分页;行在多次查询中以稳定的顺序返回,因此 `LIMIT 1 OFFSET 1` 会返回第二个匹配项:
```
$ opaquedb query 'SELECT city, country FROM weather WHERE conditions = "Sunny" LIMIT 1 OFFSET 1' \
--schema examples/weather.sql
city=Cairo country=EG
```
`LIMIT`/`OFFSET` 是公开的(它们不是机密,因此保留在明文模板中)并在客户端上执行。在底层,服务器将匹配项划分为 `crypto.result_buckets` 个存储桶(默认为 16),并将每个存储桶打包到一个结果中,因此 `LIMIT` 计算的是行数而不是存储桶插槽,且加密结果的大小不会随着 limit 的增加而增长。因此,单个值可以在一次往返中返回最多 `result_buckets` 行;增加 `result_buckets` 可获取更多结果。
## 它不是什么
- 目前还不是一个完整的 SQL 引擎。当前评估的查询为
`SELECT FROM WHERE