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算法恰好解决了这个问题:正如其所说的,要寻找大强素数的本原根,只需满足两个条件。这样一来,速度就提上去了。
关键代码如下:
扫描二维码关注公众号,回复:
8727015 查看本文章
- 变量定义
- 密钥生成
//密钥生成
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);
- 随机产生测试明文m并加密
- 解密
这里还需要提到的一点是,在解密算法中,y1-x(mod p)等价于y(-1)x(mod p),而y-1是指y模p的逆。
三、结果截图
在p为150位的情况下,从密钥生成到加密,再到解密整个过程耗时一分钟左右(反复测了几次),这个结果还可以接受。(我记得第一次测试的时候十秒就跑出来了,What happened?