网站首页 密码学

微软同态加密SEAL库的使用学习

发布时间:2021-3-23 9:22 Tuesday编辑:admin阅读(1269)

    https://github.com/microsoft/SEAL.git

    一、编译

    最近git有问题,最好翻墙,而且后面编译时候好像也要下点东西,如果不会改cmake的话,翻墙省不少功夫。。

    我是直接在Clion中以cmake项目的方式打开的。

    手动编译如下:


    cmake -S . -B build
    cmake --build build
    sudo cmake --install build


    二、SEAL库介绍


        Microsoft SEAL提供了两种不同的同态加密方案,它们具有非常不同的属性。BFV方案允许在加密的整数上执行模运算。CKKS方案允许对加密的实数或复数进行加法和乘法,但只能得到近似的结果。在诸如汇总加密的真实数字、评估加密数据上的机器学习模型或计算加密位置的距离等应用程序中,ckk将是最佳选择。对于需要精确值的应用程序,BFV方案是惟一的选择。

        1.BFV代码介绍

    
    
    //较大的poly_modulus_degree使密文的大小更大,所有的操作都更慢,但允许更复杂的加密计算。
    
    size_t poly_modulus_degree = 4096;
    
    parms.set_poly_modulus_degree(poly_modulus_degree);
    
    //更大的coeff_模数意味着更大的噪声预算,因此更加密的计算能力。coeff_modulus_degree确定了coeff_modul_modules总比特长度的上限
    parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree)); 
    
    
    //明文模量决定了明文数据类型的大小和乘法中噪声预算的消耗。
    
    parms.set_plain_modulus(1024);
    //构建一个SEALContext对象了。这是一个繁重的类,它检查我们刚刚设置的参数的有效性和属性。
    
    auto context = SEALContext::Create(parms);
    
    
    这个库是基于公钥加密的方案,本来就是想找这个的,之前在github看tfhe的代码,是基于对称加密的,这个团队论文里写了,然而没实现emm。
        KeyGenerator keygen(context);
        PublicKey public_key = keygen.public_key();
        SecretKey secret_key = keygen.secret_key();

    然后就是通过evaluator计算器调用内部函数的过程了


    evaluator.square(x_encrypted, x_sq_plus_one); //平方x_encrypted,刷新入x_sq_plus_one

    Plaintext plain_one("1"); //添加明文 1

    evaluator.add_plain_inplace(x_sq_plus_one, plain_one);

     
    
    evaluator.add_plain(x_encrypted, plain_one, x_plus_one_sq); evaluator.square_inplace(x_plus_one_sq);



    Plaintext plain_two("2"); 


    evaluator.multiply_plain_inplace(x_sq_plus_one, plain_two);

    evaluator.multiply(x_sq_plus_one, x_plus_one_sq, encrypted_result);

    以上基本就是加和乘的常用操作了,最后还有就是要判断噪音消耗,噪声预算已经达到0,这意味着不能期望解密给出正确的结果

    这个函数:

    decryptor.invariant_noise_budget(encrypted_result) 


    解决办法:

    “Relinearization”是一种将密文的大小乘回初始大小2的操作。因此,在下一次乘法之前对一个或两个输入密文进行再初始化,可以对噪声增长和性能产生巨大的积极影响,即使再初始化本身有很大的计算成本。只可能将大小为3的密文重新初始化为大小为2的密文,因此用户通常希望在每次乘法之后重新初始化,以将密文大小保持为2。





    RelinKeys relin_keys; 
    keygen.create_relin_keys(relin_keys);



    evaluator.relinearize_inplace(x_squared, relin_keys);