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

1.RSA

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <math.h>

#include <time.h>

#define PRIME_MAX 200      //生成素数范围

#define EXPONENT_MAX 200       //生成指数e范围

#define Element_Max 127       //加密单元的最大值,这里为一个char, 即1Byte

char str_read[100]="hello world !";      //待加密的明文

int str_encrypt[100];      //存放加密后的内容

char str_decrypt[100];      //存放解密出来的内容

int str_read_len;      //str_read 的长度

int prime1, prime2;      //随机生成的两个质数

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;

}

流程图:

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=m*pow_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(p);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(p));

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_);

}

流程图:

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");

}

流程图:

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;

        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=23;

short q=11;      //p q为两个大素数,且满足(p-1)能够被q整除(这里为了方便选取了两个较小数,也可取p=7879,q=101)

int g,x,y,s,k,m,w,u1,u2,v,h,r;      //对出现的变量进行初始化

printf("请输入大素数p=%d和q=%d ,满足(p-1)能够被q整除\n",p,q);

srand(time(NULL));      //随机数种子

h=12;      //rand()%p-1+2 ;//随机数

g=calculate(h,p,q);

x=10;      //rand()%p-1+2 ;//私钥

y=calculate1(g,x,p);      //计算公钥

printf("公钥是(%d,%d,%d,%d)\n",p,q,g,y);

printf("私钥为%d\n",x);



//签名过程

k=9;      //rand()%p-1+2 ;//随机数k

r=calculate1(g,k,p)%q;

exGcd(k, q);

k = xy[0];

    if(k < 0) k += (p-1);  

m=13;

s=(m+x*r)*k%q;

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



//验证程序

exGcd(s,q);

w =xy[0];

if(w < 0) w += (q);

u1=(m*w)%q;

u2=r*w%q;

v=myPow(g, u1, p)*myPow(y, u2, p)%p%q;

printf("(w,u1,u2,v)=(%d,%d,%d,%d)\n",w,u1,u2,v);

if(v==r){

printf("接受");

}else{

printf("不接受");

}



}

流程图:

5.有限域(GF)上的加、减、乘法计算器

#include<cstdio>

#include<cstdlib>

#include<iostream>

#include<algorithm>

#include<cstring>

#include<vector>

#include<cmath>

#include<bits/stdc++.h>

int hex1=0x57,hex2=0x83;



void jiafa(int hex1,int hex2)

{

    printf("请输入两个十六进制串:%x %x\n",hex1,hex2);

    printf("\n得到有限域内相加结果 : %#X\n\n",hex1^hex2);

}

//a减去b,其实就是a加上b的加法逆元,关键是找到b的加法逆元。

void chengfa(int hex1,int hex2)

{

    int a[16],b[16],s[32];

    printf("请输入两个十六进制串:%x %x\n",hex1,hex2);

    int n=hex2,cnt=0;

    while(n)///转化为二进制

    {

        s[cnt++]=n%2;

        n/=2;

    }

    a[1]=0x01,b[1]=hex1;

    for(int i=2; i<=8; i++)

        a[i]=a[i-1]<<1;///得到0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80

    for(int i=2; i<=8; i++)

    {

        if(b[i-1]&0x80)///如果最高为为1就对不可约多项式取模,否则直接左移

            b[i]=((b[i-1]<<1)^0x1B);

        else

            b[i]=b[i-1]<<1;

        b[i]&=0xFF;///直接取后两位

    }

    int hex=0x00;

    for(int i=7; i>=0; i--)

    {

        if(s[i]==1)///当二进制的这一位为1的时候才能异或

            hex^=b[i+1];

    }

    printf("\n得到有限域内相乘结果 : %#X\n\n",hex);

}

int main()

{

    while(1)

    {

        printf("请选择进行的运算: 0.退出运算  1.加/减法运算  2.乘法运算 \n\n");

        int ch;

        scanf("%d",&ch);

        switch(ch)

        {

        case 0:

            system("cls");

            printf("\n谢谢使用!\n");

            exit(0);

        case 1:

            system("cls");

            jiafa(hex1,hex2);

            break;

case 2:

            system("cls");

            chengfa(hex1,hex2);

            break;

        default :

            system("cls");

            printf("\n输入错误!请重新输入:\n\n");

            break;

        }

    }

    return 0;

}

流程图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/589087.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java基础知识(三) -- 流程控制

不论哪种编程语言&#xff0c;都会提供两种基本的流程控制结构&#xff1a;分支结构和循环结构。其中分支结构用于实现根据条件来选择性地执行某段代码&#xff0c;循环结构则用于实现根据循环条件重复执行某段代码。 1. 顺序结构 任何编程语言中最常见的程序结构就是顺序结构…

van-cascader(vant2)异步加载的bug

问题描述&#xff1a;由于一次性返回所有的级联数据的话&#xff0c;数据量太大&#xff0c;接口响应时间太久&#xff0c;因此采用了异步加载的方案&#xff0c;看了vant的官方示例代码&#xff0c;照着改了下&#xff0c;很轻松地实现了功能。正当我感叹世界如此美好的时候&a…

结合创新!频域+时间序列,预测误差降低64.7%

频域时间序列不仅能提供更丰富的信息&#xff0c;还能提高模型性能和预测准确性。对于论文er来说&#xff0c;是个可发挥空间大、可挖掘创新点多的研究方向。 具体来说&#xff1a; 通过将复杂的时间序列数据转换成简单的频率成分&#xff0c;我们可以更容易地捕捉到数据的周期…

【SpringBoot整合系列】SpringBoot整合Redis[附redis工具类源码]

目录 SpringBoot整合Redis1.下载和安装Redis2.新建工程&#xff0c;导入依赖3.添加配置4.先来几个基本的示例测试代码输出结果用redis客户端查看一下存储内容 5.封装redis工具类RedisKeyUtilRedisStringUtilRedisHashUtilRedisListUtilRedisSetUtilRedisZsetUtil备注 6.测试通用…

nginx--第三方模块安装上传下载服务

第三方模块安装 准备 cd /usr/local/src/ yum install git -y git clone https://github.com/openresty/echo-nginx-module.git cd nginx-1.24.0 yum -y install perl-devel perl-ExtUtils-Embed zlib-devel gcc-c libtool openssl openssl-devel 编译安装 ./configure \--p…

Javascript:Web APIs(一)

Javascript基础&#xff08;一&#xff09; Javascript基础&#xff08;二&#xff09; Javascript基础&#xff08;三&#xff09; Javascript基础已经结束&#xff0c;接下来我们将进入到整个Web API学习中&#xff0c;在此&#xff0c;我们将学习DOM操作&#xff0c;基本的…

32.Docker认识

Docker介绍 Docker是一个快速交付应用&#xff0c;运行应用的技术。 1.可以将程序、依赖、运行环境一起打包为一个镜像&#xff0c;可以迁移到任意Linux操作系统。 2.运行时利用沙箱机制行程隔离容器&#xff0c;各个应用互不干扰。 3.启动、移除都可以通过一行命令完成&am…

多线程基础知识(全面):创建线程、线程状态如何变化、wait()、notify()、sleep()、停止线程

文章目录 一、创建线程的四种方式1.1 继承Thread类1.2 实现runnable接口1.3 实现Callable接口1.4 线程池创建线程1.5 补充&#xff1a;runnable、callable都可以创建线程&#xff0c;有什么区别&#xff1b;run()和 start()有什么区别 二、线程包括哪些状态、状态之间如何变化2…

40.WEB渗透测试-信息收集-域名、指纹收集(2)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;39.WEB渗透测试-信息收集-域名、指纹收集&#xff08;1&#xff09; oneforall的安装前置…

《深入解析Windows操作系统》第5章节学习笔记

1、每个Windows进程都是由一个执行体进程EPROCESS结构来表示的&#xff0c;EPROCESS和相关数据结构位于系统空间&#xff0c;但是进程环境控制块PEB是个例外&#xff0c;它位于进程空间地址中&#xff08;因为它包含了一些需要由用户模式代码来修改的信息&#xff09;。对于每一…

『跨端框架』Flutter环境搭建

『跨端框架』Flutter环境搭建 资源网站简介跨平台高性能发展历程跨平台框架的比较成功案例 环境搭建&#xff08;windows&#xff09;基础环境搭建Windows下的安卓环境搭建Mac下的安卓环境配置资源镜像JDKAndroid StudioFlutter SDK问题一问题二问题三修改项目中的Flutter版本 …

Java中的字符流

字符流字节流编码表 Java为什么可以区分字母和汉字 package day3; ​ import java.io.UnsupportedEncodingException; import java.lang.reflect.Array; import java.util.Arrays; ​ public class Test {public static void main(String[] args) throws UnsupportedEncoding…

【Mybatis 】什么是mybatis?如何在普通项目中使用?(超详细建议收藏)

文章目录 mybatis第一章1、什么是mybatis2、idea中配置环境3、创建一个普通工程 第二章1、mybatis基本步骤2、导入log4j日志3、使用lombok注解4、mapper.xml文件详情1、parameterType属性2、resultType属性 5、对实体包进行扫描6、SQL语句中的占位符及转义符7、接口方法包含多个…

Flutter笔记:Widgets Easier组件库(5)使用加减器

Flutter笔记 Widgets Easier组件库&#xff08;5&#xff09;&#xff1a;使用加减器 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress…

【校招】校园招聘中的签约环节,面完HR后的流程(意向书,offer选择与三方协议)

【校招】校园招聘中的签约环节&#xff0c;面完HR后的流程&#xff08;意向书&#xff0c;offer选择与三方协议&#xff09; 文章目录 一、面完HR后的流程1、口头oc、谈薪&#xff08;两个电话&#xff09;2、邮件意向书、带薪offer&#xff08;两封邮件&#xff09;3、签三方&…

算法训练营第十三天 | LeetCode 239 滑动窗口最大值、LeetCode 347 前K个高频元素

LeetCode 239 滑动窗口最大值 本体初始思路是这样的&#xff0c;首先看下给定数组长度和维持一个滑动窗口所需要花费的时间复杂度之间的关系。初步判断是还行的&#xff0c;当然后面被样例打脸了。需要更新成优先队列的解法。原本的解法能通过37/51和46/51的测试用例。但这还不…

基于Spring Boot的校园疫情防控系统设计与实现

基于Spring Boot的校园疫情防控系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 管理员登录首页界面图&#xff0c;管理员进入校园疫…

AI大模型探索之路-训练篇10:大语言模型Transformer库-Tokenizer组件实践

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

msmpi 高性能并行计算 移植并行细胞自动机报错

报错情况如图 代码来源 元胞自动机生命游戏C语言并行实现 – OmegaXYZ 稍微修改&#xff0c;因为相对路径在 msmpi 10.1.1 中失效 Microsoft Windows [版本 10.0.22000.2538] (c) Microsoft Corporation。保留所有权利。C:\Users\ASUS>mpiexec -n 9 "C:\Users\ASUS\D…

四信数字孪生水库解决方案,加快构建现代化水库运行管理矩阵

近年&#xff0c;水利部先后出台《关于加快构建现代化水库运行管理矩阵的指导意见》与《构建现代化水库运行管理矩阵先行先试工作方案》等文件&#xff0c;明确总体要求及试点水库、先行区域建设技术要求等&#xff0c;为全面推进现代化水库运行管理矩阵建设工作提供依据。 《2…
最新文章