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

news2024/11/25 20:02:24

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.coloradmin.cn/o/1639290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

26版SPSS操作教程(高级教程第十八章)

目录 前言 粉丝及官方意见说明 第十八章一些学习笔记 第十八章一些操作方法 经典判别分析 数据假设 具体操作 结果解释 判别结果的图形化展示 结果解释 判别效果验证 结果解释 适用条件的判断 结果解释 贝叶斯判别分析 具体操作 结果解释 逐步判别法 结束语…

Redis---------实现查询缓存业务

目录 数据库与缓存之间的工作业务逻辑&#xff1a; 接下来看查询缓存代码实现&#xff0c;主要是捋清楚业务逻辑&#xff0c;代码实现是死的&#xff1a; Controller: Service: P37作业实现&#xff1a;总体逻辑跟上面的业务逻辑差不多 Controller&#xff1a; Service&#…

【项目构建】04:动态库与静态库制作

OVERVIEW 1.编译动态链接库&#xff08;1&#xff09;编译动态库&#xff08;2&#xff09;链接动态库&#xff08;3&#xff09;运行时使用动态库 2.编译静态链接库&#xff08;1&#xff09;编译静态库&#xff08;2&#xff09;链接静态库&#xff08;3&#xff09;运行时使…

数字身份管理:Facebook如何利用区块链技术?

随着数字化进程的加速&#xff0c;个人身份管理已成为一个关键议题。在这方面&#xff0c;区块链技术正在逐渐展现其巨大潜力。作为全球最大的社交媒体平台&#xff0c;Facebook也在积极探索和应用区块链技术来改进其数字身份管理系统。本文将深入探讨Facebook如何利用区块链技…

【Docker学习】docker start深入研究

docker start也是很简单的命令。但因为有了几个选项&#xff0c;又变得复杂&#xff0c;而且... 命令&#xff1a; docker container start 描述&#xff1a; 启动一个或多个已停止的容器。 用法&#xff1a; docker container start [OPTIONS] CONTAINER [CONTAINER...] 别名&…

【软件工程】需求分析

目录 前言需求分析UML概述用例图用例图的组成用例图中的符号和含义包含的两种使用场景 用例图补充&#xff1a;“系统”用例模型建模确定系统参与者确定系统用例 用例文档用例文档组成部分 活动图组成元素初始节点和终点活动节点转换决策与分支、合并分岔与汇合 类图类的表示类…

【DevOps】怎么找合适的Docker镜像?

目录 一、Docker Hub介绍 主要特点和功能 使用场景 二、怎么找合适的镜像 步骤 1: 访问 Docker Hub 步骤 2: 使用搜索功能 步骤 3: 分析搜索结果 步骤 4: 阅读详细描述 步骤 5: 下载并使用镜像 例子 三、怎么样使用国内镜像加速 常用的国内 Docker 镜像加速器地址 …

2023下半年软件设计师上午题——冒泡排序

快速排除法&#xff0c;根据冒泡排序特性&#xff0c;每一趟排序都会确实最大/最小值&#xff0c;故升序两趟后&#xff0c;最后两个元素应该是已经排序好的第二大&#xff0c;和最大的元素&#xff0c;所以排除B,D&#xff0c;再因为每次排序都会两两交换&#xff0c;所以排除…

C语言-调试技巧

目录 一、调试介绍1.1 Debug和Release的介绍1.2 Windows环境调试介绍1.2.1 学会快捷键1.2.2 查看临时变量的值1.2.3 查看内存信息1.2.4 查看调用堆栈1.2.4 查看汇编信息1.2.5 查看寄存器信息 二、编程常见的错误2.1 编译型错误2.2 链接型错误2.3 运行时错误 三、易于调试的代码…

如何配置和使用Apollo的component里的plugin

关于如何使用Apollo的Component里的plugin&#xff0c;在Apollo的文档里只有如果和开发的说明却没有找到一个清楚完整说明怎么把plugin跑起来的说明&#xff0c;例如我想把lidar_detection_filter按我们的需求对目标过滤算法作修改然后编译完后&#xff0c;执行 cyber_launch …

刷题训练之位运算

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握位运算算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷题…

菜鸡学习netty源码(一)——ServerBootStrap启动

1.概述 对于初学者而然,写一个netty本地进行测试的Server端和Client端,我们最先接触到的类就是ServerBootstrap和Bootstrap。这两个类都有一个公共的父类就是AbstractBootstrap. 那既然 ServerBootstrap和Bootstrap都有一个公共的分类,那就证明它们两个肯定有很多公共的职…

代码随想录算法训练营第二天|977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

977.有序数组的平方 题目链接https://leetcode.cn/problems/squares-of-a-sorted-array/description/ 题解&#xff1a; /*** Note: The returned array must be malloced, assume caller calls free().*/ int* sortedSquares(int* nums, int numsSize, int* returnSize) {/…

【Vue中的Ajax配置代理slot插槽】

Vue脚手架配置代理 安装命令 npm install axios vue.config.js 是一个可选的配置文件 如果项目的(和package . json同级的)根目录中存在这个文件&#xff0c; 那么它会被vue/cli-service自动加载 你也可以使用package.json中的 [vue字段&#xff0c;但是注意这种写法需要你严格…

Vue入门篇:样式冲突scoped,data函数,组件通信,prop data单向数据流,打包发布

这里写目录标题 1.组件的样式冲突scoped2.data函数3.组件通信1.两种组件关系分类和对应的组件通信方案2.父子通信方案的核心流程 4.prop & data、单向数据流5.打包发布6.打包优化:路由懒加载 1.组件的样式冲突scoped 默认情况:写在组件中的样式会全局生效→因此很容易造成多…

axios.get请求 重复键问题??

封装的接口方法&#xff1a; 数据&#xff1a; 多选框多选后 能得到对应的数组 但是请求的载荷却是这样的,导致会请求不到数据 departmentChecks 的格式看起来是一个数组&#xff0c;但是通常 HTTP 请求的查询参数不支持使用相同的键&#xff08;key&#xff09;名多次。如…

数据结构-链表OJ

1.删除链表中等于给定值 val 的所有结点。 . - 力扣&#xff08;LeetCode&#xff09; 思路一&#xff1a;遍历原链表&#xff0c;将值为val的节点释放掉 思路二&#xff1a;创建一个新链表&#xff0c;将值不为val的节点尾插到新链表中 /*** Definition for singly-linked …

Stable Diffusion WebUI 中调度器(Schedule type)简单研究

&#x1f48e;内容概要 在近期&#xff0c;stable diffusion webui更新了1.9版本&#xff0c;其中包含的一项变化就是&#xff0c;把采样器和调度器&#xff08;Schedule type&#xff09;分开了&#xff0c;之前是合并在一起来选择的&#xff0c;所以这篇文章主要分两个部分&…

用Langchain创建一个可以总结网页内容的Agent

去年的时候我写过一篇关于OpenAi Function Call的实践文章&#xff0c;就是用Function Call的功能实现抓取并总结网页内容的功能&#xff0c;具体可以参考ChatGPT函数调用初体验&#xff1a;让ChatGPT具备抓取网页文本的能力&#xff0c;当时写了还算比较多的代码&#xff0c;最…

查询每个部门工资最高的员工 sql

在线运行sql语句 CREATE TABLE dept (dno INT PRIMARY KEY AUTO_INCREMENT,dname VARCHAR(50) NOT NULL,dlocal VARCHAR(100) ); CREATE TABLE employee (eno INT PRIMARY KEY AUTO_INCREMENT,ename VARCHAR(50) NOT NULL,egender CHAR(2),deptno INT NOT NULL,ejob VARCHAR(5…