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

 

一、ElGamal公钥密码算法描述

1. 选取一个大素数p,使离散对数问题在有限域GF(p)上是难解的,选取g∈Z是一个本原元。

2. 随机选取整数x,1≤x≤p-2,计算y=g^x(mod p); y是公开的加密密钥,而x是保密的脱密密钥。

3. 明文空间为Z,密文空间为Z×Z。

4. 加密变换:对任意明文m∈Z,秘密地随机选取一个整数k,1≤k≤p-2,于是可得密文为:

c=(c1,c2)

其中

c1=g^k(mod p) , c2=my^k(mod p)

5. 脱密变换:对任意密文c=(c1,c2)∈Z×Z,明文为:

m=c2×(c1^x)^-1(mod p)

证明:

c2×(c1^x)^-1(mod p)=my^k(g^(kx))^-1 (mod p)

=mg^kx × g^(-kx) (mod p)=m (mod p)

二、ElGamal数字签名方案

1. 生成乘法群Z中的一个生成元g,p,g公开。

2. 随机选取整数x,1≤x≤p-2,计算y=g^x(mod p),y是公开密钥,而x是保密密钥。

3. 签名算法:设m∈Z是待签名的消息,秘密随机选取一个整数k,1≤k≤p-2,且(k,p-1)=1,计算

r=g^k(mod p)

s=k^-1(m-rx)(mod p-1)

则(m,r,s)为对消息m的数字签名。

4. 验证算法:对方收到对消息m的数字签名(m,r,s)后,利用签名者的公开密钥y,g,p可对签名进行以下验证:

(y^r)(r^s)=g^m(mod p)

如果上式成立,则接受该签名,否则拒绝该签名。

对m正确签名,那么有:

(y^r)(r^s)(mod p)=g^(rx+sk)(mod p)

=g^(rx+m-rx)(mod p)

=g^m (mod p)

三、ElGamal数字签名方案实现

为简化问题,我们取p=19,g=2,私钥x=9,则公钥y=29 mod 19=18。C++代码实现如下:

BigInt.h

#ifndef BIGINT_H_INCLUDED
#define BIGINT_H_INCLUDED
#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>//reverse函数所需添加的头文件
using namespace std;
/*
大整数类
*/
class BigInt
{
private:inline int compare(string s1, string s2){if(s1.size() < s2.size())return -1;else if(s1.size() > s2.size())return 1;elsereturn s1.compare(s2);}
public:bool flag;//true表示正数,false表示负数,0默认为正数string values;//保存所有位上的数字BigInt():values("0"),flag(true){};//构造函数BigInt(string str)//类型转换构造函数(默认为正整数){values = str;flag = true;}
public:friend ostream& operator << (ostream& os, const BigInt& bigInt);//重载输出操作符friend istream& operator>>(istream& is, BigInt& bigInt);//输入操作符重载BigInt operator+(const BigInt& rhs);//加法操作重载BigInt operator-(const BigInt& rhs);//减法操作重载BigInt operator*(const BigInt& rhs);//乘法操作重载BigInt operator/(const BigInt& rhs);//除法操作重载BigInt operator%(const BigInt& rhs);//求余操作重载
};
/*
重载流提取运算符'>>',输出一个整数
*/
ostream& operator << (ostream& os, const BigInt& bigInt)
{if (!bigInt.flag){os << '-';}os << bigInt.values;return os;
}
/*
重载流插入运算符'>>',输入一个正整数
*/
istream& operator >> (istream& is, BigInt& bigInt)
{string str;is >> str;bigInt.values = str;bigInt.flag = true;return is;
}
/*
两个正整数相加
*/
BigInt BigInt::operator+(const BigInt& rhs)
{BigInt ret;ret.flag = true;//正整数相加恒为正数string lvalues(values), rvalues(rhs.values);//处理特殊情况if (lvalues == "0"){ret.values = rvalues;return ret;}if (rvalues == "0"){ret.values = lvalues;return ret;}//调整s1与s2的长度unsigned int i, lsize, rsize;lsize = lvalues.size();rsize = rvalues.size();if (lsize < rsize){for (i = 0; i < rsize - lsize; i++)//在lvalues左边补零{lvalues = "0" + lvalues;}}else{for (i = 0; i < lsize - rsize; i++)//在rvalues左边补零{rvalues = "0" + rvalues;}}//处理本质情况int n1, n2;n2 = 0;lsize = lvalues.size();string res = "";reverse(lvalues.begin(), lvalues.end());//颠倒字符串,以方便从低位算起计算reverse(rvalues.begin(), rvalues.end());for (i = 0; i < lsize; i++){n1 = (lvalues[i] - '0' + rvalues[i] - '0' + n2) % 10;//n1代表当前位的值n2 = (lvalues[i] - '0' + rvalues[i] - '0' + n2) / 10;//n2代表进位res = res + char(n1 + '0');}if (n2 == 1){res = res + "1";}reverse(res.begin(), res.end());ret.values = res;return ret;
}
/*
两个正整数相减
*/
BigInt BigInt::operator-(const BigInt& rhs)
{BigInt ret;string lvalues(values), rvalues(rhs.values);//负数减负数if(flag==false&&rhs.flag==false){string tmp = lvalues;lvalues = rvalues;rvalues = tmp;}//负数减正数if(flag==false&&rhs.flag==true){BigInt res(lvalues);ret=res+rhs;ret.flag = false;return ret;}if(flag==true&&rhs.flag==false){BigInt rel(lvalues),res(rhs.values);ret=rel+res;ret.flag = true;return ret;}//处理特殊情况if (rvalues == "0"){ret.values = lvalues;ret.flag = true;return ret;}if (lvalues == "0"){ret.values = rvalues;ret.flag = false;return ret;}//调整s1与s2的长度unsigned int i, lsize, rsize;lsize = lvalues.size();rsize = rvalues.size();if (lsize < rsize){for (i = 0; i < rsize - lsize; i++)//在lvalues左边补零{lvalues = "0" + lvalues;}}else{for (i = 0; i < lsize - rsize; i++)//在rvalues左边补零{rvalues = "0" + rvalues;}}//调整使‘-’号前边的数大于后边的数int t = lvalues.compare(rvalues);//相等返回0,str1<str2返回负数,str1>str2返回正数if (t < 0){ret.flag = false;string tmp = lvalues;lvalues = rvalues;rvalues = tmp;}else if (t == 0){ret.values = "0";ret.flag = true;return ret;}else{ret.flag = true;}//处理本质情况unsigned int j;lsize = lvalues.size();string res = "";reverse(lvalues.begin(), lvalues.end());//颠倒字符串,以方便从低位算起计算reverse(rvalues.begin(), rvalues.end());for (i = 0; i < lsize; i++){if (lvalues[i] < rvalues[i])//不足,向前借一维{j = 1;while(lvalues[i+j] == '0'){lvalues[i+j] = '9';j++;}lvalues[i+j] -= 1;res = res + char(lvalues[i] + ':' - rvalues[i]);}else{res = res + char(lvalues[i] - rvalues[i] + '0');}}reverse(res.begin(), res.end());res.erase(0, res.find_first_not_of('0'));//去掉前导零ret.values = res;return ret;
}/*
两个正整数相乘
*/
BigInt BigInt::operator*(const BigInt& rhs)
{BigInt ret;string lvalues(values), rvalues(rhs.values);//处理0或结果正负if (lvalues == "0" || rvalues == "0"){ret.values = "0";ret.flag = true;return ret;}if(flag==false||rhs.flag==false){ret.flag=false;}//处理特殊情况unsigned int lsize, rsize;lsize = lvalues.size();rsize = rvalues.size();string temp;BigInt res, itemp;//让lvalues的长度最长if (lvalues < rvalues){temp = lvalues;lvalues = rvalues;rvalues = temp;lsize = lvalues.size();rsize = rvalues.size();}//处理本质情况int i, j, n1, n2, n3, t;reverse(lvalues.begin(), lvalues.end());//颠倒字符串reverse(rvalues.begin(), rvalues.end());for (i = 0; i < rsize; i++){temp = "";n1 = n2 = n3 = 0;for (j = 0; j < i; j++){temp = temp + "0";}n3 = rvalues[i] - '0';for (j = 0; j < lsize; j++){t = (n3*(lvalues[j] - '0') + n2);n1 = t % 10;//n1记录当前位置的值n2 = t / 10;//n2记录进位的值temp = temp + char(n1 + '0');}if (n2){temp = temp + char(n2 + '0');}reverse(temp.begin(), temp.end());itemp.values = temp;res = res + itemp;}ret.values = res.values;return ret;
}
/*
两个正整数相除
*/
BigInt BigInt::operator/(const BigInt& rhs)
{BigInt ret;string lvalues(values), rvalues(rhs.values);string quotient;string temp;//处理特殊情况if(rvalues == "0"){ret.values = "error";//输出错误ret.flag = true;return ret;}if(lvalues == "0"){ret.values = "0";ret.flag = true;return ret;}if(compare(lvalues, rvalues) < 0){ret.values = "0";ret.flag = true;return ret;}else if(compare(lvalues, rvalues) == 0){ret.values = "1";ret.flag = true;return ret;}else{//处理本质情况unsigned int lsize, rsize;lsize = lvalues.size();rsize = rvalues.size();int i;if(rsize > 1) temp.append(lvalues, 0, rsize-1);for(i = rsize - 1; i < lsize; i++){temp = temp + lvalues[i];//试商for(char c = '9'; c >= '0'; c--){BigInt t = (BigInt)rvalues * (BigInt)string(1, c);BigInt s = (BigInt)temp - t;if(s.flag == true){temp = s.values;quotient = quotient + c;break;}}}}//去除前导零quotient.erase(0, quotient.find_first_not_of('0'));ret.values = quotient;ret.flag = true;return ret;
}
/*
两个正整数取余
*/
BigInt BigInt::operator%(const BigInt& rhs)
{BigInt ret,kj(values),ki(rhs.values);string lvalues(values), rvalues(rhs.values);string quotient;string temp;//处理特殊情况if(rvalues == "0"){ret.values = "error";//输出错误ret.flag = true;return ret;}if(lvalues == "0"){ret.values = "0";ret.flag = true;return ret;}if(compare(lvalues, rvalues) < 0){if(flag==false){ret.values=(ki-kj).values;ret.flag = true;return ret;}else{ret.values = lvalues;ret.flag = true;return ret;}}else if(compare(lvalues, rvalues) == 0){ret.values = "0";ret.flag = true;return ret;}else{//处理本质情况unsigned int lsize, rsize;lsize = lvalues.size();rsize = rvalues.size();int i;if(rsize > 1) temp.append(lvalues, 0, rsize-1);for(i = rsize - 1; i < lsize; i++){if(temp=="0"){temp=lvalues[i];}else{temp = temp + lvalues[i];}//试商for(char c = '9'; c >= '0'; c--){BigInt t = (BigInt)rvalues * (BigInt)string(1, c);BigInt s = (BigInt)temp - t;if(s.flag == true){//cout<<s.values<<endl;temp = s.values;quotient = quotient + c;break;}}}}//去除前导零quotient.erase(0, quotient.find_first_not_of('0'));ret.values = temp;ret.flag = true;return ret;
}
/*
一个大整数和一个小整数的取余int divMod(string ch,int num)
{int s=0;for(int i=0;ch[i]!='\0';i++)s=(s*10+ch[i]-'0')%num;return s;
}*//*
欧几里德求GCD
*/
BigInt gcd(BigInt a,BigInt b)
{BigInt stemp;//cout<<a<<endl;//cout<<b<<endl;if((a-b).flag==false)//判断大小{stemp.values=a.values;a.values=b.values;b.values=stemp.values;}if(b.values=="0") return a;else return gcd(b,a%b);
}
/*
快速幂
*/
BigInt fast(BigInt a,BigInt b)
{BigInt aa=a,t("1"),k("2");//   int b2=atoi(b1[lsize-1].c_str());while(b.values!="0"){if((b%k).values!="0"){t=t*aa;}aa=aa*aa;b=b/k;}return t;
}
/*
快速幂模
*/
BigInt mod_fast(BigInt a,BigInt b,BigInt p)
{BigInt aa=a,t("1"),k("2");//   int b2=atoi(b1[lsize-1].c_str());while(b.values!="0"){if((b%k).values!="0"){t=(t%p)*(aa%p)%p;}aa=(aa%p)*(aa%p)%p;b=b/k;}return t%p;
}/*
扩展欧几里德实现乘法逆
*/
BigInt extgcd(BigInt a, BigInt b, BigInt& x, BigInt& y)
{BigInt d(a.values);if(b.values != "0"){d = extgcd(b, a % b, y, x);y = y-(a / b) * x;//   cout<<"a:"<<a<<endl;//  cout<<"b:"<<b<<endl;//  cout<<"x:"<<x<<endl;//  cout<<"y:"<<y<<endl<<endl<<endl;}else {x.values = "1";y.values = "0";}return d;
}
BigInt mod_inverse(BigInt a, BigInt m)
{BigInt x, y;extgcd(a, m, x, y);if(x.flag==false){x.flag=true;x=m-x;}return (m + x % m) % m;
}#endif // BIGINT_H_INCLUDED

Main.cpp

#include <iostream>
#include"BigInt.h"using namespace std;int main()
{/*公开密钥y,g,p*/BigInt p("19"),g("2"),x("9"),y("18"),a("1");BigInt k("5"),s,r,m,k1;BigInt t1,t2;cout<<"请输入m:"<<endl;cin>>m;r=mod_fast(g,k,p);k1=mod_inverse(k,p-a);s=((m-x*r)*k1)%(p-a);cout<<"r:"<<r<<endl;cout << "s:"<<s << endl;cout<<"接下来验证签名------->"<<endl;t1=fast(y,r);t2=fast(r,s);cout << "t1:"<<t1<< endl;cout << "t2:"<<t2<< endl;if(((t1*t2)%p).values==mod_fast(g,m,p).values){cout<<"签名成功!"<<endl;}else{cout<<"签名失败!"<<endl;}return 0;
}

四、运行结果

ElGamal公钥密码算法及ElGamal数字签名方案实现相关推荐

  1. ElGamal公钥密码算法(Python实现)

    本文目录 一.实验目的(包括实验环境.实现目标等等) 1. 实验环境 2. 实现目标 二.方案设计(包括背景.原理.必要的公式.图表.算法步骤等等) 1. 背景 2. 离散对数困难问题 3. EIGa ...

  2. (九)EIGamal公钥密码算法

    目录 EIGamal公钥密码算法 一.相关数学基础 二.算法原理 三.算法详细流程 四.特点和安全性 EIGamal公钥密码算法 ElGamal公钥密码算法是1985年由塔希尔·盖莫尔提出,是一个基于 ...

  3. 信息安全——ELGamal数字签名方案的实现

    ELGamal数字签名方案的实现 1. 问题描述 为简化问题,我们取p=19,g=2,私钥x=9,则公钥y=29 mod 19=18.消息m的ELGamal签名为(r,s),其中r=gk mod p, ...

  4. elgamal签名算法c语言,elgamal数字签名方案

    Elgamal算法由T.E1Gamal在1985年发表的一篇论文中提出,是Rabin体制的一种变型.其修正形式已被美国国家标准技术研究所作为数字签名标准(DS),其核心就是著名是数字签名方法(DSA) ...

  5. ElGamal公钥密码和椭圆曲线密码体制

    ElGamal公钥密码 基于有限域上离散对数问题的公钥密码体制,最著名的是ElGamal体制,是由T. ElGamal在1985年提出的 ElGamal有较好的安全性,同一明文在不同时刻会产生不同的密 ...

  6. elgamal签名算法c语言,ElGamal算法

    [声明] 一.本文实用于初学者,目的在于帮助大家熟悉一些系统底层的知识. 二.本文只是为了让广大网友共同提高一些基础知识,本人决无卖弄之意,只供需要这方面知识的读者阅读,如果你是高手,或者不需要这方面 ...

  7. ELGamal公钥密码

    ELGamal公钥密码 密钥产生 加密 解密 举例 Based on Descrete Logarithm Problem(DLP)离散对数问题 密钥产生 1.产生一个大的随机素数p 2.找出Zp的一 ...

  8. 一个基于RSA算法的Java数字签名例子

    ====================================================== 注:本文源代码点此下载 ================================= ...

  9. Schnorr数字签名方案

    Schnorr数字签名方案 Schnorr签名算法最初由德国密码学家claus schnorr于2008年提出,在密码学中,它是一种数字签名方案,以其简单著称 Schnorr数字签名方案也是基于离散对 ...

最新文章

  1. LeetCode 多线程 1117. H2O 生成
  2. CleanMyMac for mac之偏好设置
  3. linux改变磁盘顺序,Linux上磁盘顺序混乱的情况
  4. linux 下如何给火狐安装flash插件(常用命令cd cp tar 实践)
  5. 快逸报表数据库密码加密解决方案
  6. python 小程序——快递分拣程序
  7. 服务器在线测速系统源码_亲测可用
  8. RT-Thread Studio中使用DHT11软件包
  9. android跳转QQ陌生人聊天或者加入QQ群
  10. VB编程:SelectCase多分支选择结构实例测试生肖运势-13
  11. LDF转Excel;LDF转位定义;Excel转LDF;Excel转位定义;MatrixCreat(一)之LIN矩阵详解
  12. 【问题解决】win服务器磁盘初始化
  13. linux全角和半角的切换,全角和半角
  14. C语言中的循环语句(while、dowhile、for)
  15. 一个JAVA渣渣的校招成长记,附BAT美团网易等20家面经总结
  16. BZOJ4755: [JSOI2016]扭动的回文串——题解
  17. The first record --两次面试
  18. java实现.费诺编码_信息论编码实验报告费诺编码附源代码
  19. 2月9号cf,c题 Anu Has a Function
  20. 怎么把ppt转为html代码,ppt转html格式(示例代码)

热门文章

  1. 住建部公布温州等90个首批国家智慧城市试点名单
  2. microsoftonenote_微软的OneNote是干什么用的?
  3. 2021年年终总结及2022规划
  4. COALESCE()函数
  5. 疫情防控交流社区平台——3.3 开发社区核心功能
  6. 牛客网编程题python_牛客网数据结构练习题
  7. EXTEND RRT
  8. GEE云计算技术应用
  9. windows脚本编制引擎_手把手教你写脚本引擎(一)
  10. 遭遇WPS演示生成的PPT在PowerPoint 2010中不能显示背景的问题