抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

@auther by sizaif

HE 在人脸识别中的应用demo 演示文档

@[toc]

说明

  1. 使用的HE方案是CKKS
/
| Encryption parameters :
|   scheme: CKKS
|   poly_modulus_degree: 8192
|   coeff_modulus size: 200 (60 + 40 + 40 + 60) bits
|   scale: pow(2.0,40)
\
  1. 输入数据的长度 n = 10 ,
  2. 因为没有用FaceNet数据集的缘故,演示所用的测试数据来源为简单生成,生成方式为:
  3. 编译平台: Visual Studio 2019
  4. 所需外部环境: seal.h ; examples.hbits/stdc++.h
  5. 项目代码上传至: github: https://github.com/sizaif/SEALExamples/tree/main

数据来源

输入的input数据和database数据来源生成代码如下:

code
// slot_count = poly_modulus_degree /2  => 4096 
double curr_point = 0;
double step_size = 1.0 / (static_cast<double>(slot_count) - 1); 
ofstream out;
out.open("database.txt", ios::in | ios::out | ios::binary | ios::trunc);
if (out.is_open()) {
    int step = 0;
    for (size_t i = 0; i < slot_count; i++)
    {
        // 每10行一个数据
        if(step %10 == 9)
            out << curr_point << "\n";
        else {
            out << curr_point << " ";
        }
        step++;
        curr_point += step_size;
    }
    out << endl;
    out.close();
    cout << "Input vector: " << endl;
}

选取的input数据如下:

[0.984127 0.984371 0.984615 0.98486 0.985104 0.985348 0.985592 0.985836 0.986081 0.986325]

从生成的database中最后10行中选取第6行生成

image-20210203124141787


选取的database E 数据如下:

data

[0.974359 0.974603 0.974847 0.975092 0.975336 0.97558 0.975824 0.976068 0.976313 0.976557]
[0.976801 0.977045 0.977289 0.977534 0.977778 0.978022 0.978266 0.97851 0.978755 0.978999]
[0.979243 0.979487 0.979731 0.979976 0.98022 0.980464 0.980708 0.980952 0.981197 0.981441]
[0.981685 0.981929 0.982173 0.982418 0.982662 0.982906 0.98315 0.983394 0.983639 0.983883]
[0.984127 0.984371 0.984615 0.98486 0.985104 0.985348 0.985592 0.985836 0.986081 0.986325]
[0.986569 0.986813 0.987057 0.987302 0.987546 0.98779 0.988034 0.988278 0.988523 0.988767]
[0.989011 0.989255 0.989499 0.989744 0.989988 0.990232 0.990476 0.99072 0.990965 0.991209]
[0.991453 0.991697 0.991941 0.992186 0.99243 0.992674 0.992918 0.993162 0.993407 0.993651]
[0.993895 0.994139 0.994383 0.994628 0.994872 0.995116 0.99536 0.995604 0.995849 0.996093]
[0.996337 0.996581 0.996825 0.99707 0.997314 0.997558 0.997802 0.998046 0.998291 0.998535]


image-20210203124350026

过程步骤

总览

image-20210203193037721

  1. 首先计算 p 与 E 中的 $C_{i}$ 比较分数并用 $r_{i}$表示,求最佳的 $r_{i}$,

    $\mathbf{r}{i}=\operatorname{dist}\left(\mathbf{p}, \mathbf{c}{i}\right) \cdot \mathbf{k} ; k={1,0, \ldots 0}$​

    image-20210812101705064

  2. 处理完全部数据库内容后,N个单独结果的

    vector $\mathbf{R}=\left[\begin{array}{c}\mathbf{r}{1} \ \mathbf{r}{2} \ \vdots \ \mathbf{r}{N}\end{array}\right]=\left[\begin{array}{c}\left(\mathbf{r}{1,1}, 0, \ldots 0\right) \ \left(\mathbf{r}{2,1}, 0, \ldots 0\right) \ \vdots \ \left(\mathbf{r}{N, 1}, 0, \ldots 0\right)\end{array}\right]$​

    image-20210812101658056

    每个$r_{i}$​是单独加密的, 可以随机打乱$r_{i}$​的顺序

  3. 通过将$r_{i}$​移位,变成对角矩阵

    例如 $\mathbf{R}=\left[\begin{array}{c}
    \left(\mathbf{r}{1,1}, 0, \ldots 0\right) \
    \left(0, \mathbf{r}
    {2,1}, \ldots 0\right) \
    \vdots \
    \left(0,0, \ldots \mathbf{r}_{N, 1}\right)
    \end{array}\right]$​

    image-20210812101647010

  4. 将对角线上vector组合成新的带有与P比较分数的vector格式

    i.e. $R->\left(\mathbf{r}{1,1}, \mathbf{r}{2,1}, \ldots \mathbf{r}_{N, 1}\right)$​

    image-20210812101715291

  5. 将上式跟预先设定的阈值${t}=(t, t, \ldots t)$进行比较 形成新的vector d: $d = R - t$, 然后将d 传输给第三方

  6. 最终将 d 进行解密决定结果(decision),并传送给客户

    $d = R - t$​​ ; $d=R-t ; \quad$​​ decision $= \begin{cases}\text { accept } & \text { if } \exists d \in \mathbf{d}: d>0 \ \text { reject } & \text { if } \forall d \in \mathbf{d}: d \leq 0\end{cases}$

    image-20210812101724423

一: 将input和database中的数据分别加密获得encrypt_probe_p和 encrypt_E_matrix

1:加密得到probe_p

Ciphertext get_encrypt_probe(CKKSEncoder& ckks_encoder,Encryptor & encryptor, vector<double>v_input) {
    print_line(__LINE__);
    cout << "------get_encrypt_probe() begin------" << endl;

    /*
    * 加密获得probe_p;
    */
    Plaintext v_plaintext;
    // v编码
    ckks_encoder.encode(v_input, scale, v_plaintext);
    Ciphertext probe_p;
    // 加密
    encryptor.encrypt(v_plaintext, probe_p);

    print_line(__LINE__);
    cout << "------get_encrypt_probe() end------" << endl;
    return probe_p;
}

image-20210203124905421

将加密的probe_p解密做验证:

image-20210203130111249


2:将database中的所有数据分别加密,组成矩阵E:

vector<Ciphertext> get_encrypt_E_matrix(CKKSEncoder& ckks_encoder, Encryptor& encryptor, vector<vector<double>>E_matrix) {
    print_line(__LINE__);
    cout << "------get_encrypt_E_matrix() begin------" << endl;
    
    vector<Ciphertext> encrypt_E_matrix;
    for (auto it = E_matrix.begin(); it != E_matrix.end(); it++) {
        Plaintext plain_E_ci;
        Ciphertext encrypt_E_ci;
        ckks_encoder.encode(*it, scale, plain_E_ci);
        encryptor.encrypt(plain_E_ci, encrypt_E_ci);
        encrypt_E_matrix.push_back(encrypt_E_ci);
    }
    print_line(__LINE__);
    cout << "------get_encrypt_E_matrix() end------" << endl;

    return encrypt_E_matrix;
}

image-20210203124920149

将加密的databse数据做解密验证:

输出前4行:

image-20210203130122350


二: 计算 $\mathbf{r}{i}=\operatorname{dist}\left(\mathbf{p}, \mathbf{c}{i}\right) \cdot \mathbf{k}$

image-20210812102013754

分步骤:

image-20210812102034661

总代码调用:

code
vector<Ciphertext> get_dist(SEALContext& context,CKKSEncoder& ckks_encoder, Evaluator& evaluator, vector<Ciphertext> encrypt_E_matrix, Ciphertext probe_p,Encryptor & encryptor ,Decryptor& decryptor, RelinKeys& relin_keys,  GaloisKeys& galois_keys) {
    print_line(__LINE__);
    cout << "------get_dist() begin------" << endl;
    vector<Ciphertext> encrypt_R_matrix;

    /*
    * get (Ci - Pi)^2
    */
   
    cout << "sub & square && stored in encrypt_R_matrix: " << endl;
    vector<Ciphertext> encrypt_R_matrix_cache = get_sub_square(ckks_encoder, evaluator, decryptor,encrypt_E_matrix,probe_p, relin_keys);

    /*
    * get sum
    */
    encrypt_R_matrix = get_sum_rotate(context,ckks_encoder,evaluator,encryptor, decryptor, encrypt_R_matrix_cache,galois_keys,relin_keys);

    print_line(__LINE__);
    cout << "------get_dist() end------" << endl;
    return encrypt_R_matrix;
}

1:求 ${(C_{i} - P_{i})}^{2}$

code
vector<Ciphertext> get_sub_square(CKKSEncoder& ckks_encoder,Evaluator & evaluator,Decryptor & decryptor,vector<Ciphertext> encrypt_E_matrix, Ciphertext probe_p,RelinKeys & relin_keys) {
    
    print_line(__LINE__);
    cout << "------get_sub_square() begin------" << endl;
    
    vector<Ciphertext> encrypt_R_matrix;
    for (auto it = encrypt_E_matrix.begin(); it != encrypt_E_matrix.end(); it++) {

        Plaintext plain_sub_cache, plain_mult_cache;
        Ciphertext encrypt_sub_cache, encrypt_multiply_cache;
        vector<double>result_sub_cache, result_mult_cache;

        evaluator.sub(probe_p, (*it), encrypt_sub_cache);
        evaluator.relinearize_inplace(encrypt_sub_cache, relin_keys);

        evaluator.square(encrypt_sub_cache, encrypt_multiply_cache);
        
        evaluator.relinearize_inplace(encrypt_multiply_cache, relin_keys);
        evaluator.rescale_to_next_inplace(encrypt_multiply_cache);
         
        encrypt_R_matrix.push_back(encrypt_multiply_cache);

    }
    print_line(__LINE__);
    cout << "------get_sub_square() end------" << endl;
    return encrypt_R_matrix;
}

解码结果验证测试:

​ 1. $(C_{i} - P_{i})$结果:

image-20210203132236684

  1. ${(C_{i} - P_{i})}^{2}$结果:

    image-20210203133516381


2: $\sum_{i=0}{s}\left(\mathbf{c}_{i}-\mathbf{p}_{i}\right){2}$

image-20210812102107289

循环遍历encrypt_R_matrix, 将密文每次移位step步后加到encrypt_sum_cache上得到最终的结果,

step从0到number-1

code
vector<Ciphertext> get_sum_rotate(SEALContext &context,CKKSEncoder& ckks_encoder, Evaluator& evaluator,Encryptor &encryptor ,Decryptor& decryptor, vector<Ciphertext>encrypt_R_matrix,GaloisKeys & galois_keys,RelinKeys & relin_keys) {
    
    print_line(__LINE__);
    cout << "------get_sum_rotate() begin------" << endl;
    vector<Ciphertext> encrypt_RR_matrix;

    /*
    * get encryptor of vector K{1,0,0,....0}
    * begin
    */
    size_t slot_count = ckks_encoder.slot_count();
    vector<double>vector_k(slot_count, 0ULL);
    vector_k[0] = 1ULL;
    //print_vector(vector_k, 3, 13);

    Plaintext plain_vector_k;
    Ciphertext encrypt_vector_k;
    ckks_encoder.encode(vector_k, pow(2.0, 40), plain_vector_k);
    encryptor.encrypt(plain_vector_k, encrypt_vector_k);
    evaluator.mod_switch_to_next_inplace(encrypt_vector_k);
    //end

    /*
    *  Calculate begin
    */
    for (auto it = encrypt_R_matrix.begin(); it != encrypt_R_matrix.end(); it++) {

        Plaintext plain_rotated_cache, plain_sum_cache;
        Ciphertext encrypt_rotated_cache, encrypt_sum_cache;
        vector<double>result_rotated_cache, result_sum_cache;

        encrypt_sum_cache = (*it);
        /*
        * rotated & add to get sum of them
        */
        for (auto i = 0; i < number_n - 1; i++) {
            evaluator.rotate_vector(encrypt_sum_cache, 1, galois_keys, encrypt_rotated_cache);
            encrypt_sum_cache = encrypt_rotated_cache;
            evaluator.add_inplace(encrypt_sum_cache,(*it) );
            evaluator.relinearize_inplace(encrypt_sum_cache, relin_keys);

        }
        evaluator.multiply_inplace(encrypt_sum_cache, encrypt_vector_k);
        evaluator.relinearize_inplace(encrypt_sum_cache, relin_keys);
        evaluator.rescale_to_next_inplace(encrypt_sum_cache);
        encrypt_RR_matrix.push_back(encrypt_sum_cache);
    }
    /*
    *  Calculate end;
    */
    print_line(__LINE__);
    cout << "------get_sum_rotate() end------" << endl;
    return encrypt_RR_matrix;
}

解码结果验证测试(部分截取):

image-20210203140928407


3: 求 $\operatorname{dist}\left(\mathbf{p}, \mathbf{c}_{i}\right) \cdot \mathbf{k}$

代码内嵌在第二步求 2: $\sum_{i=0}{s}\left(\mathbf{c}_{i}-\mathbf{p}_{i}\right){2}$​中

image-20210812102208665

evaluator.multiply_inplace(encrypt_sum_cache, encrypt_vector_k);
evaluator.rescale_to_next_inplace(encrypt_sum_cache);
encrypt_RR_matrix.push_back(encrypt_sum_cache);

解码结果验证:

image-20210203140007458

三: 将得到 R 进行移位叠加操作:

image-20210812102120353

code
vector<Ciphertext> get_shifting_ri(SEALContext& context,CKKSEncoder& ckks_encoder,Evaluator& evaluator,vector<Ciphertext> encrypt_R_matrix, GaloisKeys& galois_keys, Decryptor& decryptor) {
    print_line(__LINE__);
    cout << "------get_shifting_ri() begin------" << endl;

    vector<Ciphertext> encrypt_RR_matrix;
    Plaintext plain_shift_cache;
    vector<double>result_shift_cache;
    
    int step = 0;
    for (auto it = encrypt_R_matrix.begin(); it != encrypt_R_matrix.end(); it++) {
        Ciphertext after_shift;
        // 右移
        evaluator.rotate_vector((*it),step, galois_keys,after_shift);
        step--;
        encrypt_RR_matrix.push_back(after_shift);
        
    }
    print_line(__LINE__);
    cout << "------get_shifting_ri() end------" << endl;
    return encrypt_RR_matrix;
}

解码结果验证测试;

输出前10列前10行, 保留13位小数

image-20210203162006063

四: 将得到 $R->\left(\mathbf{r}{1,1}, \mathbf{r}{2,1}, \ldots \mathbf{r}_{N, 1}\right)$:

通过移位操作得到对角矩阵后,将所有的$C_{i}$​ 累加起来得到$R->\left(\mathbf{r}{1,1}, \mathbf{r}{2,1}, \ldots \mathbf{r}_{N, 1}\right)$:

image-20210812102139359

code
Ciphertext get_combined_R(SEALContext& context,CKKSEncoder& ckks_encoder,Evaluator& evaluator, vector<Ciphertext> encrypt_R_matrix, Encryptor& encryptor, Decryptor& decryptor, RelinKeys& relin_keys) {
    print_line(__LINE__);
    cout << "------get_combined_R() begin------" << endl;
    
    Ciphertext encrypt_R_sum_cache;

    cout << " combined together: " << endl;
    int step = 0;
    for (auto it = encrypt_R_matrix.begin(); it != encrypt_R_matrix.end(); it++) {
        
        if (step == 0)
        {
            encrypt_R_sum_cache = (*it);
            step++;
            continue;
        }
        else {
            parms_id_type last_parms_id = (*it).parms_id();
            evaluator.add_inplace(encrypt_R_sum_cache, (*it));
            evaluator.relinearize_inplace(encrypt_R_sum_cache,relin_keys);
            step++;
        }
    }

    print_line(__LINE__);
    cout << "------get_combined_R() end------" << endl;
    return encrypt_R_sum_cache;
}

解密结果测试:

image-20210203183212079


最终结果展示

==注意!==

(因为没有用FaceNet缘故,这里给定的阈值 t 不得知,故程序只运行到将R做完对角化后并加在一起变成一个

$R->(r1,1, r2,1, . . . rN,1).$形式

若给定的设定的t已知; 则只需要做如下操作判定结果:

code
// d = R - t
Ciphertext encrypt_T,encrypt_d;
evaluator.sub(mapping_R,encrypt_T,encrypt_d);

// *d = Dec(d)
Plaintext plain_dd_cache;
vector<double>result_dd_cache;
decryptor.decrypt(encrypt_d, plain_dd_cache);
ckks_encoder.decode(plain_dd_cache, result_dd_cache);
// judge ∃d ∈ d∗: d > 0 ? accept : reject
bool ok = 0;
auto len = result_dd_cache.size();
for (auto i = 0; i < len; i++) {
    if (result_dd_cache[i] > 0) {
        ok = 1;
        break;
    }
}
string ans = ok ? "accept" : "reject";
cout << ans << endl; //输出最后结果

image-20210203183215036

评论吧



本站总访问量为 访客数为

鲁 ICP 备 20018157 号-1
Copyright 2021 - 2022 sizaif. All Rights Reserved