1. 隐语实现PIR总体介绍
隐匿查询(Private Information Retrieval PIR)定义
- 按服务器数量分类
- 单服务器方案(Single Server)
- 多服务器方案(Multi-Server)
- 按查询类型分类
- Index PIR
- Keyword PIR
隐语目前支持:
Single Server Index PIR:SealPIR
Single Server Keyword:Labeled PSI
1.1 隐语PIR调用接口:pir_setup
reports = spu.pir_setup(server='bob',input_path='/path/B_PIR_DATA.csv',#服务端数据文件路径,建议绝对路径key_columns='id',#Key对应的列名label_columns=['register_date','age'],#Label对应的列名。多列,用逗号隔开oprf_key_path='/path/oprf_key.bin',#服务端ecc密钥文件,32B,二进制文件 setup_path='/path/setup_path',num_per_query=1,#每次查询的id数量 label_max_len=18#Label数据拼接后填充到固定的长度大小
)
1.2 隐语PIR调用接口:pir_query
#client--alice
alice_config={'input_path':'/path/A_PIR_ID.csv',#查询id对应的csv文件路径'key_columns':'id',#key对应的列名'output_path':'/path/sf_pir_out.csv',#PIR查询结果输出的文件路径
}
#server
bob_config = {oprf_key_path='/path/oprf_key.bin',#服务端ecc密钥文件,32B,二进制文件 setup_path='/path/setup_path',#预处理阶段结果输出路径
}
query_config={alice:alice_configbob:bob_config
}
reports=spu.pir_query(server='bob',config=query_config
)
2. Index PIR-SealPIR介绍
Index PIR 是一种隐私信息检索(Private Information Retrieval, PIR)技术,它允许用户从服务器检索特定数据项而不泄露他们所查询的内容。在基于索引的PIR中,用户可以通过索引值来秘密地获取数据库中的记录,而服务器无法知道用户实际请求的是哪个索引对应的记录。
SealPIR 则是一种具体实现隐私信息检索的协议,它基于同态加密(Homomorphic Encryption, HE)技术,特别是在SEAL(Simple Encrypted Arithmetic Library)框架下实现的一种高效PIR方案。SealPIR使得用户可以在不解密服务器数据库的情况下,对加密数据执行查询操作,并获得加密形式的查询结果,然后用户可以安全地解密得到所需的真实数据,整个过程保证了用户的查询隐私。
SealPIR结合了现代密码学的进步,尤其是同态加密技术的优势,提供了一种更为安全和高效的隐私保护机制,适用于那些对数据隐私有严格要求的场景,比如云存储环境下的数据查询服务等。随着同态加密技术的不断成熟,基于此类技术的PIR协议如SealPIR,在隐私保护和效率之间找到了更好的平衡点,从而推动了隐私计算领域的发展。
3. Keyword PIR-Labeled PSI介绍
Labeled PSI (Private Set Intersection with Labeling) 是Keyword PIR中的一种具体技术实现,主要用于解决两个或多方参与者的私人集合交集问题,但增加了关键词标签的功能。在Labeled PSI中,每个参与者不仅拥有一个元素集合,而且这些元素还带有标签(关键词)。当两个参与者希望找出他们的集合中共有的元素(及对应的标签)时,可以使用Labeled PSI协议来完成这一任务,且过程中不会暴露各自的非共有元素信息。
Labeled PSI通常基于密码学技术,例如基于多方计算(MPC)、同态加密(HE)、混淆电路(Garbled Circuits)或其他零知识证明(Zero-Knowledge Proofs)的方法来设计。其中,某些Labeled PSI方案可能会利用插值多项式或其他数学工具进行优化,以便更高效地处理大规模数据集上的关键词匹配查询。
例如,Labeled PSI可能的工作流程包括:
用户将关键词加密并构建查询对象。
数据持有者用类似的技术加密其数据库中的关键词。
双方通过交互协议计算出在各自加密数据中有交集的关键词,而不揭露任何一方的具体关键词列表或多余的交集信息。
4. 代码实践
4.1. 查询一个没有使用的端口
import socket
from contextlib import closing
from typing import castdef unused_tcp_port() -> int:"""return an unused port"""with closing(socket.socket(socket.AF_INET,socket.SOCK_STREAM)) as sock:sock.bind(("",0))sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)return cast(int,sock.getsockname()[1])
print(unused_tcp_port())
4.2. 初始化alice节点
import secretflow as sfcluster_conf = {'parties': {'alice': {'address': 'ip:8000',#对外使用的地址'listen_addr': '0.0.0.0:59181'#对内的},'bob': {'address': 'ip:8001',#对外使用的地址'listen_addr': '0.0.0.0:8001'#对内的},},'self_party': 'alice'
}
sf.shutdown()
sf.init(address='local', cluster_config=cluster_conf)
4.3. 初始化bob节点
import secretflow as sfcluster_conf = {'parties': {'alice': {'address': 'ip:8000',#对外使用的地址'listen_addr': '0.0.0.0:59181'#对内的},'bob': {'address': 'ip:8001',#对外使用的地址'listen_addr': '0.0.0.0:8001'#对内的},},'self_party': 'bob'
}
sf.shutdown()
sf.init(address='local', cluster_config=cluster_conf)
4.4. 初始化spu
import spu
import secretflow as sfspu_conf = {"nodes": [{"party": "alice","address": "alice:8001","listen_addr": "alice:8001",},{"party": "bob","address": "bob:8001","listen_addr": "bob:8001",},],"runtime_config": {"protocol": spu.spu_pb2.SEMI2K,"field": spu.spu_pb2.FM128,"sigmoid_mode": spu.spu_pb2.RuntimeConfig.SIGMOID_REAL,},
}
spu = sf.SPU(cluster_def=spu_conf,link_desc={"connect_retry_times":60,"connect_retry_interval_ms":1000})
4.5.RIP
alice做服务端,bob作为客户端。
进入alice的secretnote服务器端运行命令: openssl rand 32 > ~/alice_oprf_key
准备数据
# alice端
import pandas as pd
from pathlib import Path
alice_df = pd.DataFrame({"name":["alice","bob","carol","tony"],"age":[11,13,14,26]
})
alice_df.to_csv(f"{str(Path.home())}/alice_pir_input.csv",index=False)
# bob端
import pandas as pd
from pathlib import Path
bob_df = pd.DataFrame({"name":["tony","bob"],
})
bob_df.to_csv(f"{str(Path.home())}/bob_pir_query.csv",index=False)
import spu
spu.pir_setup(server="alice",input_path=f"{str(Path.home())}/alice_pir_input.csv",key_columns=["name"],label_columns=["age"],oprf_key_path=f"{str(Path.home())}/alice_oprf_key",setup_path=f"{str(Path.home())}/alice_setup",#中间结果存储路径num_per_query=1,label_max_len=20,bucket_size=1000000
)
spu.pir_query(server='alice',client='bob',server_setup_path=f"{str(Path.home())}/alice_setup",client_key_colums=["name"],client_input_path=f"{str(Path.home())}/bob_pir_query.csv",client_output_path=f"{str(Path.home())}/bob_pir_result.csv",
)