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); 
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM