当前位置: 首页 > news >正文

【隐私计算】Paillier半同态加密算法

 一、何为同态加密(HE)?

HE是一种特殊的加密方法,它允许直接对加密数据执行计算,如加法和乘法,而计算过程不会泄露原文的任何信息。计算的结果仍然是加密的,拥有密钥的用户对处理过的密文数据进行解密后,得到的正好是处理后原文的结果。

即满足下面的性质的加密算法:

 从明文空间和密文空间的角度来看,密文空间具有特定的算符。明文空间的加法对应密文空间的 ⊕ ,明文空间的乘法对应密文空间的 ⊙ 。如下图:

根据支持的计算类型和支持程度,同态加密可以分为以下三种类型:

  • 半同态加密(Partially Homomorphic Encryption, PHE):只支持加法或乘法中的一种运算。其中,只支持加法运算的又叫加法同态加密(Additive Homomorphic Encryption, AHE);

  • 部分同态加密(Somewhat Homomorphic Encryption, SWHE):可同时支持加法和乘法运算,但支持的计算次数有限;

  • 全同态加密(Fully Homomorphic Encryption, FHE):支持任意次的加法和乘法运算,当前算法复杂度高,实际使用较少。

在同态加密概念被Rivest在1978年首次提出后,学术界出现了多个支持PHE的方案,如RSA、GM、Elgamal、Paillier。此后,SWHE方案也相继问世,如BGN。关于FHE如何实现,学术界在很长的时间都没有答案。直到2009年,Gentry使用理想格构造了第一个FHE方案,轰动了整个学术界,并引发了学者们对于FHE方案构造的研究热潮。此后相继涌现出多个优秀的FHE方案,包括BFV、BGV、CKKS等,以及多个优秀的开源算法库如SEAL、HELib等。

二、隐私计算与同态加密

隐私计算的应用场景非常广泛,除满足多方的通用计算(算数或布尔计算)功能外,还有如隐私集合求交(Private Set Intersection, PSI)、隐私保护机器学习、加密数据库查询、门限签名等等更加细分的应用。然而,在几种主要的通用计算技术路线中,每种方法各有各的效率/安全性缺陷。FHE在计算有限次乘法后需要较复杂的去除噪声的操作,经典的通用MPC协议通信开销较大,而TEE的安全性高度依赖于硬件厂商,无法提供密码学上严谨的安全性。在复杂的计算场景中,单独使用某种通用方法通常得不到一个可用的落地方案,这也激发了学者们研究对于特定场景的特定解法。一个可行的方案通常是根据具体场景来进行定制化的设计,通过组合、优化不同的技术组件来得到安全、高效的方案,精准满足该场景需求。

PHE登场:辅助多种隐私计算场景

由于通用安全计算方法的一些不足,以及在一些特定场景只需要使用一种HE运算(如加法)即可完成功能,PHE在隐私计算领域得到了大量使用,在多个开源库和大量学术顶会的方案中都有它的身影。PHE的高效、支持无限次加法或乘法的特点,使其成为隐私计算的重要基本组件,可辅助完成多种隐私计算功能:

1)隐私保护数据聚合

由于加法PHE可以在密文上直接执行加和操作,不泄露明文,在到多方协作的统计场景中,可完成安全的统计求和的功能。

  • 在联邦学习中,不同参与方训练出的模型参数可由一个第三方进行统一聚合。使用加法PHE,可以在明文数据不出域、且不泄露参数的情况下,完成对模型参数的更新,此方法已应用在实际应用(如FATE和多个顶会工作中(如SIGMOD、KDD、ATC);

  • 在在线广告投放的场景中,广告主(如商家)在广告平台(如媒体)投放在线广告,并希望计算广告点击的转化收益。然而,广告点击数据集和购买数据集分散在广告主和广告平台两方。使用PHE加密结合隐私集合求和(Private Intersection-Sum-with-Cardinality, PIS-C)协议可以在保护双方隐私数据的前提下,计算出广告的转化率。 该方案已被Google落地应用;

  • 在加密数据库SQL查询场景,在数据库不可信的情况下,可以通过部署协议和代理来保护请求者的查询隐私。其中,PHE可以用来完成安全数据求和和均值的查询。

2)乘法三元组生成

通用安全计算根据计算电路的不同可分为算数计算和布尔计算,对于算数计算来说,其中的难点是如何做乘法。而使用预生成的乘法三元组来辅助乘法运算的方法可以大大降低乘法的在线开销,是目前最为流行的方法。PHE是用于计算乘法三元组的重要工具,已在多个顶会方案和实际产品(如Sharemind)中得到应用,对于加速安全计算具有重要意义。

3)构造特定的隐私保护协议

在机器学习预测分类场景中,若拥有模型的一方不可信(如外部厂商),在数据方输入样本进行预测分类时,可能需要保护样本数据的隐私。PHE作为building block可以构造出隐私保护比较协议和argmax协议,并可以此进一步构造出隐私保护朴素贝叶斯分类器和超平面决策分类器。此外,用PHE还可构造出不经意选择(Oblivious Selection)协议,来支持隐私保护决策树分类器。

4)门限签名

传统签名方式要求签名时从存储介质(如磁盘)中拉取完整私钥到内存,存在泄露风险(如被木马、病毒窃取,侧信道攻击等)。 使用门限签名可以有效规避此类风险,让多方协作完成签名过程,并确保私钥没有在任何一方被恢复。特定的PHE算法可以用于实现门限签名,相关方案已在集团密钥管理系统落地。

5)同态秘密分享

同态秘密分享是一种前沿的安全计算技术,可以用来大幅降低安全计算的交互通信量。具有特定代数结构的PHE方案经过特殊设计,可以用来实现同态秘密分享,具有广阔的应用前景。

6)隐私集合求交

使用PHE结合多项式的方法可构造出PSI协议。

三、最著名的半同态加密方案:Paillier

Paillier是一个支持加法同态的公钥密码系统,由Paillier在1999年的欧密会(EUROCRYPT)上首次提出。此后,在PKC'01中提出了Paillier方案的简化版本,是当前Paillier方案的最优方案。在众多PHE方案中,Paillier方案由于效率较高、安全性证明完备的特点,在各大顶会和实际应用中被广泛使用,是隐私计算场景中最常用的PHE实例化方案之一。

其他的支持加法同态的密码系统还有DGK、OU和基于格密码的方案等。其中,DGK方案的密文空间相比Paillier更小,加解密效率更高,但由于算法的正确性和安全性在学术界没有得到广泛研究和验证,且实验表明算法的加解密部分存在缺陷,不推荐在工业界代码中使用。OU和基于格的加法同态计算效率更高,也是PHE不错的候选项。其中OU在方案中的使用频率相对较低,而基于格的方案密文大小较大,在一些特定场景有自身的优势。

四、Paillier原理

1.加法同态加密定义 在描述具体方案之前,我们先定义加法PHE。首先列举方案具有的所有算法。

  • KeyGen():密钥生成算法。用于产生加密数据的公钥PK(Public Key)和私钥SK(Secret Key),以及一些公开常数PP(Public Parameter);

  • Encrypt():加密算法。使用PK对用户数据Data进行加密,得到密文CT(Ciphertext);

  • Decrypt():解密算法。用于解密得到数据原文PT(Plaintext)。

HE除了加解密以外,还具有在密文上进行处理的能力,所以还应拥有“处理”算法。对于加法PHE,支持的算法有同态加以及同态标量乘(标量乘法可看作多次加法)。

  • Add():同态加算法。输入两个CT进行同态加运算。

  • ScalaMul():同态标量乘算法。输入一个CT和一个标量PT,计算CT的标量乘结果。

2.Paillier算法原理

密钥生成

加密

解密

同态加法

同态标量乘

加解密正确性

同态加法正确性

同态标量乘法正确性

注意,明文的标量乘法是加密域的指数运算。

安全性

Paillier方案满足加密方案的标准安全定义:语义安全,即在选择明文攻击下的密文的不可区分性(IND-CPA)。直观地说,就是密文不会泄露明文中的任意信息。方案安全性可以归约到判定性合数剩余假设(Decisional Composite Residuosity Assumption, DCRA),即给定一个合数n和整数z,判定z是否在n^2下是否是n次剩余是困难的。这个假设经过了几十年的充分研究,到目前为止还没有多项式时间的算法可以攻破,所以Paillier加密方案的安全性被认为相当可靠。

五、Python-Paillier算法演示

我们使用了 Python 实现的 paillier 算法来演示一些性质。你可以使用如下命令安装对应库

pip install phe

下面,我们使用 phe 演示 paillier 的同态加法和标量乘法的性质:

"""
Benchmark key generation, encryption and decryption.
"""import random
import resource
import time
import phe.paillier as paillierdef bench_encrypt(pubkey, nums):for num in nums:pubkey.encrypt(num)def bench_decrypt(prikey, nums):for num in nums:prikey.decrypt(num)def bench_add(nums1, nums2):for num1, num2 in zip(nums1, nums2):num1 + num2def bench_mul(nums1, nums2):for num1, num2 in zip(nums1, nums2):num1 * num2def time_method(method, *args):start = time.time()method(*args)return time.time() - startdef bench_time(test_size, key_size=128):print("=="*50)print('Paillier Benchmarks with key size of {} bits'.format(key_size))pubkey, prikey = paillier.generate_paillier_keypair(n_length=key_size)nums1 = [random.random() for _ in range(test_size)]nums2 = [random.random() for _ in range(test_size)]nums1_enc = [pubkey.encrypt(n) for n in nums1]nums2_enc = [pubkey.encrypt(n) for n in nums2]ones = [1.0 for _ in range(test_size)]times = [time_method(bench_encrypt, pubkey, nums1),time_method(bench_decrypt, prikey, nums1_enc),time_method(bench_add, nums1_enc, nums2),time_method(bench_add, nums1_enc, nums2_enc),time_method(bench_add, nums1_enc, ones),time_method(bench_mul, nums1_enc, nums2)]times = [t / test_size for t in times]ops = [int(1.0 / t) for t in times]print('operation: time in seconds (# operations per second)\n''encrypt: {:.6f} s ({} ops/s)\n''decrypt: {:.6f} s ({} ops/s)\n''add unencrypted and encrypted: {:.6f} s ({} ops/s)\n''add encrypted and encrypted: {:.6f} s ({} ops/s)\n''add encrypted and 1: {:.6f} s ({} ops/s)\n''multiply encrypted and unencrypted: {:.6f}  s ({} ops/s)'.format(times[0], ops[0], times[1], ops[1], times[2], ops[2],times[3], ops[3], times[4], ops[4], times[5], ops[5]))return timesdef bench_mem(test_size):r_init = resource.getrusage(resource.RUSAGE_SELF).ru_maxrsspubkey, prikey = paillier.generate_paillier_keypair()nums = []for i in range(test_size):if not i % 10000:# This is probably KB (i.e. 1000 bytes) when run on linuxr = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss - r_initprint('Memory usage for {:,} encrypted numbers = {:,} ({:.4f} per ''number)'.format(i, r, i and r / i))nums.append(pubkey.encrypt(random.random()))# bench_mem(1000000)  
# NOTE: this will take a long timetimes = []
key_sizes = [128, 256, 512, 1024, 2048, 4096]
for key_size in key_sizes:times.append(bench_time(1000, key_size))

Benchmarks

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • node前端开发基本设置
  • rust GUI框架Tauri入门——基于vanilla.js
  • 【C语言】联合体枚举的讲解
  • 02请求响应(简单参数)
  • Java学习Day42:骑龙救!(springMVC)
  • PostMan使用变量
  • 在mac中如何使python3作为默认版本
  • v-for循环中使用‘v-model‘ directives cannot update the iteration variable itself
  • JavaSE基础——第三章 运算符
  • 如何在webots中搭建一个履带机器人
  • 什么是外贸专用路由器?
  • 微信小程序----日期时间选择器(自定义时间精确到分秒)
  • 瑞芯微rv1126 Linux 系统,修改系统时区,包有效方法
  • 8.JMeter+Ant(基于工具的实现接口自动化,命令行方式)
  • 牛客背包问题练习 xinjun与阴阳师
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • codis proxy处理流程
  • Create React App 使用
  • learning koa2.x
  • October CMS - 快速入门 9 Images And Galleries
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • vue--为什么data属性必须是一个函数
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 简单数学运算程序(不定期更新)
  • 理解在java “”i=i++;”所发生的事情
  • 前端面试总结(at, md)
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 学习使用ExpressJS 4.0中的新Router
  • 异步
  • 自动记录MySQL慢查询快照脚本
  • # Redis 入门到精通(九)-- 主从复制(1)
  • $.ajax中的eval及dataType
  • (7) cmake 编译C++程序(二)
  • (C)一些题4
  • (function(){})()的分步解析
  • (第三期)书生大模型实战营——InternVL(冷笑话大师)部署微调实践
  • (二)JAVA使用POI操作excel
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (论文阅读40-45)图像描述1
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (四)Linux Shell编程——输入输出重定向
  • (转)ORM
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET 给NuGet包添加Readme
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET单元测试使用AutoFixture按需填充的方法总结
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • @ResponseBody
  • [ Socket学习 ] 第一章:网络基础知识
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell