2021SC@SDUSC

2021-12-19

前言

前两篇我们讨论了SEAL对于BFV的实现。本篇开始我将开始讨论SEAL对于CKKS的实现。
照例我会先补充理论知识,然后分析源码native/examples/_ckks_basis.cpp文件。当然注意,本文的目的并非深入探究CKKS原理,而是力求帮助开发者在完全不懂原理的情况下,快速构建CKKS工程,并掌握基本的使用技巧。

CKKS简介

CKKS算法是2017年论文《Homomorphic Encryption for Arithmetic of Approximate Numbers》中提出的近似计算同态加密算法,其具体构造基于BGV方案,但也可以依赖于其他现有的同态方案。
如论文标题所写的那样,不同于以往同态加密算法中所追求的解密结果和明文完全一致,CKKS算法的目标是做近似计算。这并不偏离需求,因为现实生活中大部分运算,面对的是实数(复数),而实数(复数)的运算,往往只需要保留一部分有效数字即可。此外,允许误差,放宽准确性的限制,使得CKKS对比于其他基于LWE/RLWE难题的同态方案,细节有了较大的简化,计算效率也有了很大提升。
CKKS提出之后很快被纳入于同态加密库的实现中,包括IBM的HElib,微软的SEAL,以及最全面的通用格密码库PALISADE。
Notation:本文用m代指明文,c代指密文

代码分析:标准化构建流程

经过对于源码的整体阅读,我们先分析一下构建的总体流程。
看代码之前我们先回顾一些概念:
首先,CKKS是一个公钥加密体系,具有公钥加密体系的一切特点,例如公钥加密、私钥解密等。因此,我们的代码中需要以下组件:

  • 密钥生成器 keygenerator
  • 加密模块 encryptor
  • 解密模块 decryptor

其次,CKKS是一个(level)全同态加密算法(level表示其运算深度仍然存在限制),可以实现数据的“可算不可见”,因此我们还需要引入:

  • 密文计算模块 evaluator

最后,加密体系都是基于某一数学困难问题构造的,CKKS所基于的数学困难问题在一个“多项式环”上(没有数论知识也没有关系,只需要明白环上的元素与实数并不相同),因此我们需要引入:

  • 编码器 encoder

来实现数字和环上元素的相互转换。
总结下来,整个构建过程为:
① 选择CKKS参数 parms
② 生成CKKS框架 context
③ 构建CKKS模块 keygenerator,encoder,encryptor,evaluator和decryptor
④ 使用encoder 将 数据n 编码为 明文m
⑤ 使用encryptor 将 明文m 加密为 密文c
⑥ 使用evaluator 对 密文c 运算为 密文c’
⑦ 使用decryptor 将 密文c’ 解密为 明文m’
⑧ 使用encoder 将 明文m’ 解码为 数据n’

同态加密算法最直观的应用是云计算,其基本流程为:
①发送方利用公钥pk 加密 明文m 为 密文c
②发送方把密文c发送到服务器
③服务器执行密文运算,生成结果密文 c’
④服务器将结果密文c’发送给接收方
⑤接收方利用私钥sk 解密密文c’为明文结果m’
当发送方与接收方相同时,则该客户利用全同态加密算法完成了一次安全计算,即既利用了云计算的算力,又保障了数据的安全性,这对云计算的安全应用有重要意义。

代码解释

print_example_banner("Example: CKKS Basics");

在这个例子中,我们演示了一个多项式函数的求值
PI * x^3 + 0.4*x + 1
在加密的浮点输入数据x为一组4096等距点在区间[0,1]。这个例子演示了CKKS方案的许多主要特性,但也说明了使用它的挑战。
我们首先建立CKKS方案。

EncryptionParameters parms(scheme_type::CKKS);

我们在2_encoders.cpp中看到CKKS中的乘法导致了规模在密文中成长。任何密文的尺度都不能太接近coeff_modulus的总大小,否则密文就会耗尽空间来存储放大的明文。CKKS方案提供了一个“rescale”功能,可以减少scale,并稳定scale扩展。

Rescaling是一种模转换操作(回忆一下3_levels.cpp’)。在转换模量时,它会从coeff_modulo中移除最后一个素数,但作为副作用,它会通过移除的素数缩小了密文。通常,我们想要对尺度如何变化有完美的控制,这就是为什么在CKKS方案中,为coeff_moduls使用精心挑选的素数更为常见。

更精确地说,假设CKKS密文中的scale为S,则当前coeff_modulus(密文)中的最后一个素数是P. Rescaling下一层将scale更改为S/P,并从coeff_modulo中删除素数P,和模量切换中通常的做法一样。质数的数量限制了重新计算的次数,从而限制了计算的乘法深度。
自由选择初始规模是有可能的。一个好的策略是在coeff_modul_be中设置初始标度S和素数P_i彼此非常接近。如果密文在乘法之前有scale S,乘法之后是S^2,rescaling之后是 S^2 / P_i。如果所有P_i接近S,然后S^2/P_i又接近S。通过这种方法,我们可以在整个计算过程中使scale稳定在接近S。一般来说,对于深度D的电路,我们需要缩放D倍,即我们需要把D 素数从系数模数中去掉。一旦在coeff_modules中只剩下一个素数,剩下的素数必须比S大几个位,以保留明文的小数点前值。
我们使用

CoefModulusf::Create

来生成适当大小的素数。注意,我们的coeff_modules是200位,这低于我们的多项式模数: coeff_modulus_degree::MaxBitCount(8192)返回218`。

size_t poly_modulus_degree = 8192;parms.set_poly_modulus_degree(poly_modulus_degree);parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 60, 40, 40, 60 }));

我们选择初始规模为2^40。在最后一层,小数点前留下60-40=20位精度,小数点后留下足够(大约10-20位)的精度。因为我们的中间质数是40位(事实上,它们非常接近2的40),所以我们可以像上面描述的那样实现规模稳定。

    double scale = pow(2.0, 40);auto context = SEALContext::Create(parms);print_parameters(context);cout << endl;KeyGenerator keygen(context);auto public_key = keygen.public_key();auto secret_key = keygen.secret_key();auto relin_keys = keygen.relin_keys();Encryptor encryptor(context, public_key);Evaluator evaluator(context);Decryptor decryptor(context, secret_key);CKKSEncoder encoder(context);size_t slot_count = encoder.slot_count();cout << "Number of slots: " << slot_count << endl;vector<double> input;input.reserve(slot_count);double curr_point = 0;double step_size = 1.0 / (static_cast<double>(slot_count) - 1);for (size_t i = 0; i < slot_count; i++, curr_point += step_size){input.push_back(curr_point);}cout << "Input vector: " << endl;print_vector(input, 3, 7);cout << "Evaluating polynomial PI*x^3 + 0.4x + 1 ..." << endl;/*We create plaintexts for PI, 0.4, and 1 using an overload of CKKSEncoder::encodethat encodes the given floating-point value to every slot in the vector.*/Plaintext plain_coeff3, plain_coeff1, plain_coeff0;encoder.encode(3.14159265, scale, plain_coeff3);encoder.encode(0.4, scale, plain_coeff1);encoder.encode(1.0, scale, plain_coeff0);Plaintext x_plain;print_line(__LINE__);cout << "Encode input vectors." << endl;encoder.encode(input, scale, x_plain);Ciphertext x1_encrypted;encryptor.encrypt(x_plain, x1_encrypted);/*To compute x^3 we first compute x^2 and relinearize. However, the scale hasnow grown to 2^80.*/Ciphertext x3_encrypted;print_line(__LINE__);cout << "Compute x^2 and relinearize:" << endl;evaluator.square(x1_encrypted, x3_encrypted);evaluator.relinearize_inplace(x3_encrypted, relin_keys);cout << "    + Scale of x^2 before rescale: " << log2(x3_encrypted.scale())<< " bits" << endl;

现在rescale;除了模数切换之外,规模还减少了一个因子,该因子等于被切换掉的素数(40位素数)。因此,新的scale应该接近2的40次方。但是注意,scale不等于2^40:这是因为40位素数只接近2的40次方。

 print_line(__LINE__);cout << "Rescale x^2." << endl;evaluator.rescale_to_next_inplace(x3_encrypted);cout << "    + Scale of x^2 after rescale: " << log2(x3_encrypted.scale())<< " bits" << endl;

最后。CKKS支持模切换,就像BFV方案一样,允许我们在根本不需要时切换部分系数模量。

 print_line(__LINE__);cout << "Normalize encryption parameters to the lowest level." << endl;parms_id_type last_parms_id = x3_encrypted.parms_id();evaluator.mod_switch_to_inplace(x1_encrypted, last_parms_id);evaluator.mod_switch_to_inplace(plain_coeff0, last_parms_id);/*三个密文兼容,可加了All three ciphertexts are now compatible and can be added.*/print_line(__LINE__);cout << "Compute PI*x^3 + 0.4*x + 1." << endl;Ciphertext encrypted_result;evaluator.add(x3_encrypted, x1_encrypted, encrypted_result);//计算结果存入 encrypted_resultevaluator.add_plain_inplace(encrypted_result, plain_coeff0);/*First print the true result.*/Plaintext plain_result; //明文结果print_line(__LINE__);cout << "Decrypt and decode PI*x^3 + 0.4x + 1." << endl;cout << "    + Expected result 希望打印出:" << endl;vector<double> true_result;for (size_t i = 0; i < input.size(); i++){double x = input[i];true_result.push_back((3.14159265 * x * x + 0.4)* x + 1);}print_vector(true_result, 3, 7);/*  真正解密、解码、打印 看看如何Decrypt, decode, and print the result.*/decryptor.decrypt(encrypted_result, plain_result); //解密vector<double> result;encoder.decode(plain_result, result);   //解码cout << "    + Computed result ...... Correct." << endl;print_vector(result, 3, 7);

虽然我们没有在这些例子中显示任何复数的计算,但是CKKSEncoder可以让我们很容易地做到这一点。复数的加法和乘法就像人们所期望的那样。

结语

本篇分析先到此为止。对于理论知识的补充一直在继续。

SEAL全同态加密开源库(十二) CKKS-源码浅析相关推荐

  1. SEAL全同态加密开源库(七) rns剩余数系统-源码解析

    SEAL全同态加密开源库(七) rns剩余数系统-源码解析 2021SC@SDUSC 2021-11-14 前言 这是SEAL开源库代码分析报告第六篇,本篇将分析util文件夹中的rns.h和rns. ...

  2. SEAL全同态加密开源库(八) rns源码解析(2)

    SEAL全同态加密开源库(七) rns剩余数系统-源码解析 2021SC@SDUSC 2021-11-21 前言 这是SEAL开源库代码分析报告第七篇,本篇将继续分析util文件夹中的rns.h和rn ...

  3. SEAL全同态加密开源库(十一) BFV-源码浅析(2)

    2021SC@SDUSC 2021-12-12 前言 从本篇开始,接上一篇的BFV分析,这里我们继续分析BFV源码.争取本篇结束战斗. 与之前的工作相比,这些代码显得更具整体性,也能更好体现出SEAL ...

  4. Miracle密码算法开源库(一)源码分析 :mraes.c

    2021SC@SDUSC 山东大学软件学院软件工程应用与实践 一.mraes.c结构 mraec.c的总体结构如下,具有fbsub.ftable1等数组,主要实现了aes_decrypt .aes_e ...

  5. OPPO 40万年薪招应届生,狂揽芯片人才;恶意差评小米新手机,一用户被判赔3万元;谷歌开源全同态加密通用转译器|极客头条...

    「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 梦依丹 出品 | CSDN(ID:CSDNnews ...

  6. OPPO 40万年薪招应届生,狂揽芯片人才;恶意差评小米新手机,一用户被判赔3万元;谷歌开源全同态加密通用转译器|极客头条

    一分钟速览新闻点! 小米造车"急"了,发布大量自动驾驶相关岗位招聘 阿里平头哥:国产嵌入式 CPU 实现关键技术突破 BOSS 直聘:2021 年应届生岗位平均薪资为 6112 元 ...

  7. 实测 Google 全同态加密FHE,效果如何?

    文 / 瑚琏 技术爱好者,广泛涉猎各领域机器学习技术,对不规范代码重度过敏.本篇首发于富数科技官方公号. Google 开源了首个通用全同态加密(FHE)的转译器(transpiler),可以将普通的 ...

  8. 谷歌开源首个通用全同态加密转译器

    谷歌近日开源了首个通用全同态加密(FHE)的转译器(transpiler),可以将普通的C++程序转译为基于TFHE同态库的同态程序,将明文运算转换为了同态密文运算.这个项目依赖XLS和TFHE两个库 ...

  9. 全同态加密 (FHE) 框架

    同态加密密码系统是一种解密是态射的密码系统. Decrypt(a*b) = Decrypt(a) * Decrypt(b) 同态加密密码系统允许在不解密的情况下对密文进行操作.它确保了端到端的语义安全 ...

最新文章

  1. c++ 打开添加删除程序_Docker 添加容器到一个网络
  2. android gridview滑动卡,Android RecyclerView的卡顿问题
  3. angular 指令渲染_Angularjs渲染的 using 指令的星级评分系统示例
  4. DM6467T开发板领航——dmai经验谈
  5. tracepro应用实例详解_离心铸造工艺(实例)
  6. 域服务器批量修改用户密码,Windows域控制器批量创建用户
  7. oracle join过滤数据,oracle join on 数据过滤问题
  8. 开源数据同步神器——canal
  9. jquery怎么创建一个img标签
  10. POJ1860Currency Exchange(SPFA)
  11. Mysql中max函数取得的值不是最大
  12. 揭开互联网金融健康发展意见神秘面纱
  13. 黑客逆向破解基础-1:壳、加壳和脱壳分别是什么?加壳的解压原理介绍。
  14. 视频主观质量评价方法总结
  15. 随心所欲的“四舍五入” 之 ROUNDDOWN函数如何使用?
  16. 决定人生高度的,不是智力,而是体力
  17. 一个新手的评价---人机交互方面(有些不搭题
  18. Android Bitmap关于setPixel设置的值和getPixel获得的值不一样的问题
  19. JavaWeb之页面跳转数据库连接
  20. 计算机二级关系代数运算知识点,计算机二级:关系代数运算.doc

热门文章

  1. 数据分析方法和思维—RFM用户分群
  2. Es检索 must与filter区别
  3. Android Studio打包APK安装失败:应用是非正式版本,当前设备不支持安装
  4. 云计算基础知识:何为混合云?
  5. 一生中最值得珍藏的电影台词
  6. 华为无线-Portal认证异常-无线强制切换为手机流量
  7. 嚼得菜根做得大事·《菜根谭》·十
  8. 17:Oriented R-CNN for Object Detection
  9. 计算机应用技术专业名词解释,计算机应用技术名词解释--02316(26页)-原创力文档...
  10. 【Android 教程系列第 13 篇】在小米手机上使用安卓投屏软件 QtScrcpy ,为什么点击屏幕没有反应