密码学基础练习五道 RSA、elgamal、elgamal数字签名、DSA数字签名、有限域(GF)上的四则运算(3)

int mod,eular;      //模数和欧拉数

int pubKey, priKey;      //公钥指数和私钥指数

//生成随机素数

int randPrime()

{

int prime,prime2,i;

next:

prime=rand()%PRIME_MAX;      //随机产生数

if (prime <= 1) goto next;      //不是质数,生成下一个随机数

if (prime == 2 || prime == 3)

return prime;

prime2=prime/2;      //注:prime>=4, prime2 的平方必定大于 prime , 因此只检查小于等于prime2的数

for (i=2;i<=prime2;i++)      //判断是否为素数

{

if(i*i>prime)

return prime;

if(prime%i==0)

goto next;      //不是质数,生成下一个随机数

}

}

// 欧几里德算法,判断a,b互质

int gcd(int a, int b)

{

int temp;

while (b!=0){

temp=b;

b=a%b;

a=temp;

}

return a;

}

//生成公钥,条件是 1< e < 欧拉数,且与欧拉数互质。

int randExponent()

{

int e;

while (1)

{

e=rand()%eular;

if(e<EXPONENT_MAX)

break;

}

while (1)

{

if(gcd(e, eular)==1)

return e;

e=(e+1)%eular;

if(e==0||e>EXPONENT_MAX)

e = 2;

}

}

//生成私钥指数

int inverse()

{

int d,x;

while (1)

{

d=rand()%eular;

x=pubKey*d%eular;

if(x==1)

{

return d;

}

}

}

//加密函数

void jiami()

{

str_read_len = strlen(str_read);//从参数表示的地址往后找,找到第一个’\0’,即串尾.计算’\0’至首地址的“距离”,即隔了几个字符,从而得出长度.

printf(“密文是:”);

for(int i=0;i<str_read_len;i++)

{

int C=1;

int a=str_read[i],b=a%mod;

for(int j=0;j<pubKey;j++)      //实现加密

{

C=(C*b)%mod;

}

str_encrypt[i]=C;

printf(“%d”,str_encrypt[i]);

}

printf(“\n”);

}

//解密函数

void jiemi()

{

int i=0;

for(i=0;i<str_read_len;i++)

{

int C=1;

int a=str_encrypt[i],b=a%mod;

for(int j=0;j<priKey;j++)

{

C=(C*b)%mod;

}

str_decrypt[i]=C;

}

str_decrypt[i]=‘\0’;

printf(“解密文是:%s\n”,str_decrypt);

}

//主函数

int main()

{

srand(time(NULL));

while (1)

{

prime1=randPrime();

prime2=randPrime();

printf(“随机产生两个素数:prime1=%d,prime2=%d”,prime1,prime2);

mod=prime1*prime2;

printf(“模数:mod=prime1*prime2=%d\n”,mod);

if(mod>Element_Max)

break;      //模数要大于每个加密单元的值

}

eular=(prime1-1)*(prime2-1);

printf(“欧拉数:eular=(prime1-1)*(prime2-1)=%d\n”,eular);

pubKey=randExponent();

printf(“公钥指数pubKey=%d\n”,pubKey);

priKey=inverse();

printf(“私钥指数:priKey=%d\n  私钥为(%d, %d)\n”, priKey, priKey, mod);

jiami();

jiemi();

return 0;

}


流程图:


![](https://img-blog.csdnimg.cn/direct/30c37fa204484d43abdc14e65fc5fec3.png)



2.elgamal



#include<stdio.h>

#include<stdlib.h>

#include<math.h>

//模重复平方算法,计算a^b mod p

int pow_mod(int a,int b,int p)

{

int ans=1;

int tmp=a%p;

while(b){

if(b&1)

ans=ans*tmp%p;

b>>=1;

tmp=tmp*tmp%p;

}

return ans%p;

}

//elgamal加密算法,k为任意整数,m为明文,pub为公钥,p为大素数,g为生成元,c1,c2为密文

void elgamal_en(int m,int pub,int p,int g,int *c1,int *c2)

{

int k=5;

*c1=pow_mod(g,k,p);

c2=mpow_mod(pub,k,p)%p;

}

//elgamal解密算法,m_为解密后的数据,p为大素数,g为生成元,c1_为c1模p的逆元,pr为私钥

int elgamal_de(int c1,int c2,int pr,int p,int g)

{

int m;

int c1_=pow_mod(c1,p-2,p);

m=c2*pow_mod(c1_,pr,p)%p;

return m;

}

//判断是否为素数(为了严谨性而存在的函数,题中所给出的测试数据已经是素数了)

int is_prime(int p)

{

int i;

for(i=2;i<=sqrt§;i++){

if(p%i==0)

return 0;

}

return 1;

}

int main(){

int p=1069;      //必须为素数

int g=2;      //本原元

do{

printf(“请输入一个素数:%d\n”,p);

}

while(!is_prime§);

int pr=123;      //用户A的私钥

printf(“输入用户A的私钥:%d\n”,pr);

int pub;

pub=pow_mod(g,pr,p);

printf(“用户A的公钥为:%d\n”,pub);

int m=677;      //明文要小于p

int c1,c2;

elgamal_en(m,pub,p,g,&c1,&c2);

printf(“用公钥加密后的密文为:c1=%d,c2=%d\n”,c1,c2);

int m_=elgamal_de(c1,c2,pr,p,g);

printf(“用私钥解密后的明文为:%d\n”,m_);

}




流程图:


![](https://img-blog.csdnimg.cn/direct/7c81e8f358b446f39fb3b9dc7d5d08cc.png)


3.elgamal数字签名:



#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <math.h>

int xy[22];

int myPow(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;

}

//判断两个数是否互质

int Coprime(int a, int b) {

return b==0?a:Coprime(b,a%b);

}

int calculate3(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 的逆元

void exGcd(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];

}

}

//主函数

int main() {

int p=1669,m=101,q=2;        //p为大素数,m为消息,q为本原元

int x,y,k,k1,r,a;

int k2,ni;

int s;

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(Coprime(k,p-1)!=1) {

k=rand()%p-1+1;

}

printf(“k=%d\n”,k);

//求r :r = g^k mod p

r=myPow(q,k,p);

printf(“r=%d\n”,r);

//加密过程

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\n”,ni);

m=myPow(ni,x,p)*s;

printf(“m=%d\n”,m%p);

//签名过程

// 计算k^-1 mod p-1

exGcd(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)%b

if(s<0)s=(s%(p-1)+(p-1))%(p-1);

printf(“签名为(%d,%d)\n”,r,s);

if((myPow(y,r,p)*myPow(r,s,p))%p==myPow(q,m,p))

printf(“接受签名\n”);

else

printf(“拒绝签名\n”);

}




流程图:


![](https://img-blog.csdnimg.cn/direct/c6aa62b03d01470886b99f802b1c038b.png)


4.DSA数字签名算法:



#include <stdlib.h>

#include <stdio.h>

#include <time.h>

int xy[22];

//乘法逆元

int myPow(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;

}

int calculate(int h,int p,int q){

int a=(p-1)/q;

long int k=1;

for(int i=0;i<a;i++){

k=k*h;

}

return k%p;

}

int calculate1(int g,int x,int p){

long int k=1;

for(int i=0;i<x;i++){

k=k*g;

}

return k%p;

}

// 求 a mod b 的逆元

void exGcd(int a, int b) {

if (b == 0) {

xy[0] = 1;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

exGcd(int a, int b) {

if (b == 0) {

xy[0] = 1;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-ra02gcdS-1715684629135)]

[外链图片转存中…(img-UYKwPAKe-1715684629136)]

[外链图片转存中…(img-XAF38iOx-1715684629136)]

[外链图片转存中…(img-9ZGmq5PJ-1715684629136)]

[外链图片转存中…(img-qziIs0UB-1715684629137)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值