近期刚接触SEAL库,本文记录该库的使用方法,具体的同态加密的原理不过多介绍,若有错误,请各位大佬批评指正。

SEAL(Simple Encrypted Arithmetic Library)是微软开源的同态加密库,基于C++11编写,代码在Github可以找到,额外依赖比较少,下载到本地编译安装就能使用了。

SEAL提供了两种机制的同态加密,BFVCKKS。我粗略的理解为前者编码整数,而后者可以用于编码浮点数。浮点数的编码,需要scale一定的倍数,将浮点数转换成整数。SEAL采用的同态加密算法基于多项式环,其中有几个重要的参数:

polynomial modulus
coefficient modulus
plaintext modulus (只在BFV机制中)

其中polynomial modulusmax coefficient modulus bit-length有一个对应关系,示例代码中给出了对应关系,比如1024 对应27,8192对应218。SEAL提供了默认设置的函数,其中polynomial modulus是必须设置的。本文主要讨论CKKS机制的用法,针对浮点数进行同态加密。

在SEAL中有一个重要的level的概念,根据示例代码里的注释,可以理解为SEAL根据默认的参数创建了一个modulus switching chain ,在同一个链上的加密实例除了coefficient modulus 其他都相同。下面示例代码给的一个解释:

coeff_modulus: { 50, 30, 30, 50, 50 }  +---+  Level 4 (all keys; `key level')|coeff_modulus: { 50, 30, 30, 50 }  +---+  Level 3 (highest `data level')|coeff_modulus: { 50, 30, 30 }  +---+  Level 2|coeff_modulus: { 50, 30 }  +---+  Level 1|coeff_modulus: { 50 }  +---+  Level 0 (lowest level)

这是通过set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 50, 30, 30, 50, 50 })) 方法设置的。这个我粗略的理解是用于浮点数乘法之后对扩展的倍数rescale,后面会介绍到。

由于SEAL代码用到了SIMD(Single Instruction Multiple Data)的技术加速同态加密操作,我简单的理解就是把多个明文一起加密成一个密文,例如可以把一个vector编码成一个密文Ciphertext。下面给出一个简单的加密操作基础的代码:

//定义加密参数
EncryptionParameters encryptionParameters(scheme_type::CKKS);
size_t poly_modulus_degree = 8192;
encryptionParameters.set_poly_modulus_degree(poly_modulus_degree);
encryptionParameters.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, {60,40,40,60}));
double scale = pow(2.0,40);
//创建加密上下文,并初始化相关实例
std::shared_ptr<SEALContext> context = SEALContext::Create(encryptionParameters);
KeyGenerator keyGenerator(context);auto public_key = keyGenerator.public_key();
auto secret_key = keyGenerator.secret_key();
auto relin_keys = keyGenerator.relin_keys();
const GaloisKeys galois_keys = keyGenerator.galois_keys();Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);CKKSEncoder encoder(context);
vector<double> test(1);
test.push_back(1.0);
//加密/解密操作都是在编码后的数据上进行
Plaintext test_plain;
Ciphertext test_cipher;
encoder.encode(test,scale, test_plain);
encryptor.encrypt(test_plain, test_cipher);
Plaintext plain_coeff1;
encoder.encode(3.0, scale, plain_coeff1);evaluator.multiply_plain_inplace(test_cipher,plain_coeff1);
evaluator.relinearize_inplace(test_cipher, relin_keys);
evaluator.rescale_to_next_inplace(test_cipher);Plaintext plain_test_result;
decryptor.decrypt(test_cipher, plain_test_result);
vector<double> test_result;
encoder.decode(plain_test_result, test_result);
print_vector(test_result, 4, 7);
//输出
/*
[ 0.0000000, 9.0000000, -0.0000000, -0.0000000, ..., -0.0000000, 0.0000000, -0.0000000, -0.0000000 ]
数组长度为 poly_modulus_degree/2
*/

基于此,目标是实现一个基于SEAL的矩阵相乘操作,该如何实现。简单的方法对两个矩阵的每个元素进行加密,然后相应乘法。但这样的方式当矩阵较大时,无论是时间还是内存上都难以承受。

基于前面描述的,SEAL可以把一个vector一起加密为一个Ciphertext,这个密文实际上是一个长度为poly_modulus_degree/2长度的vector(看了源码实际上是IntArray) 。在SEAL中,密文上的加法乘法操作都是element-wise的,是对每个元素的操作。实际上SEAL中向量的点积(dot product)是要自己扩展实现的。

[1.0,2.0,3.0,4.0]
//加密后
[c1,c2,c3,c4,...,c(0),c(0),c(0),c(0)] //这是一个密文

第一个向量乘第二个矩阵

如上图所示,以向量乘矩阵为例,我们可以把x1,x2,...xn加密成一个Ciphertext c1 ,然后可以把矩阵中的每一列y1,y2,...yn加密成一个Ciphertext c2 。那么调用multiply得到的乘积后的密文,实际上是x1y1,x2y2,...,xnyn加密后的结果(注意这是一个密文)。要求x1y1+x2y2+...+xnyn,需要额外的计算。SEAL中提供了rotate方法,对加密后的密文进行旋转移动。比如 x1,x2,...xn转成xn,x2,...x1 。(知乎怎么编辑公式啊!)利用如下的rotate_sum的方法可以计算得到一个每一项为z=x1y1+x2y2+...+xnyn的密文。

const int poly_modulus_degree_power = log2(poly_modulus_degree)
void rotate_sum(Evaluator& evaluator, Ciphertext& ciphertext, const GaloisKeys& keys){Ciphertext rotated;for (int i = 0; i < poly_modulus_degree_power - 1; ++i) {evaluator.rotate_vector(ciphertext, pow(2,i), keys, rotated);evaluator.add_inplace(ciphertext, rotated);}
}

类似这么一个过程

以上操作之后,再把这个密文除了第一项其他项数都变为0。这是向量乘以矩阵中的某一列,得到了一个第一项为乘积结果,其他项为0的密文。对于其他列的乘积也是类似,但需要把结果计算到一个密文中,其实就是把第j列的乘积结果向右旋转j位,再把相应的结果相加。

第j列的乘积结果向右旋转j位再累加

最终得到z1,z2,...,zn的一个密文(注意这是一个密文 )。这是向量乘矩阵的结果是一个密文,如果是矩阵相乘那么将得到的是一个密文的vector。

我自己的实验中,以一个784的输入向量乘784X200的矩阵,在参数poly_modulus_degree=8192的条件下,这个乘法大约化了40s(笔记本上测试)。其实这里可以看到,对于4096长度的密文长度,我只利用了前784位,还有大量的slot是属于浪费的。这里是不是存在着优化的方法?或者说是否还存在更加适合SEAL的矩阵乘法规则。

由于刚刚接触,还有一些问题。比如对于浮点数,是否是只能支持有限次的乘法,因为每次乘法之后scale实际上是会翻倍,尽管每次可以rescale到相同的倍数,但是这样实际上是下降到了低一层的level上,在经过几次乘法之后就会报超出范围的错。如果有大佬了解原因,还望不吝指教。根据计算的任务选取合适的参数实际上非常重要的,因为这会很大程度地影响SEAL计算的效率。以上只是我个人使用同态加密库的一些记录和心得,如果有错误还请批评指正。

把SEAL用于机器学习的Cryptonets实际上预测的效率也是很低,看最新的Cryptonets的库预测小数据集通常都需要上百秒。在隐私保护机器学习领域还有别的方式,有机会把基于MPC的方案整理总结写成文章。

bfv同态加密_微软同态加密库SEAL使用相关推荐

  1. gentry同态加密算法_全同态加密算法

    摘要 本文主要讲述完全同态加密算法. 1. 是什么? 同态加密是一种对称加密算法,由Craig Gentry发明提出.其同态加密方案包括4个算法,即密钥生成算法.加密算法.解密算法和额外的评估算法.全 ...

  2. 0宽字符加密_前端AES加密方式分析,及其python实现

    在前端常见的加密方式中AES很少使用,因为相对于非对称的RSA安全性很低,AES是典型的对称加密,密钥就在前端源码里. 案列网站是http://ewt360.com,一个并不复杂的网站,首先抓个包看看 ...

  3. mfc140dll 丢失 微软常用运行库_微软常用运行库合集 2020.9月(32amp;64位)

    每日一谈 电脑在刚买来的时候,我们常常会思考一个问题,那就是微软的运行库有必要安装吗?微软运行库有什么用?其实在这里我想说,微软运行库主要是运行计算机软件的,例如一些测绘的职业人员,需要用到Auto ...

  4. visual studio code Python终端运行_微软常用运行库合集32/64位只需一键全部安装

    微软常用运行库合集32/64位这些运行库都是采用Microsoft Visual Studio 20XX编写的软件必须使用的公用DLL运行库,相当于程序的字典文件:只需要一键全部安装,堪称装机必备神器 ...

  5. mysql数据库传输加密_[数据库]MySQL加密

    [数据库]MySQL加密 0 2016-12-28 13:00:07 MySQL字段加密和解密1.加密:aes_encrypt('admin','key') 解密:aes_decrypt(passwo ...

  6. bfv同态加密_全同态加密BFV-(section 2-SHE)

    写在前面 如果第一次来到我的专栏,如果想从头学习全同态加密FHE,那么点击下面的链接吧,我在最开始的地方等你~安全六三:全同态加密1-(BFV section 1)​zhuanlan.zhihu.co ...

  7. python url加密_使用base64加密在URL传递(python和php版本)

    把base64加密后在url传输,会把"+","/"分别替换为"-","_",以及会把末尾的等号"=" ...

  8. 电脑文件加密_电脑文件加密软件哪个好?企业加密软件排行榜

    企业电脑文件加密软件哪个好,企业加密软件排行榜最好用的加密软件是那个?这应该是当前很多涉密企业网络管理员人员的共同的心声.毋庸置疑,在高速发展的今天,企业信息安全.电脑文件安全.商业机密保护已经成为企 ...

  9. java python rsa加密_实现Java加密,Python解密的RSA非对称加密算法功能

    摘要 因为最近业务需要使用到openssl的rsa非对称加密算法,研究了下它的使用方式,但是特殊在于前端分IOS和android两端,所以前端部门要求使用java给他们做一个加密工具包,但是因为服务端 ...

最新文章

  1. Ant Design Pro 网络请求流程
  2. 百度黄埔学院计划第四期来了!
  3. lnmp环境切换php版本,并安装相应redis扩展
  4. sdut 1488 连通分量的个数(并查集)
  5. 百练OJ:2764:数根
  6. 盘一盘推荐系统里值得一读的那些论文
  7. 武汉大学计算机学院的李明,李明副研究员
  8. Java ClassLoader setDefaultAssertionStatus()方法与示例
  9. 关于部分手机无法搜索到5G wifi信号的解决方法
  10. C#/WPF学习笔记:起始
  11. 高级JAVA程序员必备:必看书籍清单
  12. 原码一位乘法和补码一位乘法
  13. 服务器cpu对游戏的支持,还想用服务器CPU玩游戏?其实没必要,至强E3-1231 V3时代已不在...
  14. LookaHead优化器
  15. 再见,2018俄罗斯世界杯!
  16. Impala: Reducing query concurrency or configuring admission control may help avoid this error
  17. 使用 Nginx 部署前后端分离项目,解决跨域问题
  18. erlang 开源项目之 Bigwig
  19. Qt: multiple definition of XXX
  20. html代码width什么意思,width:100% 啥意思呢,在什么情况下使用?

热门文章

  1. 码出高效:java开发手册_Java 11手册:最聪明的技巧来简化Java 11导航
  2. Python 字典get()函数的使用
  3. Linux之旅 9:正则表达式与文件格式化
  4. 【综述】情感计算的“前世今生”
  5. p50搭载鸿蒙os有什么不同,后置镜头变液态双摄?华为P50Pro再曝光,搭载鸿蒙OS传感器变1寸...
  6. C语言实现STL静态链表,先进后出的数据结构-栈 一
  7. 【Node.js超详细安装配置教程(2022)】
  8. 深入探索以太坊世界状态,Part-2
  9. 重定向次数过多 java_Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案...
  10. Vue2源码解析 虚拟节点VNode