#include<stdlib.h>#include<stdio.h>#include<time.h>#include<math.h>int xy[22];intmyPow(int a,int b,int m){
int res =1;
a %= m;while(b !=0){
if((b &1)==1)
res =(res * a)% m;
a =(a * a)% m;
b >>=1;}return res;}// 判断两个数是否互质intisHuZhi(int a,int b){
return b ==0? a :isHuZhi(b, a % b);}intcalculate3(int y,int k,int p){
printf("...%d %d %d\n",y,k,p);int l=1;for(int i =0;i<k;i++){
l=l*y;
l=l%p;}printf("l=%d\n",l);return l;}// 求 a mod b 的逆元voidexGcd(int a,int b){
if(b ==0){
xy[0]=1;
xy[1]=0;}else{
exGcd(b, a % b);int x = xy[0];
xy[0]= xy[1];
xy[1]= x -(a / b)* xy[1];}}main(){
int p,q,x,y,k,k1,m,r,a;int k2,ni;int s;printf("请输入大素数 p ");scanf("%d",&p);printf("请输入消息 m ");scanf("%d",&m);printf("请输入本源元 q ");scanf("%d",&q);srand(time(NULL));//随机数种子
x=15;//rand()%p-1+2 ;printf("x=%d\n",x);
y =myPow(q, x, p);// y是公开密钥printf("公开密钥y=%d\n",y);
k =11;//rand()%p-1+1 ;while(isHuZhi(k, p-1)!=1){
k =rand()%p-1+1;}printf("k=%d",k);// r = g^k mod p
r =myPow(q, k, p);printf("r=%d\n",r);printf("若是加密请输入1,签名输入2");scanf("%d",&a);switch(a){
case1:
s=calculate3(y,k,p);if(s <0) s =(s+(p-1))%(p-1);
s=s*m%p;printf("发送密文(%d,%d)\n",r,s);//解密
k2=myPow(r, x, p);printf("k2=%d\n",k2);exGcd(r,p);
ni=xy[0];if(ni<0)ni=ni+p;printf("ni=%d",ni);
m=myPow(ni,x,p)*s;printf("m=%d",m%p);break;case2:// 计算k^-1 mod p-1exGcd(k,(p-1));
k1 = xy[0];if(k1 <0) k1 +=(p-1);printf("k1=%d\n",k1);// s = k^(-1)*(m-rx)(mod p-1)
s =(k1*(m-r*x))%(p-1);// (m,r,s)为对消息m的数字签名printf("s=%d\n",s);// s可能为负值,所以要将其转化为正数,利用a%b=(a%b+b)%bif(s <0) s =(s%(p-1)+(p-1))%(p-1);printf("签名为(%d,%d)",r,s);if((myPow(y, r, p)*myPow(r, s, p))%p ==myPow(q, m, p)){
printf("接受签名");}else{
printf("拒绝签名");}// 计算k^-1 mod p-1exGcd(k,(p-1));
k1 = xy[0];if(k1 <0) k1 +=(p-1);printf("k1=%d\n",k1);// s = k^(-1)*(m-rx)(mod p-1)
s =(k1*(m-r*x))%(p-1);// (m,r,s)为对消息m的数字签名printf("s=%d\n",s);// s可能为负值,所以要将其转化为正数,利用a%b=(a%b+b)%bif(s <0) s =(s%(p-1)+(p-1))%(p-1);printf("签名为(%d,%d,%d)",r,s,p);if((myPow(y, r, p)*myPow(r, s, p))%p ==myPow(q, m, p)){
printf("接受签名");}else{
printf("拒绝签名");}break;}}