我们先来简短认识一下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); };