详解密码学中几种常见密码加密与解密
Posted 肥学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解密码学中几种常见密码加密与解密相关的知识,希望对你有一定的参考价值。
目录
题目
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("解密后以上是关于详解密码学中几种常见密码加密与解密的主要内容,如果未能解决你的问题,请参考以下文章