信息安全:使用程序编写基于密钥的加密方式

news2024/11/22 18:58:15

目录

  • 前言
  • RSA算法
    • 代码实现
    • 设计思路
    • 结果示意
  • Diffie-Hellman算法
    • 代码实现
    • 设计思路
    • 结果示意

前言

信息安全是计算机科学的一个重要分支,它涉及到保护信息的机密性、完整性和可用性。信息加密是信息安全的一种常用手段,它通过使用一些数学算法和密钥,将明文转换为不易被破解的密文,从而防止未经授权的访问和篡改。本实验的目的是让学生了解基于密钥的加密方式的原理和实现方法,使用程序编写一个简单的加密和解密功能,并测试其效果。本实验分为两个部分:第一部分是理论学习,介绍基于密钥的加密方式的分类和特点,以及常见的加密算法;第二部分是实践操作,使用C语言编写一个基于对称密钥的加密和解密程序,并对不同长度的明文进行加密和解密,观察其运行时间和结果。

RSA算法

RSA算法是一种非对称加密算法,与对称加密算法不同的是,RSA算法有两个不同的密钥,一个是公钥,一个是私钥。
RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。
在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,但却不能根据PK计算出SK 。
正是基于这种理论,1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA对话密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要 。
RSA是被研究得最广泛的公钥算法,从提出后经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。1983年麻省理工学院在美国为RSA算法申请了专利 。
RSA允许选择公钥的大小。512位的密钥被视为不安全的;768位的密钥不用担心受到除了国家安全管理(NSA)外的其他事物的危害;RSA在一些主要产品内部都有嵌入,像 Windows、网景 Navigator、 Quicken和 Lotus Notes 。
由于RSA算法1024位密钥面临严重的安全威胁,为保障电子认证服务安全应用,2016年12月5日,上海市密码管理局在其官方网站上发布公告,称从2017年1月1日起停止提供RSA算法1024位密钥对服务,并配合电子认证服务机构和应用单位做好应对措施,确保平稳过渡。

代码实现

#include<stdio.h>
#include<string.h>
#include <stdlib.h>
 
const int max=2e4;
int size;
int miwen[max];//为加密后的数字密文
char mingwen[max]; 
 
//判断两个数是否互为素数  eg:p和q e和 t 
bool gcd(int p,int q)
{
	int m,n;
	if(q<p)
	{
		m=p;  p=q;  q=m;  //将p换成p和q之间那个小的数 
		m=q%p;  n=q/p;  //辗转相除法求两个数的最大公因数 
	}
	while(m!=0)
	{
		q=p; p=m;  //将p换成p和q之间那个小的数
		m=q%p;  n=q/p;		
	} 
	if(m==0&&n==q)
	{
		printf("符合条件!\n");
			return true;
	}
	else{
		printf("不符合条件!请重新输入:\n");
	    	return false;
	}
} 
//判断输入的p和q是不是素数 
bool sushu(int s){
	for(int i=2;i<s;i++){
		if(s%i==0) 
		return false;
	}
	return true;
}
//求私钥d
int siyao(int e,int t)  //t:欧拉函数 
{
	int d;
	for(d=0;d<t;d++)
	    if(e * d % t==1)
	       return d;
}
//随机生成与 t互质的数e
int getrand(int p,int q)
{
	int t=(p-1)*(q-1);
	while(1)
	{
		int e=rand() % t;
		if(gcd(e,t)==1)
		return e;
	//	if(e<=2)
	//	e=3;
	}
}
void jiami(int e,int n) 
{
	//先将符号明文转换成字母所对应的ascii码。 
	char mingwen[100];    //符号明文 
	printf("请输入明文:\n");
	scanf("%s",mingwen);
	size=strlen(mingwen);
	int ming[strlen(mingwen)];   //定义符号明文 
	for(int i=0;i<strlen(mingwen);i++)
	{
	   ming[i]=mingwen[i];        //将字母转换成对应的ascii码。 
	//printf("%d",mingwen[i]);  //将字母转换成对应的ascii码。可以不输出 
	} 
	int flag=1;    //miwen为加密后的数字密文 
	for(int i=0;i<strlen(mingwen);i++)
	{
	    for(int j=0;j<e;j++)
		{
		    flag=flag*ming[i]%n; 
	    }
	    miwen[i]=flag; 
	    flag=1;
	} 
	printf("加密密文为:\n");
	for(int i=0;i<strlen(mingwen);i++) 
	printf("%d",miwen[i]); 
}
void jiemi(int d,int n)
{
	int de_mingwen[size],flag=1;//解密后得到的数字明文(即ascii码) 
	char de_ming[size];//解密后得到的字符串明文 
	for(int i=0;i<size;i++)
	{
	   for(int j=0;j<d;j++)
	   {
	   	  flag=flag*miwen[i]%n;
	   }
	   de_mingwen[i]=flag; 
	   flag=1;
	} 
	printf("解密后的明文为:\n");
	for(int i=0;i<size;i++)
	{
		de_ming[i]=de_mingwen[i];
		printf("%c",de_ming[i]);
	}
}
int main()
{
	int p,q,e,d,n,t,tep;
	while(1)
	{
		printf("请输入p:",p);
		scanf("%d",&p);
		tep=sushu(p);
		if(tep==0)
		{
			printf("p不是素数,请重新输入p!\n");
		    continue;
		} 
		printf("请输入q:",q);
		scanf("%d",&q);
	    tep=sushu(q);
	    if(tep==0)
		{
		printf("q不是素数,请重新输入q!\n");
		printf("请输入q:",q);
		scanf("%d",&q);
		tep=sushu(q);
		}
		int n=p*q;
		int t=(p-1)*(q-1);
		tep=gcd(p,q);
		if(tep==0)   continue;
		printf("t=(q-1)*(p-1)=%d\n",t);
		e=getrand(p,q);
		printf("公钥(e=%d n=%d)\n",e,n);
		tep=(e,t);
		d=siyao(e,t);
		printf("私钥d=%d",d);
		int a=0;
		while(a!=3)
		{
			printf("\n-------------------------\n");
			printf("1、加密\n");
	        printf("2、解密\n");
	        printf("3、退出");
	        printf("\n-------------------------\n");
	        scanf("%d",&a);
	        getchar();
	        if(a==1)
	        {
	        	jiami(e,n);
	        }
	        else if(a==2)
	        {
	        	printf("请输入密钥:");
		        scanf("%d",&d);2
		        jiemi(d,n);
	        }
	        else 
			     return 0;
		}		
    }
    return 0;
}

设计思路

RSA加密算法的设计思路是基于数论的一些性质,主要有以下几个步骤:

首先,选择两个大的素数p和q,计算它们的乘积n,作为公钥的一部分。n的长度就决定了RSA算法的安全强度。
然后,计算n的欧拉函数φ(n),即小于n且与n互质的正整数的个数。根据数论的性质,φ(n) = (p-1)(q-1)。
接着,选择一个整数e,使得e与φ(n)互质,即最大公约数为1。e也作为公钥的一部分,用于加密信息。
然后,利用扩展欧几里得算法,求出e对于φ(n)的模反元素d,即满足ed ≡ 1 (mod φ(n))的整数d。d作为私钥的一部分,用于解密信息。
最后,将公钥(e, n)和私钥(d, n)分别保存或发布。加密信息m时,计算c = m^e mod n,得到密文c。解密密文c时,计算m = c^d mod n,得到明文m。
这样,RSA算法就实现了非对称加密和解密的过程,利用了素数分解和模反元素的难度来保证安全性。更多细节和证明可以参考这篇文章link或这篇文章link。

结果示意

在这里插入图片描述

Diffie-Hellman算法

Diffie-Hellman(简称 DH) 密钥交换是最早的密钥交换算法之一,它使得通信的双方能在非安全的信道中安全的交换密钥,用于加密后续的通信消息。 Whitfield Diffie 和 Martin Hellman 于 1976 提出该算法,之后被应用于安全领域,比如 Https 协议的 TLS(Transport Layer Security) 和 IPsec 协议的 IKE(Internet Key Exchange) 均以 DH 算法作为密钥交换算法。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 定义一个函数,用于计算a的b次方模n的结果
int mod_pow(int a, int b, int n) {
    int res = 1;
    while(b > 0) {
        if(b & 1) { // 如果b的最低位为1,则将res乘以a并取模
            res = (res * a) % n;
        }
        a = (a * a) % n; // 将a平方并取模
        b >>= 1; // 将b右移一位
    }
    return res;
}

// 定义一个函数,用于测试Diffie-Hellman加密算法
void test() {
    // 定义公共参数p和g,这两个参数可以公开
    int p = 23; // 一个大素数
    int g = 5; // 一个小于p的整数
    printf("Public parameters: p = %d, g = %d\n", p, g);

    // 定义私有参数a和b,这两个参数不对外公开
    int a = rand() % p; // A方随机选择一个小于p的整数作为私有参数
    int b = rand() % p; // B方随机选择一个小于p的整数作为私有参数
    printf("Private parameters: a = %d, b = %d\n", a, b);

    // 定义公开参数A和B,这两个参数可以互相交换
    int A = mod_pow(g, a, p); // A方计算g的a次方模p的结果作为公开参数
    int B = mod_pow(g, b, p); // B方计算g的b次方模p的结果作为公开参数
    printf("Public parameters: A = %d, B = %d\n", A, B);

    // 定义共享密钥s,这个结果是相同的
    int s1 = mod_pow(B, a, p); // A方计算B的a次方模p的结果作为共享密钥
    int s2 = mod_pow(A, b, p); // B方计算A的b次方模p的结果作为共享密钥
    printf("Shared secret: s1 = %d, s2 = %d\n", s1, s2);
}

// 主函数,调用测试函数
int main() {
    test();
    return 0;
}

设计思路

Diffie-Hellman密钥交换算法的设计思路是基于以下的想法:

两个通信方,比如说A和B,想要通过一个公开的不安全的信道,协商出一个共享的密钥,用于后续的对称加密通信。
他们首先选择一个大素数p和一个小于p的整数g,作为公共的参数,任何人都可以知道这两个数。
然后,A和B各自随机选择一个小于p的私有数a和b,作为自己的私钥,不对外公开。
接着,A和B分别计算g的a次方模p和g的b次方模p的结果,作为自己的公钥,互相交换这两个数。
最后,A和B利用对方的公钥和自己的私钥,计算出g的ab次方模p或者g的ba次方模p的结果,作为共享的密钥。由于模幂运算的性质,这两个结果是相同的。
这样,A和B就通过两轮信息交换,实现了密钥协商的过程。由于离散对数问题和计算性Diffie-Hellman问题的难度,即使有人知道了p、g、g的a次方模p和g的b次方模p这四个数,也很难推算出a、b或者g的ab次方模p。因此,这个算法可以保证密钥的安全性。更多细节和证明可以参考这篇文章tink或这篇文章tink。

结果示意

在这里插入图片描述

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

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

相关文章

P1525 [NOIP2010 提高组] 关押罪犯(并查集)

[NOIP2010 提高组] 关押罪犯 题目描述 S 城现有两座监狱&#xff0c;一共关押着 N N N 名罪犯&#xff0c;编号分别为 1 − N 1-N 1−N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久&#xff0c;如果客观条件具备则随时可能爆发冲突。我们用“怨气值”&#x…

编程每日一练(多语言实现)基础篇:满足abcd=(ab+cd)^2的数 (增加Go语言实现)

文章目录 一、实例描述二、技术要点三、代码实现3.1 C 语言实现3.2 Python 语言实现3.3 Java 语言实现3.4 JavaScript 语言实现3.5 Go 语言实现 一、实例描述 假设 abcd 是一个四位整数&#xff0c;将它分成两段&#xff0c;即 ab 和 cd&#xff0c;使之相加求和后再平方。求满…

linux入门---信号量

什么是信号量 信号量的本质是一个计数器&#xff0c;通常用来表示公共资源中资源数量多少&#xff0c;公共资源是指可以被多个进程同时访问的资源&#xff0c;访问没有被保护的公共资源时可能出现数据不一致的问题&#xff0c;比如说一个进程对公共资源执行一些写操作&#xf…

Python 数据分析与挖掘(一)

Python 数据分析与挖掘&#xff08;数据探索&#xff09; 数据探索 1.1 需要掌握的工具&#xff08;库&#xff09; 1.1.1 Nump库 Numpy 提供多维数组对象和各种派生对象&#xff08;类矩阵&#xff09;&#xff0c;利用应用程序接口可以实现大量且繁琐的数据运算。可以构建…

一文搞懂如何求MOS管的等效阻抗

首先先明确方法论&#xff0c;求等效电阻有多种方法&#xff0c;这里使用加压求流法&#xff0c;即我们要求从MOS的哪端看进去等效阻抗&#xff0c;就在哪个端口加一个电压源&#xff0c;并将原电路所有独立源置零&#xff08;电压源短路&#xff0c;电流源断路&#xff09;&am…

【MySQL】MySQL 官方安装包形式

MySQL 官方提供3种包&#xff1a; 1. 源码包 mysql-5.7.42.tar.gz mysql-5.7.42-aarch64.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.34.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.42.tar.gz需要用户根据自己的CPU架构选择对应的…

文心一言 VS 讯飞星火 VS chatgpt (103)-- 算法导论10.1 1题

一、用go语言&#xff0c;仿照图 10-1&#xff0c;画图表示依次执行操作 PUSH(S&#xff0c;4)、PUSH(S&#xff0c;1)、PUSH(S&#xff0c;3)、POP(S)、PUSH(S&#xff0c;8)和 POP(S)每一步的结果&#xff0c;栈 S初始为空&#xff0c;存储于数组 S[1…6]中。 文心一言&…

国庆10.01

TCPselect 代码 服务器 #include<myhead.h> #include<sqlite3.h> #define PORT 6666 //端口号 #define IP "192.168.0.104" //IP地址//键盘事件 int jp(fd_set tempfds,int maxfd) {char buf[128] ""; //用来接收数据char buf1[128] …

RHEL8.0安装+基础命令练习+discuz(lamp)论坛搭建

上课练习环境&#xff1a; RHEL8.0系统镜像下载&#xff1a; 链接1&#xff1a;https://pan.baidu.com/s/1wX2j-aTO1VRcHQYpCDYnEg 提取码&#xff1a;6buv 链接2&#xff1a;https://ws28.cn/f/32i4oq8p5r1 &#xff08;下载完2个文件后只需要解压001&#xff0c;推荐压缩…

树莓派4B串口通信配置方式

目录 1树莓派4B的安装&#xff1a; 1.1安装Serial与使用 1.1.1安装serial 1.1.2打开串口 1.2设置硬件串口为GPIO串口&#xff08;修改串口映射关系&#xff09; 1.2.1修改配置文件 2.1minicom串口 2.1.1安装minicom 这篇博客源于&#xff1a;工创赛。需要让树莓派与STM…

Java集合处理Stream流使用解析

Stream Stream是Java 8引入的一个新的API&#xff0c;用于处理集合数据的流式操作。它提供了一种更简洁、更灵活的方式来处理集合数据&#xff0c;可以实现更高效的数据处理和转换。 使用Stream&#xff0c;可以通过一系列的操作来对集合数据进行筛选、映射、排序、聚合等操作…

SpringBoot终极讲义第一章笔记

01.Spring Boot简介 1.Spring的本质和作用 spring的本质就是一个"容器",它负责创建并管理容器中的对象(组件,也称为Bean),并管理组件之间的依赖关系(何为依赖关系:A组件需要调用B组件方法,称为A依赖于B) 因此学习Spring最常用的两个注解: Component:将被修饰的类…

使用VSCODE 调试ros2具体设置

vscode 调试 ROS2 张得帅&#xff01; 于 2023-09-09 15:39:39 发布 456 收藏 1 文章标签&#xff1a; vscode ros2 版权 1、在下列目录同层级找到.vscode文件夹 . ├── build ├── install ├── log └── src 2、 安装ros插件 3、创建tasks.json文件&#xff0c;添…

真正理解浏览器渲染更新流程

浏览器渲染更新过程 文章目录 浏览器渲染更新过程帧维度解释帧渲染过程一些名词解释Renderer进程GPU进程rendering(渲染) vs painting(绘制)⭐位图纹理Rasterize(光栅化) 1. 浏览器的某一帧开始&#xff1a;vsync2. Input event handlers3. requestAnimationFrame4. 强制重排(可…

Git/GitHub/Idea的搭配使用

目录 1. Git 下载安装1.1. 下载安装1.2. 配置 GitHub 秘钥 2. Idea 配置 Git3. Idea 配置 GitHub3.1. 获取 GitHub Token3.2. Idea 根据 Token 登录 GitHub3.3. Idea 提交代码到远程仓库3.3.1. 配置本地仓库3.3.2. GitHub 创建远程仓库1. 创建单层目录2. 创建多层目录3. 删除目…

【数据结构】二叉树链式结构补充和二叉树的顺序结构及实现

&#x1f407; &#x1f525;博客主页&#xff1a; 云曦 &#x1f4cb;系列专栏&#xff1a;数据结构 &#x1f4a8;吾生也有涯&#xff0c;而知也无涯 &#x1f49b; 感谢大家&#x1f44d;点赞 &#x1f60b;关注&#x1f4dd;评论 文章目录 前言&#x1f4da;一、二叉树链…

机器人过程自动化(RPA)入门 8. 异常处理、调试和日志记录

有时,自动化程序可能无法执行。为了处理此类情况,我们使用异常处理活动。在本章中,我们将从UiPath中可用的各种类型的异常处理方法、您可能遇到的异常以及如何处理它们开始。我们还将学习日志记录。本章涉及的一个重要主题是调试,以检查工作流是否正常工作,并更正任何错误…

Neural Networks for Fingerprint Recognition

Neural Computation ( IF 3.278 ) 摘要&#xff1a; 在采集指纹图像数据库后&#xff0c;设计了一种用于指纹识别的神经网络算法。当给出一对指纹图像时&#xff0c;算法输出两个图像来自同一手指的概率估计值。在一个实验中&#xff0c;神经网络使用几百对图像进行训练&…

Python学习之索引与切片

Python学习之索引与切片 s “0abcdefghijklmnopqrstuvwxyz”&#xff0c;第一个元素‘0’&#xff0c;索引号为0&#xff0c;最后一个元素‘z’&#xff0c;索引号为26 1. s[0]获取索引号为0的元素 2. s[1:3]获取索引号为1的元素&#xff0c;直到但不包括索引号为3的元素。即…

大数据-玩转数据-Flink Sql 窗口

一、说明 时间语义&#xff0c;要配合窗口操作才能发挥作用。最主要的用途&#xff0c;当然就是开窗口然后根据时间段做计算了。Table API和SQL中&#xff0c;主要有两种窗口&#xff1a;分组窗口&#xff08;Group Windows&#xff09;和 含Over字句窗口&#xff08;Over Win…