简单的ElGamal算法实现

ElGamal算法实现的难点在于,求大素数的本原根。

:创造是极客唯一的属性

一、算法介绍

ElGamal是公钥密码的一种,建立在模大素数的离散对数困难求解问题之上。
本文只关注ElGamal在加解密上的简单实现(你可以理解为验证),在签名、认证、密钥交换方面的应用不予考虑。
ElGamal加解密共分为三个模块:密钥生成、加密、解密。

  • 密钥生成
    在这里插入图片描述

  • 加密
    在这里插入图片描述

  • 解密
    在这里插入图片描述

说明:在这里,设定大素数p为强素数(即p=2*q+1,且q为大素数),并且最高150位。

二、代码实现

整个算法的难点在于大素数p的本原根的寻找。
通常情况下,我们求一个素数p的原根的方法是:从2开始往上逐一递增,直到找到一个数a,满足ap-1(mod p)==1且a(p-1)的各质因子(mod p)!=1,此时a即为p的一个原根。(注意:素数是一定存在原根的
但是此法放在大数的背景下就黔驴技穷了,因为时间复杂度太高了!!!
你会急得满头大汗:本原根可是加密的前提。
江山代有才人出,真正的极客能够从0到1,解决别人解决不了的问题,比如咱们的Whitefield与Martin Hellman两位老先生,“别急,先坐下来喝杯茶,关于强素数本原根问题,我们已经解决了!”
算法给出的p是强素数,而著名的DH算法恰好解决了这个问题:正如其所说的,要寻找大强素数的本原根,只需满足两个条件。这样一来,速度就提上去了。

关键代码如下:

  1. 变量定义
    在这里插入图片描述
  2. 密钥生成
//密钥生成
	printf("First,let's generate the key!\n");
	irand((int)time(NULL));
	//key_generate:1,generate prime p
	while (1) {// according D-H algorithm,i can find g more quickly.
		while (1) {
			bigdig(N, 10, temp2);
			if (isprime(temp2))
				break;
		}
		fft_mult(two, temp2, p);
		incr(p, 1, p);
		if (isprime(p))
			break;
	}

	//key_generate:2.find g
	decr(p, 1, temp3);
	while (1) {
		bigrand(temp3, g);
		if (compare(g, one)) {
			powmod(g, two, p, temp1);
			if (compare(temp1, one)) {
				powmod(g,temp2, p, temp1);// here temp2=(p-1)/2
				if (compare(temp1, one))
					break;
			}
		}
	}

	//key_generate:3.generate private key x
	decr(p, 2, temp2);
	//irand((int)time(NULL));
	while (1) {
		//irand((int)time(NULL));
		bigrand(temp2,x);
		if (compare(x, one))
			break;
	}

	//key_generate:4.then computing y
	powmod(g, x, p, y);

  1. 随机产生测试明文m并加密
    在这里插入图片描述
  2. 解密
    在这里插入图片描述

这里还需要提到的一点是,在解密算法中,y1-x(mod p)等价于y(-1)x(mod p),而y-1是指y模p的逆。

三、结果截图

在p为150位的情况下,从密钥生成到加密,再到解密整个过程耗时一分钟左右(反复测了几次),这个结果还可以接受。(我记得第一次测试的时候十秒就跑出来了,What happened?
在这里插入图片描述

发布了24 篇原创文章 · 获赞 19 · 访问量 6895

猜你喜欢

转载自blog.csdn.net/tch3430493902/article/details/103208539