使用NTL库实现Paillier算法

思路

两种构造函数,一种是传入p和q的,一种是没有传参的,p和q靠程序生成。
得到p和q之后,设置密钥相关变量,n=p*q、lambda=lcm(p-1,q-1),对于长度相等的p和q来说,使用g=n+1可以快速生成密钥。
在生成密钥的过程中,通过查阅资料,有些资料上私钥为两部分,lambda和mu,mu可有lambda、g和n在后续解密过程中算出

结果

结果


代码

main.cpp

#include <iostream>

#include "Paillier.h"

using namespace std;
using namespace NTL;


void test(Paillier p,ZZ m)
{
	cout << "public key: (" << p.getN()<< ", "<< p.getG() << ")" << endl;
	cout << "private key: "<<p.getLam()<< endl;
	cout << "message: "<< m << endl;
	
	ZZ c = p.encrypt(m);		//加密
	ZZ em = p.decrypt(c);
	cout << "\nencrypt: "<< c << endl;
	cout << "decrypt: "<< em << endl;	//解密 
	
	if(em == m)
		cout<<"\nsucess!"<<endl;
	else
		cout<<"\nwrong!"<<endl;
	cout<<"-------------------------"<<endl;
}

int main(int argc, char** argv) {
	ZZ p = ZZ(43), q = ZZ(41);
	ZZ m = ZZ(12);//加密信息
	
//	cout<<"please input p q m: ";
//	cin>>p>>q>>m;	//输入 
	
	Paillier p1 = Paillier(p, q);
	test(p1,m);
	
	Paillier p2 = Paillier();
	test(p2,m);
	return 0;
}

Paillier.h

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

using namespace NTL;

class Paillier {
public:
	Paillier();
	Paillier(ZZ, ZZ);

	void createPQ();
	void init();
	void createG();			
	ZZ L(ZZ);
	ZZ getRandom();		//产生随机数 
	ZZ encrypt(ZZ);		//加密
	ZZ decrypt(ZZ);		//解密

	ZZ getP();
	ZZ getQ();
	ZZ getN();
	ZZ getG();
	ZZ getLam();
	
private:
	ZZ p;
	ZZ q;
	ZZ n;
	ZZ g;
	ZZ lambda;
//	ZZ mu;	//本来作为私钥一部分,可又lambda、g和n求得 
};

Paillier.cpp

#include "Paillier.h"

using namespace std;
using namespace NTL;

Paillier::Paillier()
{
	createPQ();
//	cout<<"P :"<<p<<"\tQ:"<<q<<endl;
	init();
}

Paillier::Paillier(ZZ p, ZZ q)
{
	this->p = p;
	this->q = q;
	init();
}

void Paillier::init()	//初始化,生成密钥 
{
	n = p * q;
	lambda = ((p - 1) * (q - 1)) / GCD(p - 1, q - 1);	//lcm
	createG();
//	g = n + 1;	//pq两个质数长度相同的情况下,可以快速生成密钥 
}

void Paillier::createPQ()	//产生两个大素数 长度相等 
{
	long length = 32;	//长度bit 
	while (true)
	{
		p = GenPrime_ZZ(length, 80);
		q = GenPrime_ZZ(length, 80);

		while (p == q)
		{
			q = GenPrime_ZZ(length, 80);
		}
		if (GCD(p * q, (p - 1) * (q - 1)) == 1)
			return;
	}
}

//	产生g 
void Paillier::createG()
{
	while (1)
	{
		g = RandomBnd(n * n);
		if (g <= 0)
			continue;
		if (GCD(L(PowerMod(g, lambda, n * n)), n) == 1)
			return;
	}
}


ZZ Paillier::L(ZZ mu)
{
	return (mu - 1) / n;
}

ZZ Paillier::getRandom()
{
	ZZ r;
	while (1)
	{
		r = RandomBnd(n);
		if (GCD(r, n) == 1)
			return r;
	}
}

ZZ Paillier::encrypt(ZZ m)
{
	ZZ r = getRandom();	//随机数 
//	ZZ r=ZZ(131);	//测试用例 
	return (PowerMod(g, m, n * n) * PowerMod(r, n, n * n)) % (n * n);

}

ZZ Paillier::decrypt(ZZ c)
{
	ZZ mu = InvMod(L(PowerMod(g, lambda, n * n)), n);	//mu 在有的文献中,mu作为私钥的一部分 
	return (L(PowerMod(c, lambda, n * n)) * mu) % n;

//	return (L(PowerMod(c, lambda, n * n)) * InvMod(lambda, n)) % n;	//如果g=n+1 可用这种简便方法 
}


ZZ Paillier::getLam() {
	return lambda;
}

ZZ Paillier::getP() {
	return p;
}

ZZ Paillier::getQ() {
	return q;
}

ZZ Paillier::getN() {
	return n;
}

ZZ Paillier::getG() {
	return g;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值