Paillier同态加密的介绍以及c++实现

我们先来简短认识一下Paillier同态加密算法:

 

 

如果就这么按照定义来用最简朴的c++程序写 就像这样:

#include <iostream>
#include <math.h> 
#include   <stdlib.h>      
#include   <time.h>   
#include<cmath>
#define MIN 32768    //随机数产生的范围      
#define MAX 65536  

using namespace std;
int p, q;

bool judgeprime(int i) {
    int j;
    for (j = 2; j <= sqrt(i); j++)
        if (i % j == 0)
            break;
    if (j > sqrt(i))
        return true;
}

int gcd(int a, int b)///辗转相除法求最大公约数 最朴实的求法
{

    int t = a;
    while (a % b)
    {
        a = b;
        b = t % b;
        t = a;
    }
    return b;
}
int lcm(int a,int b)
{
    return a * b / gcd(a, b);
}



void get2prime()
{
    srand((unsigned)time(NULL));
    while (1)
    {
        p = MIN + (rand() % (MAX - MIN));
        q = MIN + (rand() % (MAX - MIN));
        if (gcd(p * q, (p - 1) * (q - 1)) == 1 && judgeprime(p) && judgeprime(q))
            break;

    }
    
}
int N;
int Lfun(int x)
{
    int b; b = (x - 1) / N;
    return b;
}


int main()
{
   
    get2prime();
    N = p*q;
    cout << "p:" << p << "  " << "q:" << q << endl;
    int lan;
    lan = lcm(p - 1, q - 1);
    int g = 0;
    int k;
    k = Lfun( int (pow(g, lan)) % (N * N));
    srand((unsigned)time(NULL));
    while (1)
    {
        g = rand() % (N * N);

        if (gcd(k, N) == 1)
            break;

    }
    cout << "算法公钥为 " << g << " ," << N << endl;

    
}

这个代码当时写错了 

当时没有系统学习数论 对于乘法群  生成元 循环群的理解有差错

不过先不影响这个

 

得...这时间复杂度...

光这个公钥就跑不出来

但是怎么去缩小时间复杂度 至今没有办法

去gayhub找了找别人的代码 这没办法 我真 不知道有NTL这玩意 这个只能自己多敲代码多实践才能发现

 

原来 c++还有一种便携结构和算法库 叫做NTL

可实现任意长度的整数,向量,矩阵和整系数多项式和有限域上的运算。

在当前平台支持C++11,NTL可以编译线程安全的异常安全模式

说白了就是一个C++的非标准外部库文件。要使用的的话得自己编译安装。一般利用C++实现某些公钥密码算法会用到,可以提高运算效率。实现全同态密码算法会常用到。

所以对于应用密码学来说 还挺有用的!
 
这个NTL 不是标准库中的 所以要自己装 同时 你找c reference也是找不到注解的
安装教程:https://www.jianshu.com/p/cfe0a8072be7
 
 
然后 看一下代码的实现
以下是主程序main.cpp:
#include <iostream>
#include <math.h>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

#include "paillier.h"

using namespace std;
using namespace NTL;

ZZ lcm(ZZ x, ZZ y){
  ZZ ans = (x * y) / NTL::GCD(x,y);
  return ans;
}

int main()
{

    ZZ p = ZZ(43);
    ZZ q = ZZ(41);
    ZZ lambda = lcm(p - 1, q - 1);
    Paillier paillier(p*q, lambda);

    ZZ m = ZZ(10);
    ZZ n = p * q;

    cout << "p = " << p << endl;
    cout << "q = " << q << endl;
    cout << "n = " << n << endl;
    cout << "lamdba = " << lambda << endl;

    ZZ c = paillier.encrypt(m, (ZZ)131 );
    cout << "c = " << c << endl;
    ZZ m2 = paillier.decrypt(c);
    cout << "m2 = " << m2 << endl;

    if (m == m2){
        cout << "m = m2, encryption and decryption successful" << endl;
    }

    return 0;
}

以下是

paillier.cpp文件

#include "paillier.h"

NTL::ZZ generateCoprimeNumber(const NTL::ZZ& n) {
    NTL::ZZ ret;
    while (true) {
        ret = RandomBnd(n);
        if (NTL::GCD(ret, n) == 1) { return ret; }
    }
}

Paillier::Paillier() {
    /* Length in bits. */
    long keyLength = 512;
    NTL::ZZ p, q;
    GenPrimePair(p, q, keyLength);
    modulus = p * q;
    generator = modulus + 1;
    NTL::ZZ phi = (p - 1) * (q - 1);
    // LCM(p, q) = p * q / GCD(p, q);
    lambda = phi / NTL::GCD(p - 1, q - 1);
    lambdaInverse = NTL::InvMod(lambda, modulus);
}

Paillier::Paillier(const NTL::ZZ& modulus, const NTL::ZZ& lambda) {
    this->modulus = modulus;
    generator = this->modulus + 1;
    this->lambda = lambda;
    lambdaInverse = NTL::InvMod(this->lambda, this->modulus);
}

void Paillier::GenPrimePair(NTL::ZZ& p, NTL::ZZ& q,
                               long keyLength) {
    while (true) {
        long err = 80;
        p = NTL::GenPrime_ZZ(keyLength/2, err); 
        NTL::ZZ q = NTL::GenPrime_ZZ(keyLength/2, err);
        while (p != q) {
            q = NTL::GenPrime_ZZ(keyLength/2, err);
        }
        NTL::ZZ n = p * q;
        NTL::ZZ phi = (p - 1) * (q - 1);
        if (NTL::GCD(n, phi) == 1) return;
    }
}

NTL::ZZ Paillier::encrypt(const NTL::ZZ& message) {
    NTL::ZZ random = generateCoprimeNumber(modulus);
    NTL::ZZ ciphertext = 
        NTL::PowerMod(generator, message, modulus * modulus) *
        NTL::PowerMod(random, modulus, modulus * modulus);
    return ciphertext % (modulus * modulus);
}

NTL::ZZ Paillier::encrypt(const NTL::ZZ& message, const NTL::ZZ& random) {
    NTL::ZZ ciphertext = 
        NTL::PowerMod(generator, message, modulus * modulus) *
        NTL::PowerMod(random, modulus, modulus * modulus);
    return ciphertext % (modulus * modulus);
}


NTL::ZZ Paillier::decrypt(const NTL::ZZ& ciphertext) {
    /* NOTE: NTL::PowerMod will fail if the first input is too large
     * (which I assume means larger than modulus).
     */
    NTL::ZZ deMasked = NTL::PowerMod(
            ciphertext, lambda, modulus * modulus);
    NTL::ZZ power = L_function(deMasked);
    return (power * lambdaInverse) % modulus;
}

 

 
 

 以下是paillier.h文件

#include <NTL/ZZ.h>
#include <NTL/ZZ_pXFactoring.h>

class Paillier {
    public:
    /* Completely generate everything, from scratch */
    Paillier();
    Paillier(const NTL::ZZ& modulus, const NTL::ZZ& lambda); 
    //Paillier(path to public key, path to private key).

    /* Paillier encryption function. Takes in a message from the
     * integers modulo n (Paillier.modulus) and returns a message in
     * the integers modulo n**2.
     *
     * Parameters
     * ==========
     * NTL::ZZ message : The message to encrypt, as a number.
     *
     * Returns
     * =======
     * NTL:ZZ ciphertext : The encyrpted message.
     */
    NTL::ZZ encrypt(const NTL::ZZ& message); 

    /* Paillier encryption function with provided randomness, if user
     * wants to provide their own randomness.
     *
     * Random number should be coprime to modulus.
     *
     * Parameters
     * ==========
     * NTL::ZZ message : The message to encrypt, as a number.
     * NTL::ZZ random : The random mask.
     *
     * Returns
     * =======
     * NTL:ZZ ciphertext : The encyrpted message.
     */
    NTL::ZZ encrypt(const NTL::ZZ& message, const NTL::ZZ& random); 

    /* Paillier decryption function. Takes in a cipertext from Z mod
     * n**2 and returns a message in the Z mod n.
     *
     * Parameters
     * ==========
     * NTL::ZZ cipertext : The encrypted message.
     *
     * Returns
     * =======
     * NTL::ZZ message : The original message.
     */
    NTL::ZZ decrypt(const NTL::ZZ& ciphertext); 

    private:
    /* modulus = pq, where p and q are primes */
    NTL::ZZ modulus;
    NTL::ZZ generator;
    NTL::ZZ lambda;
    NTL::ZZ lambdaInverse;

    /* The L function in the paillier cryptosystem.  See
     * <https://en.wikipedia.org/wiki/Paillier_cryptosystem> for more
     * details.
     *
     * Parameters
     * ==========
     * NTL::ZZ x : The argument to L.
     * NTL::ZZ n : The paillier modulus.
     *
     * Returns
     * =======
     * NTL::ZZ result : (x - 1) / n
     */
    NTL::ZZ L_function(const NTL::ZZ& n) { return (n - 1) / modulus; }

    void GenPrimePair(NTL::ZZ& p, NTL::ZZ& q, long keyLength); 
};

 

posted @ 2020-09-11 21:35  然终酒肆  阅读(711)  评论(0编辑  收藏