详解密码学中几种常见密码加密与解密

题目

11.已知明文:MEET ME AFITER THE TOGO PARTY,分别用以下方法加密,写出加密后的密文。然后完成解密。
(1)Caesar加密,分别用k=3,k= 5加密;
(2) Vigenere密码,k = word:
(3)栅栏式密码;
(4)矩阵置换密码,矩阵3×8,分别用k= 12345678和k= 34127856

凯撒加密法

凯撒加密法,或称恺撒加密、恺撒变换、变换加密,是一种最简单且最广为人知的加密技术。它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。

凯撒加密法通常被作为其他更复杂的加密方法中的一个步骤,例如维吉尼亚密码。凯撒加密法还在现代的ROT13系统中被应用。但是和所有的利用字母表进行替换的加密技术一样,凯撒加密法非常容易被破解,而且在实际应用中也无法保证通信安全。
凯撒加密法的替换方法是通过排列明文和密文字母表,密文字母表示通过将明文字母表向左或向右移动一个固定数目的位置。例如,当偏移量是左移3的时候(解密时的密钥就是3):
明文字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZ 密文字母表:DEFGHIJKLMNOPQRSTUVWXYZABC
使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。需要解密的人则根据事先已知的密钥反过来操作,得到原来的明文。例如:
明文:THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 密文:WKH TXLFN EURZQ IRA
MXPSV RYHU WKH ODCB GRJ
凯撒加密法的加密、解密方法还能够通过同余的数学方法进行计算。首先将字母用数字代替,A=0,B=1,…,Z=25。此时偏移量为n的加密方法即为:
En(x)=(x+n)mod26{\displaystyle E_{n}(x)=(x+n)\mod 26} 解密就是:
Dn(x)=(x−n)mod26{\displaystyle D_{n}(x)=(x-n)\mod 26}

代码实现

若代码粘贴时有问题可在下方领取

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

void Encry();//凯撒加密
void Decry();//解密 
 
char Encry(char strl[],int key)//向右 移动key 
{
	//printf("%d\n",&strl);
	for(int i=0;i<strlen(strl);i++)
	{
		if(strl[i]>='A'&&strl[i]<='Z')
		{
			strl[i]=((strl[i]-'A')+key)%26+'A';
		}
		else if(strl[i]>='a'&&strl[i]<='z')
		{
			strl[i]=((strl[i]-'a')+key)%26+'a';
		}
	}
	return *strl;
}
void Decry(char *strl,int key)
{
	key=26-key;
	for(int i=0;i<strlen(strl);i++)
	{
		if(strl[i]>='A'&&strl[i]<='Z')
		{
			strl[i]=((strl[i]-'A')+key)%26+'A';
		}
		else if(strl[i]>='a'&&strl[i]<='z')
		{
			strl[i]=((strl[i]-'a')+key)%26+'a';
		}
	}
}

int main()
{
	int ans,key,flag=1; 
	char strl[100];
	while(flag)
	{
		
		printf("               **Caesar加密或解密菜单**\n\n\n");
		printf("--1·加密\n\n");
		printf("--2·解密\n");
		printf("请输入1或2选择功能:");
		scanf("%d",&ans);
		printf("请输入要加密或解密的字符串:");
		scanf(" %[^\n]",&strl);
		//gets(strl);
		printf("请输入加密或解密密钥:");
		scanf("%d",&key); 
		switch(ans)
		{
			case 1:
				{
					*strl=Encry(strl,key);
					printf("%s\n",&strl);
				}
				break;
			case 2:
				{
					Decry(strl,key);
					printf("%s\n",&strl);
				}
				break;
			default:
				break;
			
		}
		printf("是否结束(输入0为结束/1则继续):");
		scanf("%d",&flag); 
	}


	return 0;
}

结果展示:
在这里插入图片描述

维吉尼亚密码

维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。

在这里插入图片描述
若代码粘贴时有问题可在下方领取

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

void Encry();//维吉尼亚加密
void Decry();//解密 
void GetKey();
 
void Encry(char *PTstr,char *Kstr)
{
	for(int i=0;i<strlen(PTstr);i++)
	{
		if(PTstr[i]>='A'&&PTstr[i]<='Z')
		{
			PTstr[i]=(PTstr[i]+Kstr[i])%26+'A';
		}
//		else if(PTstr[i]>='a'&&PTstr[i]<='z')
//		{
//			PTstr[i]=(PTstr[i]+Kstr[i])%26+'a';
//		}
	}
}

void Decry(char *strl,char *Kstr)
{
	for(int i=0;i<strlen(strl);i++)
	{
		if(strl[i]>='A'&&strl[i]<='Z')
		{
			strl[i]=(strl[i]-Kstr[i])%26+'A';
		}
//		else if(strl[i]>='a'&&strl[i]<='z')
//		{
//			strl[i]=((strl[i]-Kstr[i])+26)%26+'a';
//		}
	}
}

//MEET ME AFITER THE TOGO PARTY
void GetKey(char *key,int PTlen)
{
	int len=strlen(key);
	for(int i=0;i<PTlen;i++)
	{
		if(key[i]>='a'&&i<len)//将小写转为大写 
		{
			key[i]=key[i]-32;
		}
		if(i>=len)
		{
			key[i]=key[i-len];
		}
	}
}

int main()
{
	int ans,flag=1; 
	char plaintext[100];
	char key[50];
	while(flag)
	{
		
		printf("               **Vigenere加密或解密菜单**\n\n\n");
		printf("--1·加密\n\n");
		printf("--2·解密\n");
		printf("请输入1或2选择功能:");
		scanf("%d",&ans);
		printf("请输入要加密或解密的字符串:");
		scanf("%[^\n]",&plaintext);
		//gets(strl);
		printf("请输入加密或解密密钥关键字:");
		scanf("%[^\n]",&key);
		switch(ans)
		{
			case 1:
				{
					GetKey(key,strlen(plaintext));
					Encry(plaintext,key);
					printf("%s\n",&plaintext);
				}
				break;
			case 2:
				{
					GetKey(key,strlen(plaintext));
					Decry(plaintext,key);
					printf("%s\n",&plaintext);
				}
				break;
			default:
				break;
			
		}
		printf("是否结束(输入0为结束/1则继续):");
		scanf("%d",&flag); 
	}


	return 0;
}

在这里插入图片描述

栅栏密码

①把将要传递的信息中的字母交替排成上下两行。
②再将下面一行字母排在上面一行的后边,从而形成一段密码。
③例如:
明文:THE LONGEST DAY MUST HAVE AN END
加密:
1、把将要传递的信息中的字母交替排成上下两行。
T E O G S D Y U T A E N N
H L N E T A M S H V A E D
2、 密文:
将下面一行字母排在上面一行的后边。
TEOGSDYUTAENN HLNETAMSHVAED
解密:
先将密文分为两行
T E O G S D Y U T A E N N
H L N E T A M S H V A E D
再按上下上下的顺序组合成一句话
明文:THE LONGEST DAY MUST HAVE AN END

代码
若代码粘贴时有问题可在下方领取

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

void Encry();//栅栏密码加密
void Decry();//解密 
 
void Encry(char *PTstr)
{
	int len=strlen(PTstr),flag=0,count=0;
	char pre[(len+1)/2];//无论奇偶都加一,主要练习指针其实完全没必要建立pre和rear可以直接在PTstr操作 
	char rear[(len+1)/2];
	char *p=pre,*r=rear; 
	for(int i=0;i<len;i++)
	{
		if(PTstr[i]!=' ')
		{
			if(flag==0) 
			{
				*p=PTstr[i];
				p=p+1;
				flag=1;
			}
			else
			{
				*r=PTstr[i];
				r=r+1;
				flag=0;
			}
		}
		else
		{
			count++;
		}
	}
	*p='\0';
	*r='\0';
	printf("加密后得到:");
	printf("%s",pre);
	printf("%s\n",rear);
}
//MEET ME AFITER THE TOGO PARTY
void Decry(char *strl)
{
	int len=strlen(strl),flag=0;
	char *p=strl;
	char *r=&strl[((len+1)/2)];
	printf("解密后得到:");
	for(int i=0;i<len;i++)
	{
		if(flag==0)
		{
			printf("%c",*p);
			p++;
			flag=1;
		
		}
		else 
		{
			
			printf("%c",*r);
			r++;
			flag=0;
		
		}
	}
}


int main()
{
	int ans,flag=1; 
	char plaintext[100];
	char key[50];
	while(flag)
	{
		
		printf("               **栅栏密码加密或解密菜单**\n\n\n");
		printf("--1·加密\n\n");
		printf("--2·解密\n");
		printf("请输入1或2选择功能:");
		scanf("%d",&ans);
		printf("请输入要加密或解密的字符串:");
		scanf(" %[^\n]",&plaintext);
		//gets(strl);
		switch(ans)
		{
			case 1:
				{
					Encry(plaintext);
				}
				break;
			case 2:
				{
					Decry(plaintext);
				}
				break;
			default:
				break;
			
		}
		printf("\n是否结束(输入0为结束/1则继续):");
		scanf("%d",&flag); 
	}

	return 0;
}

在这里插入图片描述

矩阵置换密码

置换也是一个简单的换位,每个置换都可以用一个置换矩阵Ek来表示。每个置换都有一个与之对应的逆置换Dk。置换密码的特点是仅有一个发送方和接受方知道的加密置换(用于加密)及对应的逆置换(用于解密)。它是对明文L长字母组中的字母位置进行重新排列,而每个字母本身并不改变。

如下:
在这里插入图片描述
代码:此次解法是适用于3*8矩阵其实稍加变换把里面的矩阵行列变为可出入的变量即可变成万能解:
若代码粘贴时有问题可在下方领取

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

void Encry();//矩阵置换加密
void Decry();//解密 
 
 //此次解法比较低级只针对3*8矩阵 
void Encry(char *PTstr,char *k)
{
	char matrix[3][8],*p;
	int row=0,col=0,flag=0;
	p=PTstr;
	while(flag<strlen(PTstr))//构建矩阵 
	{
		if(*p!=' ')
		{
			matrix[row][col]=*p;
			p++;
			col++;
		}
		else
		{
			p++;
		}
		if(col==8)
		{
			col=0;
			row++;
		}
		flag++;
	}
	printf("矩阵置换密码后得到:");
	char newMatrix[3][8];
	for(int i=0;i<8;i++)
	{
		for(int j=0;j<3;j++)
		{
			int n=*k-48-1;//从零开始需要在减一 
			newMatrix[j][i]=matrix[j][n];
		}
		k++;
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<8;j++)
		{
			printf("%c",newMatrix[i][j]);
		}
	}
}
//MEET ME AFITER THE TOGO PARTY
void Decry(char *strl,char *k)
{
	char matrix[3][8],p;
	int row=0,col=0,flag=0;
	p=strl;
	while(flag<strlen(strl))//构建矩阵 
	{
		if(*p!=' ')
		{
			matrix[row][col]=*p;
			p++;
			col++;
		}
		else
		{
			p;
		}
		if(col==8)
		{
			col=0;
			row++;
		}
		flag++;
	}
	printf("解密后得到:");
	char newMatrix[3][8];
	for(int i=0;i<8;i++)
	{
		for(int j=0;j<3;j++)
		{
			int n=*k-48-1;//从零开始需要在减一 
			newMatrix[j][n]=matrix[j][i];
		}
		k++;
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<8;j++)
		{
			printf("%c",newMatrix[i][j]);
		}
	}
}


int main()
{
	int ans,flag=1; 
	char plaintext[100];
	char key[50];
	while(flag)
	{
		
		printf("               **栅栏密码加密或解密菜单**\n\n\n");
		printf("--1·加密\n\n");
		printf("--2·解密\n");
		printf("请输入1或2选择功能:");
		scanf("%d",&ans);
		printf("请输入要加密或解密的字符串:");
		scanf(" %[^\n]",&plaintext);
		printf("请输入Key的值:");
		scanf(" %[^\n]",&key);
		//gets(strl);
		switch(ans)
		{
			case 1:
				{
					Encry(plaintext,key);
				}
				break;
			case 2:
				{
					Decry(plaintext,key);
				}
				break;
			default:
				break;
			
		}
		printf("\n是否结束(输入0为结束/1则继续):");
		scanf("%d",&flag); 
	}

	return 0;
}

在这里插入图片描述

点击直接资料领取

在资料回复密码学即可获取源码和截图

这里有python,Java学习资料还有有有趣好玩的编程项目,更有难寻的各种资源。反正看看也不亏。

  • 18
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
在Oracle,可以使用DBMS_CRYPTO包的函数来实现MD5加密解密。 MD5加密的步骤如下: 1. 将原始数据转换成二进制数据。 2. 对二进制数据进行填充,使其长度为512的整数倍。 3. 将填充后的数据分成512位的数据块,每个数据块包含16个32位的字。 4. 对每个数据块进行4轮循环运算,每轮运算包含16个步骤,每个步骤都是基于位运算和非线性函数计算得到的。 5. 将最后一个数据块的结果进行累加,并输出128位的MD5值。 下面是使用DBMS_CRYPTO包的函数实现MD5加密解密的示例: ``` -- MD5加密 DECLARE l_text VARCHAR2(32767) := 'hello world'; l_key RAW(2000) := UTL_RAW.CAST_TO_RAW('secret key'); l_hash RAW(16); BEGIN l_hash := DBMS_CRYPTO.HASH(UTL_RAW.CAST_TO_RAW(l_text), DBMS_CRYPTO.HASH_MD5); DBMS_OUTPUT.PUT_LINE('MD5 hash of ' || l_text || ': ' || UTL_RAW.CAST_TO_VARCHAR2(l_hash)); END; -- MD5解密(无法解密) DECLARE l_text VARCHAR2(32767) := 'hello world'; l_key RAW(2000) := UTL_RAW.CAST_TO_RAW('secret key'); l_hash RAW(16); l_decrypt RAW(2000); BEGIN l_hash := DBMS_CRYPTO.HASH(UTL_RAW.CAST_TO_RAW(l_text), DBMS_CRYPTO.HASH_MD5); DBMS_OUTPUT.PUT_LINE('MD5 hash of ' || l_text || ': ' || UTL_RAW.CAST_TO_VARCHAR2(l_hash)); -- MD5是不可逆的加密算法,无法解密。 END; ``` 需要注意的是,MD5是一种不可逆的加密算法,无法对其进行解密。因此,上面的MD5解密示例实际上是无法解密的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥学

感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值