现代密码学实验5 数字签名ElGamal签名方案

赞赏码 & 联系方式 & 个人闲话

【实验名称】数字签名ElGamal签名方案

 

【实验目的】

1、了解数字签名的过程,包括签名过程和认证过程;

2、掌握ElGamal签名方案。

 

【实验原理】

ElGamal公钥密码算法是在密码协议中有着重要应用的一类公钥密码算法,它是基于1985年提出的公钥密码体制和椭圆曲线加密体系,其安全性是基于有限域上离散对数学问题的难解性。它至今仍是一个安全性良好的公钥密码算法。它既可用于加密又可用于数字签名的公钥密码体制。

数字签名就是附加在数据单元上的一些数据,或是对数据单元所作的密码变换。这种数据或变换允许数据单元的接收者用以确认数据单元的来源和数据单元的完整性并保护数据,防止被人(例如接收者)进行伪造。

 

【实验内容】

实验内容: 生成各自的密钥,并公布给相邻同学自己的公钥(p,g,y),A和B之间约定签署的消息m(如学号),A签署消息m,将三元组(m,r,s)发给B,B验证签名。

代码:(代码解释见代码中注释)

#include<iostream>
#include<time.h>
using namespace std;
#define  LL long long

//幂次运算,含模运算,防止溢出
LL My_Pow(LL a, LL m, LL input)
{
	LL result = 1;
	for (LL i = 0; i < m; i++)
	{
		result = (result*a) % input;
	}
	return result;
}

//用辗转相除法求最大公约数
LL gcd(LL a, LL b)
{
	LL temp = b;
	while (a%b != 0)
	{
		temp = a % b;
		a = b;
		b = temp;
	}
	return temp;
}

//扩展欧几里得法,递归法
LL extend(LL a, LL b, LL&x, LL&y)
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	LL r = extend(b, a % b, x, y);
	LL t = x;
	x = y;
	y = t - a / b * y;
	return r;
}

//借助递归扩展欧几里得求逆
LL inv(LL a, LL b)
{
	LL x, y;
	LL r = extend(a, b, x, y);
	if (r != 1)
	{
		return 0;
	}
	x = x % b;
	if (x < 0)
	{
		x = x + b;
	}
	return x;
}


int main()
{
	//密钥产生
	cout << "***   密钥产生环节   ***" << endl;
	LL p, g;
	cout << "请输入大素数p和本原根g:";
	cin >> p >> g;
	srand((unsigned)time(NULL));
	LL x = 0;
	while (x <= 0)
	{
		x = rand() % (p - 1);
	}
	cout << "秘密整数x随机选择完毕" << endl;
	LL y = My_Pow(g, x, p);
	cout << "公钥计算完毕" << endl;
	cout << "公钥为:(" << p << "," << g << "," << y << ")" << endl;

	//数字签名
	LL m;
	cout << "\n***   数字签名环节   ***" << endl;
	cout << "请输入签名消息m:";
	cin >> m;
	LL k = 0;
	while (gcd(k, p - 1) != 1 || k <= 0)
	{
		k = rand() % (p - 1);
	}
	cout << "安全随机数k选择完毕" << endl;
	LL r = My_Pow(g, k, p);
	//cout << k<<" "<<inv(k, p-1) << (m - x * r)<<endl;
	LL s = inv(k, p - 1)*(m - x * r) % (p - 1);
	//cout << s << endl;
	if (s < 0)
	{
		s = s + p - 1;
	}
	cout << "签署消息生成完毕" << endl;
	cout << "签署消息为:(" << m << "," << r << "," << s << ")" << endl;

	cout << "\nA将签名传送给B" << endl;

	//签名验证
	cout << "\n***   签名验证环节   ***" << endl;
	cout << "请输入收到的签署消息:";
	cin >> m >> r >> s;
	LL temp1, temp2;
	temp1 = My_Pow(y, r, p);
	temp2 = My_Pow(r, s, p);
	LL v1 = (temp1 * temp2) % p;
	LL v2 = My_Pow(g, m, p);
	cout << "开始验证..." << endl;
	cout << "结果:v1 = " << v1 << "  v2 = " << v2 << endl;
	if (v1 == v2)
	{
		cout << "经验证,该签名有效\n" << endl;
	}
	else
	{
		cout << "请注意签名已失效!\n" << endl;
	}

	return 0;
}

运行演示:

 

【小结或讨论】

这次实验总体难度不是很大,我觉得重要的是理解ElGamal加密算法和数字签名算法。密码学的很多加密算法都对离散数学有着很高的要求,但是这一部分又是十分抽象晦涩的,即使我们学过离散数学和信息安全数学基础,对密码学里的很多算法理解上也是会遇到不小的困难的,所以这就需要反复琢磨,仔细思考,而且还需要时常温习。

这次算法其实比之前的加密算法要容易懂一些,我觉得ElGamal设计的十分巧妙,利用了有限域上离散对数的困难性,通过模数的逆在双方都不知道具体密钥数值的情况下,却能实现秘密信息的准确传达,而且利用的还是随机密钥,这就意味着即使相同的明文加密后的密文每次也是不一样的,这又进一步加强了算法的安全性。

  • 10
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值