xd信息安全数学基础密码学实验-4 ElGamal公钥密码算法


这个好像是最后一个实验了,同学们可以看一下以往的实验题目。

一、基础知识原理

这个EIGamal公钥加密算法其实非常有意思,但是我太菜了,我啥也不会。我除了说卧槽牛逼666也不会说啥了。
ppt我也截图下来了,突然想到同学们可能在写实验报告的时候公式可能不大好写,我这里也给出来吧。不想写公式的可以截个图啥的。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
总体就分为三步密钥生成、加密、解密。

难点主要在于随机数g的生成,也就是求p的原根,这里通过翻各种求原根算法,终于找到了DH算法,DH算法用到了一个卧槽牛逼666的公式,能够很方便的求出模p的原根,即g若满足如下条件

在这里插入图片描述

则说明是g是 mod p的一个原根。
可以看这篇博客:
https://blog.csdn.net/borsyu/article/details/8240666

二、算法实现

1.环境

使用的是vc 6++ 和miracl大整数库。
资源见之前的博客。

2.Miracl库函数说明

	1powmod2(v,one,c2,one,p,res);// res = v*c2 mod p
	//感谢学长倾情相助的好函数。
	

这个是我在编程的时候遇到的一个坑。
在求C2时,有用到模p之下的乘积,就是
在这里插入图片描述
这里,因为当时不知好函数,只能先分别求模,再求乘积,然后再模p得到C2。

P.S.这个感觉代码的时间复杂度可能有点太高了,我的渣机子得跑十多秒才能找到p、q、g这几个随机数。
但是剩下的几个随机数好像找起来挺快的。

3.主要代码

代码如下:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include"miracl.h"
#define N 150

int main()
{
    FILE *fp;
	miracl *mip = mirsys(90000, 10);
    int i = 0;
	int j = 0;
	int flag = 1;
    big p = mirvar(1);//随机数
    big p1 = mirvar(0);//p-1    
    big p2 = mirvar(0);//p-2
    big q = mirvar(1);//随机数q p = 2q + 1
    big g = mirvar(1);//随机数
    big a = mirvar(1);//随机数
    big y = mirvar(1);//随机数
    big c1 = mirvar(1);
    big c1_1 = mirvar(1);// c1^-1
    big c2 = mirvar(1); 
    big k = mirvar(1);//随机数
    big v = mirvar(0);
    big res = mirvar(0);
	big temp = mirvar(0);
    big temp1 = mirvar(0);
    big temp2 = mirvar(0);
	big m = mirvar(1);//明文
	big one = mirvar(1);
    big two = mirvar(2);
    
    fp = fopen("secret3.txt","r");
	if (fp == NULL)
	{
		printf("FILE ERROR\n");
		return 0;
	}
    else
    {
        cinnum(m, fp);
		printf("明文");
        printf("\n------------------------------------------------------------------\n");
        cotnum(m,stdout);
        printf("------------------------------------------------------------------\n");
    }    
    fclose(fp);

    //密钥生成
    //p、q生成
    while(flag){
        bigdig(150,10,q);
        if(isprime(q)){
            multiply(q,two,p);
            add(p,one,p);
            if(isprime(p)&&(numdig(p)==150))
                flag = 0;//p = 2*q + 1 qiang  su shu
        }
        else 
            flag = 1;
    }
    //g生成
    flag = 1;
    copy(p,temp);//temp = p
    decr(p,1,p1); //temp-1
    while(flag){
        bigdig(150,10,g);
        if((compare(p1,g)==1)&&(compare(g,one)==1)){//p-1<g  g>one
            powmod(g,two,p,temp1);//g^2 mod p!=1 且 g ^ q mod p!=1
            powmod(g,q,p,temp2);
            if(compare(temp1,one)&&compare(temp2,one))
                flag = 0;
            else 
                flag = 1;
        }
    }

    decr(p,2,p2); //temp-1
    //生成私钥a
    while (1){
	    bigrand(p2,a);//a<p-2
		if (compare(a,one) > 0)//a>1
			break;
    }
    powmod(g, a, p, y);//y = g^a mod p

    printf("公钥p、g、y");
    printf("\n------------------------------------------------------------------\n");
	cotnum(p, stdout);
	cotnum(g, stdout);
	cotnum(y, stdout);
    printf("------------------------------------------------------------------\n");
    printf("私钥a");
    printf("\n------------------------------------------------------------------\n");
    cotnum(a,stdout);
    printf("------------------------------------------------------------------\n");

    //加密
    //k生成
    while(1){
        bigdig(150,10,k);
        egcd(k,p1,temp);
        if(compare(p1,k)==1&&compare(one,temp)==0)//p-1>k (k,p-1)=1
            break;
    }

    powmod(g,k,p,c1);// y1 = g^k mod p  加密k=c1
    powmod(y,k,p,temp); //temp = y^k mod p
    powmod(m,one,p,temp1);
    multiply(temp1,temp,temp2);
    powmod(temp2,one,p,c2);//c2 = m*y^k mod p
    printf("密文c1、c2");
    printf("\n------------------------------------------------------------------\n");
    cotnum(c1, stdout);
	cotnum(c2, stdout);
    printf("------------------------------------------------------------------\n");

    //解密
    xgcd(c1,p,temp,temp,temp);//temp = c1^-1 mod p
    //xgcd(x,p,z,z,z);   z = x^-1 mod p => z*x = 1 mod p
    powmod(temp,a,p,v);//v = (c1^-1)^a mod p
	powmod(c2,one,p,c2);//c2 = c2 mod p
	//powmod2(v,one,c2,one,p,res);// res = v*c2 mod p
    //可以求 m*y^k mod p
    multiply(v,c2,temp2);
    powmod(temp2,one,p,res);//res = v*c2 mod p
	
    printf("解密后的明文");
    printf("\n------------------------------------------------------------------\n");
    cotnum(res, stdout);
    printf("------------------------------------------------------------------\n");

    if(compare(res,m)==0)
        printf("恢复明文和原明文相同\n");
    else
        //pritnf("失败");
    
    mirexit(); //清除MIRACL系统,释放所有的内部变量
    getchar();
    return 0;   
}

在这里插入图片描述

三、总结

这个是此课程的第四个实验,经过了这么四个实验,感觉代码一个比一个长,一想到还有一个什么大作业,心情稀碎。
总而言之,这四个实验我都上传到CSDN了,所有代码也都给了。
希望大家给我点个赞啊!!!!!!!!!!!!!!!!!!!!!

  • 31
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值