Scalable Equi-Join Queries over Encrypted Database 论文理解
XOR 过滤器的原理
Xor Filter 的实现原理(修正版)
1.Xor Filter 的核心思想
Xor Filter 是一种高效的空间节省型过滤器,用于判断一个元素是否存在于集合中。它通过多个哈希函数将元素映射到位数组中,并利用异或操作来减少空间占用和提高查找效率。
2.构建过程
构建 Xor Filter 的过程如下:
• 选择哈希函数
通常选择多个哈希函数(例如h1, h2, h3),将每个元素映射到位数组中的多个位置。这些哈希函数的输出范围通常是数组的索引范围。
• 计算指纹(Fingerprint)
对于每个元素x,通过多个哈希函数计算其指纹。指纹通常是多个哈希值的异或结果:
fingerprint(x) = h1(x) ⊕ h2(x) ⊕ h3(x)
• 存储指纹
将每个元素的指纹存储到位数组中。位数组的每个位置可以存储一个固定长度的指纹值(例如k位)。
• 分组与索引映射
为了提高查找效率,Xor Filter 通常将元素分组,并为每个组分配一个签名。签名是组内所有元素指纹的异或结果。同时,需要一个索引映射表来快速定位每个元素所属的组。
3.查找过程
查找一个元素是否存在于集合中的过程如下:
• 计算哈希值
使用相同的哈希函数计算待查找元素的指纹:
fingerprint(x) = h1(x) ⊕ h2(x) ⊕ h3(x)
• 定位组
通过索引映射表找到该元素所属的组。
• 验证签名
比较计算的指纹与存储的签名是否一致。如果一致,则元素可能存在;否则,元素一定不存在。
假设我们有以下键集合:{A, B, C, D},并且我们选择三个哈希函数:h1, h2, h3。
构建过程
• 计算指纹
假设:
• h1(A) = 101,h2(A) = 110,h3(A) = 011
• h1(B) = 011,h2(B) = 100,h3(B) = 111
• h1(C) = 111,h2(C) = 001,h3(C) = 101
• h1(D) = 010,h2(D) = 111,h3(D) = 000
计算指纹:
• fingerprint(A) = h1(A) ⊕ h2(A) ⊕ h3(A) = 101 ⊕ 110 ⊕ 011 = 000
• fingerprint(B) = h1(B) ⊕ h2(B) ⊕ h3(B) = 011 ⊕ 100 ⊕ 111 = 000
• fingerprint(C) = h1(C) ⊕ h2(C) ⊕ h3(C) = 111 ⊕ 001 ⊕ 101 = 011
• fingerprint(D) = h1(D) ⊕ h2(D) ⊕ h3(D) = 010 ⊕ 111 ⊕ 000 = 101
• 分组与存储签名
将元素分组并计算组签名:
• 第一组{A, B}的签名:fingerprint(A) ⊕ fingerprint(B) = 000 ⊕ 000 = 000
• 第二组{C, D}的签名:fingerprint(C) ⊕ fingerprint(D) = 011 ⊕ 101 = 110
存储签名数组:[000, 110]
• 索引映射表
记录每个元素所属的组:
• A -> 0,B -> 0
• C -> 1,D -> 1
查找过程
假设我们要查找键A是否存在:
• 计算指纹
计算fingerprint(A) = h1(A) ⊕ h2(A) ⊕ h3(A) = 000
• 定位组
根据索引映射表,A属于第 0 组。
• 验证签名
比较计算的指纹与存储的签名:
• 计算第 0 组的签名:fingerprint(A) ⊕ fingerprint(B) = 000 ⊕ 000 = 000
• 存储的签名为000,两者一致,因此A可能存在。
总结
- XOR 过滤器通过对元素的哈希值进行映射并使用异或操作更新位数组,实现了高效的空间利用和查询。
- 插入和查询都能在常数时间内完成,存储开销也比传统数据结构低。
- 该结构可能会产生假阳性,即查询时返回元素“可能存在”,即使它实际上不在集合中,但不会有假阴性,即不存在的元素不会错误地返回为“存在”。
在JXT+和JXT++中,XOR 过滤器的实现是通过特殊的加密和数据结构处理来减少存储开销并增强查询效率的。下面我将解释 XOR 过滤器 在这些方案中的实现过程,并阐述它是如何在加密数据库中与其它数据结构(如 TSet、XSet、CSet)协作的。
1. 在 JXT+ 和 JXT++ 中的实现
在 JXT+ 和 JXT++ 这两个方案中,XOR 过滤器的实现主要涉及到以下几个关键步骤:初始化、数据存储、查询和泄漏防护。
(1) 数据存储(EDBSetup)
在加密数据库的设置阶段,客户端需要将数据库中的表格和连接属性进行加密,并将这些加密后的数据存储到 XOR 过滤器中。具体步骤如下:
-
生成密钥和数据结构:
在EDBSetup函数中,客户端为每个表生成必要的密钥(如Kz、Kw、Kr等),并初始化以下数据结构:TSet:用于存储表中每个属性-值对的匹配记录标识符。XSet:用于存储所有记录的标识符和连接属性的值对。CSet:一个多映射,用于存储加密的记录标识符。- XOR 过滤器:用于存储连接属性对和记录标识符。
-
属性加密和存储:
- 每当客户端遍历数据库中的属性值对时,都会执行加密操作,使用伪随机函数(PRF)对属性和记录标识符进行加密。
- 对于每个属性值对,客户端将其通过多个哈希函数映射到 XOR 过滤器中的多个位置,并通过 XOR 操作更新这些位置的值。
(2) XOR 过滤器在查询中的作用(Search)
在查询阶段,XOR 过滤器的主要作用是快速查询和匹配连接属性。以下是查询过程的详细实现:
-
生成查询令牌:
客户端首先根据查询构造查询令牌。查询令牌中包含表格、属性值对以及连接属性。这些信息将作为输入传递给 XOR 过滤器。 -
查询过程:
- 客户端生成查询令牌并发送给服务器。服务器使用查询令牌来检索
TSet中相应的条目,并通过 XOR 过滤器快速查询记录标识符和连接属性的匹配情况。 - 通过 XOR 过滤器,服务器能够快速确定某个属性值对是否在查询中存在,如果存在则继续进行后续操作。如果某个属性值对不存在,查询过程将提前结束。
- 客户端生成查询令牌并发送给服务器。服务器使用查询令牌来检索
-
防止信息泄漏:
使用 XOR 过滤器可以隐藏连接属性的统计信息,避免泄露“子查询泄漏”。例如,当多个记录的属性值相同(即低熵属性时),传统的查询方法可能会暴露频率信息,而 XOR 过滤器通过将这些值存储在加密且混淆的位数组中,避免了泄漏。
(3) 优化存储和查询效率
通过使用 XOR 过滤器,JXT+ 和 JXT++ 方案在多个方面实现了存储和查询的优化:
-
存储优化:
在传统的加密查询方案中,存储每个连接属性及其值对的记录会占用大量空间,尤其是在数据库中记录很多时。XOR 过滤器通过将多个记录标识符和连接属性的值对映射到较小的位数组中,显著减少了存储空间的占用。 -
查询效率提升:
XOR 过滤器支持在常数时间内判断某个元素是否存在,大大提高了查询效率。在进行多表连接查询时,查询的过程需要检查大量的属性值对和连接标识符,XOR 过滤器通过快速的哈希查找和位数组操作,能够在短时间内完成大量的匹配检查。
(4) 防止泄漏
由于 XOR 过滤器的加密和位数组操作,服务器无法直接访问连接属性的具体值或频率,从而减少了数据泄漏的风险。在传统的加密数据库查询中,如果查询频繁涉及到某些特定属性,攻击者可能通过频率分析来推断出某些敏感信息,而 XOR 过滤器通过将数据加密并混淆,避免了这种泄漏。
2. XOR 过滤器的具体操作流程
以下是 XOR 过滤器在 JXT+ 和 JXT++ 中的具体操作流程:
-
初始化阶段:
- 生成密钥:客户端生成多个密钥(例如
Kz、Kw等)用于加密和哈希操作。 - 填充
TSet和XSet:客户端遍历数据库中的每个表格,使用密钥对属性值进行加密,并将结果存储在TSet和XSet中。同时,利用 XOR 过滤器对连接属性进行加密存储。 - 填充
CSet:加密的记录标识符存储在CSet中。
- 生成密钥:客户端生成多个密钥(例如
-
查询阶段:
- 客户端生成查询令牌,包括查询表格和连接属性。
- 通过
TSetGetTag和 XOR 过滤器,客户端将查询令牌发送到服务器。 - 服务器根据查询令牌从
TSet和XSet中获取加密记录,并使用 XOR 过滤器判断是否有匹配记录。 - 服务器返回查询结果,客户端通过解密操作获取最终结果。
3. 总结
XOR 过滤器在 JXT+ 和 JXT++ 中的实现,主要通过以下方式优化了存储和查询效率,同时增强了隐私保护:
- 优化存储:通过将连接属性和记录标识符映射到较小的位数组中,显著减少存储开销。
- 提高查询效率:通过哈希查找和位数组操作,快速判断元素是否存在,减少查询时间。
- 防止泄漏:通过加密和混淆,避免了频率信息和连接属性的泄漏。
通过这种方式,XOR 过滤器帮助 JXT+ 和 JXT++ 在加密数据库中实现高效、安全的多表连接查询,同时有效降低了存储和查询的成本。
4. JXT+ 示例实现
数据结构:
- TSet: 存储加密后的属性值对和记录标识符的映射。使用
HashMap<String, List<Integer>>来存储,每个加密属性值作为键,所有匹配的记录ID作为值的列表。 - XSet: 存储加密后的连接属性值对。使用
HashSet<String>来存储。 - CSet: 存储加密的记录标识符和连接属性值对。使用
HashMap<String, String>来存储连接属性和加密记录标识符的映射。
实现代码:
import java.util.*;
public class JXTPExample {
// 加密函数
public static String encrypt(String value) {
return value + "_encrypted"; // 简单的加密
}
public static void main(String[] args) {
// 示例数据
List<Map<String, String>> table1 = new ArrayList<>();
table1.add(Map.of("ID", "1", "Name", "Alice"));
table1.add(Map.of("ID", "2", "Name", "Bob"));
table1.add(Map.of("ID", "3", "Name", "Charlie"));
List<Map<String, String>> table2 = new ArrayList<>();
table2.add(Map.of("ID", "10", "Name", "Alice"));
table2.add(Map.of("ID", "11", "Name", "Bob"));
table2.add(Map.of("ID", "12", "Name", "David"));
// 初始化JXT+数据结构
Map<String, List<Integer>> TSet = new HashMap<>(); // 存储属性值对应的记录ID
Set<String> XSet = new HashSet<>(); // 存储连接属性
Map<String, List<String>> CSet = new HashMap<>(); // 存储加密的记录标识符
// 填充TSet、XSet和CSet
for (Map<String, String> record : table1) {
String name = record.get("Name");
String encryptedName = encrypt(name);
TSet.computeIfAbsent(encryptedName, k -> new ArrayList<>()).add(Integer.parseInt(record.get("ID")));
XSet.add(encryptedName); // 添加连接属性
CSet.computeIfAbsent(encryptedName, k -> new ArrayList<>()).add("encrypted_id_" + record.get("ID")); // 存储加密后的连接属性
}
// 对table2执行相同操作
for (Map<String, String> record : table2) {
String name = record.get("Name");
String encryptedName = encrypt(name);
TSet.computeIfAbsent(encryptedName, k -> new ArrayList<>()).add(Integer.parseInt(record.get("ID")));
XSet.add(encryptedName); // 添加连接属性
CSet.computeIfAbsent(encryptedName, k -> new ArrayList<>()).add("encrypted_id_" + record.get("ID")); // 存储加密后的连接属性
}
// 打印TSet, XSet, CSet的内容
System.out.println("TSet: " + TSet);
System.out.println("XSet: " + XSet);
System.out.println("CSet: " + CSet);
// 查询Name = Alice的记录
String queryName = "Alice";
String encryptedName = encrypt(queryName);
if (TSet.containsKey(encryptedName)) {
System.out.println("Matching records for " + queryName + ": " + TSet.get(encryptedName));
} else {
System.out.println("No matching records for " + queryName);
}
}
}
输出:
TSet: {Alice_encrypted=[1, 10], Bob_encrypted=[2, 11], Charlie_encrypted=[3], David_encrypted=[12]}
XSet: [Alice_encrypted, Bob_encrypted, Charlie_encrypted, David_encrypted]
CSet: {Alice_encrypted=[encrypted_id_1, encrypted_id_10], Bob_encrypted=[encrypted_id_2, encrypted_id_11], Charlie_encrypted=[encrypted_id_3], David_encrypted=[encrypted_id_12]}
Matching records for Alice: [1, 10]
数据结构说明:
- TSet:TSet 用于存储加密的属性值与原始记录 ID 的一对多映射,帮助快速定位记录。
- XSet:XSet 存储所有参与连接的加密连接属性,用于辅助执行多表连接查询。
- CSet:CSet 用于存储加密的连接属性与加密记录标识符之间的映射,它确保了查询过程中隐私保护,并且是一对多的映射。
JXT++ 是 JXT+ 的扩展,旨在处理 多表等值连接查询,并且通过加密技术保证隐私保护。在实现 JXT++ 时,主要是基于 加密查询 和 倒排索引 的技术框架。为了实现这一目标,JXT++ 结合了 加密数据结构(如 TSet、XSet、CSet)和 查询优化 技术,使得查询过程高效且安全。
JXT++ 实现思路与步骤总结
1. 加密数据结构的初始化
JXT++ 的核心思想是通过加密数据结构(TSet、XSet 和 CSet)来实现对多个表的安全查询。每个表的属性会经过加密处理,查询时再解密进行匹配。
- TSet:存储加密后的属性值与记录 ID 的一对多映射。
- XSet:存储加密后的连接属性值,表示在查询中需要进行连接的属性。
- CSet:存储加密的连接属性值与加密后的记录标识符之间的映射。
这些数据结构会存储在服务器端,以便处理加密查询。客户端会通过生成加密查询令牌来请求查询数据,服务器使用这些数据结构来判断连接条件,并返回加密后的查询结果。
2. 初始化表格数据和加密
每个表的属性会进行加密,生成相应的加密值(例如使用简单的加密函数 encrypt)。这些加密值将被存储在 TSet、XSet 和 CSet 中。
- 表格数据初始化:首先,准备多个表格数据,每个表格具有一个字段(如
Name),并用多个记录(每个记录都有一个 ID)。 - 加密属性值:对每个表的属性值(如
Name)进行加密处理,生成加密后的属性值。
3. 数据存储到 TSet、XSet 和 CSet
-
TSet:每个加密属性值(例如
"Alice_encrypted")与对应的多个记录 ID 列表(例如[1, 10, 100])进行关联。这是倒排索引,用于帮助快速查找某个属性值对应的所有记录。示例:
TSet.put("Alice_encrypted", Arrays.asList(1, 10, 100)); -
XSet:存储加密的连接属性值(例如
Alice_encrypted、Bob_encrypted等),这些值将用来参与多表连接查询。示例:
XSet.add("Alice_encrypted"); XSet.add("Bob_encrypted"); -
CSet:存储加密的连接属性值与加密记录 ID 的多对多映射。每个加密的属性值(如
"Alice_encrypted")映射到一个或多个加密的记录标识符(如"encrypted_id_1","encrypted_id_10")。示例:
CSet.put("Alice_encrypted", Arrays.asList("encrypted_id_1", "encrypted_id_10"));
4. 查询过程
查询的关键步骤是生成查询令牌并通过加密的数据结构进行匹配。以下是查询过程的核心步骤:
-
客户端生成查询令牌:客户端根据查询条件(如查询
Name = Alice)生成加密的查询令牌。查询令牌包含加密的查询属性值(如Alice_encrypted)以及其他查询条件。 -
服务器端查询处理:服务器收到查询令牌后:
- 根据查询令牌中的加密属性值,查找
TSet,找到所有匹配的记录 ID。 - 查找
XSet,确定查询涉及的连接属性值。 - 查找
CSet,找到与查询条件相关的加密记录标识符。
- 根据查询令牌中的加密属性值,查找
-
匹配结果返回:服务器将查询的匹配结果返回给客户端。返回的数据仍然是加密的,客户端在收到结果后通过解密操作得到最终的查询结果。
5. 多表连接查询
JXT++ 的一个关键特性是它支持多表连接查询,这需要通过 TSet、XSet 和 CSet 来协调工作:
- 多次查找:当进行多表连接查询时,服务器需要执行多次查找操作,基于加密的属性值查找
TSet中所有匹配的记录。 - 连接属性的匹配:对于多个表的连接,服务器需要根据
XSet中的连接属性值来判断哪些表的记录可以进行连接。CSet用于通过加密的连接属性值找到加密的记录标识符,并确定哪些记录需要连接。 - 优化查询效率:
JXT++使用这些数据结构来优化查询效率,避免暴力搜索所有记录,而是通过哈希映射快速定位匹配的记录。
6. 安全性与隐私保护
JXT++ 通过加密技术保证查询的隐私性,确保即使服务器端无法访问明文数据,客户端也能进行有效的查询。由于所有的数据(包括记录标识符和连接属性)都经过加密,即使攻击者能够访问加密的数据,也无法破解出实际的属性值和记录标识符。
总结
JXT++ 的实现思路可以总结为以下几个步骤:
- 数据加密与存储:通过加密函数对表格中的属性值和记录标识符进行加密,存储到
TSet、XSet和CSet中。 - 查询令牌生成:客户端根据查询条件生成加密查询令牌,发送给服务器。
- 服务器查询处理:服务器根据查询令牌,查找加密的属性值和记录标识符,利用
TSet、XSet和CSet进行匹配。 - 返回加密结果:服务器将加密的查询结果返回给客户端,客户端进行解密操作,获得查询结果。
- 多表连接支持:通过
TSet、XSet和CSet的多次查询和配合,支持多表连接查询。
JXT++ 提供了一种安全、高效的多表等值连接查询方法,利用加密技术保证了隐私保护,并通过合理的数据结构优化了查询效率。
全文总结
- JXT+ 主要是支持两个表的等值连接查询。通过加密数据结构(
TSet和XSet)进行查询,客户端可以快速地找到匹配的记录。 - JXT++ 是对
JXT+的扩展,支持多表的等值连接查询,并且能够高效地处理多个表之间的连接。通过多次查询和TSet、XSet数据结构的协作,客户端能够获得最终的查询结果。
3.本人第一篇blog,请多多包涵!

浙公网安备 33010602011771号