Seal库官方示例(二):encoders.cpp解析

news2025/4/5 1:32:25

补充一个常用的SIMD操作原理
1928790-20220311160927293-1090011372.png
图片来自的Hang Shao的文章。

完整代码
这个代码主要功能是编码明文,使得能够使用更加完整的明文多项式(前一个只用到了一个多项式的常量),也就是SIMD操作。主要包含了两个部分,一个是BGV、BFV的BatchEncoder,另一个是CKKS的CKKSEncoder。

BatchEncoder

for BFV or BFV
批处理编码,将明文多项式视为一个矩阵(假设多项式阶数为N,明文模数为T,那么这个矩阵就是一个 2 × N 2 2 \times \frac N2 2×2N的矩阵,其中每个元素都需要mod T),在矩阵视角之下,批处理可以通过一些方法来加速运算优势就是,对密文的操作相当于对所有N个明文(也就是插槽)做同样的操作,速度远超过没有使用批处理的。

首先是比较常规的参数设置,bgv和bfv一样的,直接换方案名字就行了。

EncryptionParameters parms(scheme_type::bfv);
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));

要能使用批处理,需要设置明文模数为一个 **1mod2*多项式阶数 **的一个素数,下面的代码创建了这样以恶个20-bits大小的素数。

parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 20));

SEALContext context(parms);
print_parameters(context);
cout << endl;

看看输出结果
image.png

验证一下批处理是否是启用状态

auto qualifiers = context.first_context_data()->qualifiers();
cout << "Batching enabled: " << boolalpha << qualifiers.using_batching << endl;

结果
image.png

接着生成加密相关的公钥,私钥,评估密钥等。

KeyGenerator keygen(context);
SecretKey secret_key = keygen.secret_key();
PublicKey public_key;
keygen.create_public_key(public_key);
RelinKeys relin_keys;
keygen.create_relin_keys(relin_keys);
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);

创建批处理实例和设置批处理的插槽,插槽的数量等于多项式的模阶数N,

BatchEncoder batch_encoder(context);
size_t slot_count = batch_encoder.slot_count();
size_t row_size = slot_count / 2;
cout << "Plaintext matrix row size: " << row_size << endl;

创建明文矩阵 2 × N 2 2 \times \frac N2 2×2N,每个元素要模T

vector<uint64_t> pod_matrix(slot_count, 0ULL);
pod_matrix[0] = 0ULL;
pod_matrix[1] = 1ULL;
pod_matrix[2] = 2ULL;
pod_matrix[3] = 3ULL;
pod_matrix[row_size] = 4ULL;
pod_matrix[row_size + 1] = 5ULL;
pod_matrix[row_size + 2] = 6ULL;
pod_matrix[row_size + 3] = 7ULL;

cout << "Input plaintext matrix:" << endl;
print_matrix(pod_matrix, row_size);

这里创建的矩阵输出如下
image.png

接着是将矩阵编码为多项式

Plaintext plain_matrix;
print_line(__LINE__);
cout << "Encode plaintext matrix:" << endl;
batch_encoder.encode(pod_matrix, plain_matrix);

可以解码来看看正确性

vector<uint64_t> pod_result;
cout << "    + Decode plaintext matrix ...... Correct." << endl;
batch_encoder.decode(plain_matrix, pod_result);
print_matrix(pod_result, row_size);

结果
image.png

现在,来加密明文

Ciphertext encrypted_matrix;
print_line(__LINE__);
cout << "Encrypt plain_matrix to encrypted_matrix." << endl;
encryptor.encrypt(plain_matrix, encrypted_matrix);
cout << "    + Noise budget in encrypted_matrix: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits"
     << endl;

看看噪声预算
image.png

现在,操作密文就相当于对8192个明文槽同时进行操作!为了显示效果,首先创建第二个明文矩阵

vector<uint64_t> pod_matrix2;
for (size_t i = 0; i < slot_count; i++)
{
    pod_matrix2.push_back((i & size_t(0x1)) + 1);
}
Plaintext plain_matrix2;
batch_encoder.encode(pod_matrix2, plain_matrix2);
cout << endl;
cout << "Second input plaintext matrix:" << endl;
print_matrix(pod_matrix2, row_size);

image.png

这里执行的同态操作是第一个矩阵的密文加上第二个矩阵的明文,并且取平方

print_line(__LINE__);
cout << "Sum, square, and relinearize." << endl;
evaluator.add_plain_inplace(encrypted_matrix, plain_matrix2);
evaluator.square_inplace(encrypted_matrix);
evaluator.relinearize_inplace(encrypted_matrix, relin_keys);

查看一下噪声预算,看看是否能正确的解密

cout << "    + Noise budget in result: " << decryptor.invariant_noise_budget(encrypted_matrix) << " bits" << endl;

不为0,那么可以解密
image.png

解密,解码并输出

Plaintext plain_result;
print_line(__LINE__);
cout << "Decrypt and decode result." << endl;
decryptor.decrypt(encrypted_matrix, plain_result);
batch_encoder.decode(plain_result, pod_result);
cout << "    + Result plaintext matrix ...... Correct." << endl;
print_matrix(pod_result, row_size);

image.png

然后有个奇怪的点,密文加上明文的操作怎么单独写了一个函数,同态操作是密文之间的运算,那么大概这个密文加上明文就是,先把明文加密,再相加,于是写了段代码试了一下

/*
自己添加的代码
*/
cout << "+++++++++++++++" << endl;
Ciphertext encrypted_matrix1, encrypted_matrix2, ciphertext_result;
encryptor.encrypt(plain_matrix2, encrypted_matrix2);
encryptor.encrypt(plain_matrix, encrypted_matrix1);
evaluator.add(encrypted_matrix2, encrypted_matrix1, ciphertext_result);
evaluator.square_inplace(ciphertext_result);
evaluator.relinearize_inplace(ciphertext_result, relin_keys);
cout << "    + Noise budget in result: " << decryptor.invariant_noise_budget(ciphertext_result) << " bits"
     << endl;
Plaintext plain_result2;
decryptor.decrypt(ciphertext_result, plain_result2);
batch_encoder.decode(plain_result2, pod_result);
print_matrix(pod_result, row_size);

运行截图,噪声预算是一样的,那么这个函数的实质就是先明文加密,再相加,调用能少写点代码。
image.png

当然,bfv,bgv方案里面的处理都是以整数形式,那么在代码中,整数类型的位数是比较少的,那么通过多次同态计算后就容易造成数据类型溢出。所以接下来就有了ckks的编码。

CKKSEncoder

CKKS是针对浮点数类型的近似运算,也就是会丢失一定的精度。CKKS没有明文模数哦。
首先依然是方案参数设置,至于为什么这么设置5个40bit的,ckks方案用的是模数链,每一个模数因子都接近缩放因子 Δ \Delta Δ,用于rescale重缩放。

EncryptionParameters parms(scheme_type::ckks);

size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 40, 40, 40, 40, 40 }));
SEALContext context(parms);
print_parameters(context);
cout << endl;

参数结果
image.png

密钥生成(包含私钥,公钥,评估密钥)

KeyGenerator keygen(context);
auto secret_key = keygen.secret_key();
PublicKey public_key;
keygen.create_public_key(public_key);
RelinKeys relin_keys;
keygen.create_relin_keys(relin_keys);

加解密器,同态计算,编码的实例化

Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
CKKSEncoder encoder(context);

ckks的编码是把复数或实数数字向量编码为明文对象

ckks的插槽数量为多项式阶数/2(它的明文空间就是 C N / 2 \mathbb C^{N/2} CN/2),这里就没有像BFV一样化为两行矩阵了。

size_t slot_count = encoder.slot_count();
cout << "Number of slots: " << slot_count << endl;

定义明文向量

vector<double> input{ 0.0, 1.1, 2.2, 3.3 };
cout << "Input vector: " << endl;
print_vector(input);

image.png

好了,现在来回顾一下CKKS算法里的编码步骤:首先从N/2维扩张到N维,接着乘以一个缩放因子(用于提高精确度,这个因子就接近与重缩放要用的模数),最后是取整并编码为多项式

设立缩放因子并编码,这里设置的为2^30,使用0填充到N维(这好像跟方案里写的不一样,方案里是取的共轭再拼接)

Plaintext plain;
double scale = pow(2.0, 30);
print_line(__LINE__);
cout << "Encode input vector." << endl;
encoder.encode(input, scale, plain);

可以立刻解码看看

vector<double> output;
cout << "    + Decode input vector ...... Correct." << endl;
encoder.decode(plain, output);
print_vector(output);

image.png

接着是加密

Ciphertext encrypted;
print_line(__LINE__);
cout << "Encrypt input vector, square, and relinearize." << endl;
encryptor.encrypt(plain, encrypted);

计算平方,重线性化缩小密文规模

evaluator.square_inplace(encrypted);
evaluator.relinearize_inplace(encrypted, relin_keys);

平方后,缩放因子也跟着平方,所以现在缩放因子达到了2^60

cout << "    + Scale in squared input: " << encrypted.scale() << " (" << log2(encrypted.scale()) << " bits)"
     << endl;

print_line(__LINE__);
cout << "Decrypt and decode." << endl;
decryptor.decrypt(encrypted, plain);
encoder.decode(plain, output);
cout << "    + Result vector ...... Correct." << endl;
print_vector(output);

image.png

当然这里演示的不是完整的ckks方案,还少了rescale过程,也就是重缩放(还原缩放因子和降低噪声),主要看看如何编码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Animator动画状态机

1、有限状态机 有限状态机&#xff08;Finite - state machine, FSM&#xff09;&#xff0c;又称有限状态自动机&#xff0c;简称状态机&#xff0c;是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型 有限&#xff1a;表示是有限度的不是无限的 状态&#x…

机器人开发--减速机

机器人开发--减速机1 概述介绍功能分类按照传动类型可分为&#xff1a;按照传动级数不同可分为&#xff1a;按照齿轮形状可分为:按照传动的布置形式可分为:应用2 电机使用减速机原因3 RV减速机、谐波减速机 和 行星减速机RV减速机谐波减速机行星减速机蜗轮蜗杆减速机4 机器人各…

社区系统项目复盘-1

文章目录技术架构开发环境开发社区首页技术架构 Spring BootSpring、Spring MVC、MyBatisRedis、Kafka、ElasticsearchSpring Security、Spring Actuator 开发环境 构建工具&#xff1a;Apache Maven 版本&#xff1a;3.6.1集成开发环境&#xff1a;IntelliJ IDEA数据库&…

R3LIVE代码详解(四)

0. 简介 上一节中&#xff0c;我们过完了VIO中的状态预测以及特征点跟踪部分。此时我们已经拿到了光流的特征点信息&#xff0c;而这部分越来越接近我们想要去讲的帧到帧的VIO部分了。这一节&#xff0c;我们将围绕着VIO部分来进行讲解 1. PNP误差更新 我们从之前的博客《经…

人工智能前沿——未来AI技术的五大应用领域

关注“PandaCVer”公众号 >>>深度学习Tricks&#xff0c;第一时间送达<<< 目录 一、航空航天 二、医疗保健 三、建筑行业 四、能源领域 五、供应链 关于YOLO算法改进及论文投稿可关注并留言博主的CSDN/QQ >>>一起交流&#xff01;互相学习&…

力扣(LeetCode)1758. 生成交替二进制字符串的最少操作数(C++)

模拟 我们最终串只有两种形态 ① 1010101…1010101\dots1010101… 偶数位全 111 &#xff0c;奇数位全 000 &#xff0c; ② 0101010…0101010\dots0101010… 偶数位全 000 &#xff0c;奇数位全 111 &#xff0c; 我们统计将偶数位全变成 111 &#xff0c;奇数位全变成 000 的…

传奇外网架设全套图文教程-Hero引擎

当你拿到一个Hero引擎的版本&#xff0c;首先查看一下版本内文件是否完整&#xff0c;一个完整的Hero版本应该包括&#xff1a;DBServer、LoginGate、LoginSrv、LogServer、Mir200、Mud2、RunGate、SelGate、网站和GameCenter.exe&#xff08;引擎&#xff09;&#xff0c;以上…

龙芯 处理器

龙芯&#xff1a;国内最早自主研发芯片厂商&#xff0c;MIPS 架构体系自主化程度高 龙芯是中国科学院计算所自主研发的通用CPU&#xff0c;采用自主LoongISA指令系统&#xff0c;兼容MIPS指令 n “龙芯”是我国最早研制的高性能通用处理器系列&#xff0c;于 2001 年在中科院计…

【每日一题Day42】生成交替二进制字符串的最小操作数 | 模拟 位运算

生成交替二进制字符串的最小操作数【LC1758】 You are given a string s consisting only of the characters 0 and 1. In one operation, you can change any 0 to 1 or vice versa. The string is called alternating if no two adjacent characters are equal. For example,…

黑马点评--用户签到

用户签到 BitMap用法签到功能签到统计 BitMap用法&#xff1a; 我们按月来统计用户签到信息&#xff0c;签到记录为1&#xff0c;未签到则记录为0.&#xff08;布隆过滤器就是采用这种结构&#xff09; 把每一个bit位对应当月的每一天&#xff0c;形成了映射关系。用0和1标示…

docker的安装

1、docker官网 Install Docker Engine on CentOS | Docker Documentation yum -y install gcc yum -y install gcc-c yum install -y yum-utils yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum makecache fast yum insta…

原型(克隆)模式

文章目录思考原型(克隆)模式1.原型模式的本质2.何时选用原型模式3.优缺点4.实现原型模式(浅克隆)原型模式(深克隆)java浅克隆java深克隆思考原型(克隆)模式 原型模式顾名思义通过一个接口实现快速创建对象 1.原型模式的本质 原型模式的本质:克隆生成对象。 克隆是手段&#xff…

【Ubuntu】进程与线程编程实验

文章目录进程与线程实验一&#xff1a;创建进程基础版&#xff1a;创建父子线程 fork基础版&#xff1a;父子线程交替运行基础版&#xff1a;创建进程 文件写入练习版&#xff1a;创建线程 子读父阻塞实验二&#xff1a;线程共享进程中的数据实验三&#xff1a;多线程实现单词统…

总结709(bug集合)

今天不知道怎么了&#xff0c;那个曾弄了我20多天的冒险模块&#xff0c;在今天&#xff0c;差不多要完工了。弄出的那一刻&#xff0c;有的是喜悦&#xff0c;但之后&#xff0c;更多的是叹气。 也就是从此刻我才意识到&#xff0c;我曾自认为很崇高的职位&#xff0c;可能事…

传奇出现黑屏卡屏不动是怎么回事

在写这篇文章之前&#xff0c;先给给大家说一下&#xff0c;这篇文章写的是出现黑屏、卡屏不动是我们玩传奇的时候出现的&#xff0c;而不是在架设传奇时候出现的&#xff0c;所以要特别是注意一下&#xff0c;架设和玩出现黑屏是完全不一样的&#xff0c;所以解决方案也不一样…

驱动开发 platfrom总线驱动的三种方式

驱动的分隔与分离&#xff1a; 对于 Linux 这样一个成熟、庞大、复杂的操作系统&#xff0c;代码的重用性非常重要&#xff0c;在驱动程序&#xff0c;因为驱动程序占用了 Linux 内核代码量的大头&#xff0c;如果不对驱动程序加以管理&#xff0c;任由重复的代码肆意增加&…

基于深度学习的合成孔径雷达自聚焦

文章目录引言什么是合成孔径雷达什么是自聚焦经典自聚焦方法基于机器学习的方法基于极速学习机的方法基于深度学习的SAR自聚焦代码附录引言 本文全面介绍合成孔径雷达自聚焦概念和方法。想获取更为详尽的描述&#xff0c;请参考以下几篇论文, 如果数据或代码对你的研究有用&am…

【ASM】字节码操作 工具类与常用类 ClassRemapper 介绍 类映射 代码混淆

文章目录 1.概述2. ClassRemapper#2.1 class info2.2 fields2.3 构造方法2.4 method3. 案例3.1 案例1-修改类名3.2 案例2-修改字段名和方法3.3 案例3-修改2个类4.总结1.概述 在上一篇文章:【ASM】字节码操作 工具类与常用类 InstructionAdapter 介绍 我们知道了,对于Instruc…

[思维模式-5]:《如何系统思考》-1- 认识篇 - 总体结构与知识框架

目录 前言&#xff1a; 第一篇&#xff1a;认知篇 第1章 无所不在的系统 // 2 第2章 思维的转变 // 30 第二篇&#xff1a;方法与工具 第3章 深入思考 // 50 第4章 动态思考 // 78 第5章 全面思考 // 109 第6章 系统思考的“新语言”&#xff1a;因果回路图 // …

Zookeeper(一)- Zookeeper介绍与集群部署

文章目录一、Zookeeper 介绍1. Zookeeper概述2. Zookeeper工作机制3. Zookeeper特点4. Zookeeper数据结构5. Zookeeper应用场景&#xff08;1&#xff09;统一命名服务&#xff08;2&#xff09;统一配置管理&#xff08;3&#xff09;统一集群管理&#xff08;4&#xff09;服…