本文是对之前自学密码学的一个总结,包含了一些总结总结的一些有趣密码的破解方式和自己写的代码。有些是CTF大佬搭建的CTF题目服务器上寻的题,感谢大佬们搭建的平台(题目需 中南大学 内网)。那么开始:
目 录
一、古典密码······
1.移位密码解密·············
2.仿射密码揭秘·············
3.列换位密码解密············
二、现代密码······
1.维吉尼亚密码解密···········
2.Many-Time-Pad攻击··········
三、安全协议······
1.数字签名···············
实验一 古典密码学
1、移位密码解密:
阅读题目代码,可以理解其加密具体思路,题目部分关键代码:
密钥为随机生成:
int offset = rand() % 51 % 26; //随机生成
加密方式:
for(int i = 0; i < 511; ++i){
if(isupper(origin[i])){
casear[i] = (origin[i] - 'A' + offset) % 26 + 'A';
}else if(islower(origin[i])){
casear[i] = (origin[i] - 'a' + offset) % 26 + 'a';
}else{casear[i] = origin[i];} //大小写相同密钥,符号不加密
综上所述,由于密钥空间只有26,暴力破解最简单,源代码如下:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAX 1000
int main()
{
char a[MAX];
char m[MAX];
gets(a);
for(int i=1;i<=26;i++){
printf("ÒÆλ%d:",i);
int j=0;
for(;a[j]!='\0';j++)
{
if(islower(a[j]))m[j]=(a[j]-'a'+i)%26+'a';
else if(isupper(a[j]))m[j]=(a[j]-'A'+i)%26+'A';
else m[j]=a[j];
printf("%c",m[j]);
}
printf("\n");
printf("\n");
}
return 0;
}
代码运行如下,当移位25时接触明文:
服务器提交:
2、仿射密码解密:
经过分析题目,可以看出就是传统仿射加密方式,不同的是符号“ ”、“,”、“.”也参与加密。顺序:“abcdefghijklmnopqrstuvwxyz .,”
解法一:可以计算密钥的传统解法
源代码:
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAX 1000
int ny(int a,int b)
{
int i=1;
while(a*i%b!=1)i++;
return i;
}
int main()
{
char a[MAX];
char m[MAX];
int b[29];int e[1000];
for(int q=0;q<29;q++)b[q]=0;
int i=0,max=0,min=0,va=0,vi=0;int x1,y1,x2,y2;
char txt[]="abcdefghijklmnopqrstuvwxyz .,";
printf("输入密文:");
fgets(a,1000,stdin);
for(i=0;a[i]!='\n';i++)
{
if(islower(a[i])){ b[a[i]-'a']++; e[i]=a[i]-'a';}
else if(a[i]==' '){b[26]++;e[i]=26; } else if(a[i]=='.'){b[27]++;e[i]=27; } else if(a[i]==','){b[28]++;e[i]=28; }
}
for(i=0;i<29;i++){ if(max<b[i]){ max=b[i];va=i;} }
for(i=0;i<29;i++){ if(min<b[i]&&b[i]<max){ min=b[i];vi=i;} }
x1=ny(22,29)*(va-vi)%29; if(x1<0)x1+=29;
y1=(va-x1*27)%29; if(y1<0)y1+=29;
x2=ny(x1,29);
y2=(-x2*y1)%29; if(y2<0)y2+=29;
printf("\n加密密钥:(%d,%d)\n解密密钥:(%d,%d)\n\n",x1,y1,x2,y2);
printf("明文:");
for(int i=0;a[i]!='\n';i++)
{
if(islower(a[i])||a[i]==' '||a[i]==','||a[i]=='.')m[i]=txt[(e[i]*x2+y2-1)%29];
else m[i]=a[i];
printf("%c",m[i]);
}
return 0;
}
结果如下:
解法二:暴力破解+筛选法
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAX 1000
int main()
{
int a=2,b=1;
char txt[]="abcdefghijklmnopqrstuvwxyz .,";
char s[MAX];
printf("输入明文:");
fgets(s,513,stdin);
printf("\n筛选的可能密文:\n________________________________________\n");
for(a=2;a<30;a++)
{
for(b=1;b<30;b++)
{
int k=0;int q=0;
int n[29];for(q=0;q<29;q++)n[q]=0;
char m[511];
for(k=0;k<511;k++)
{
if(islower(s[k]))m[k]=txt[(a*(s[k]-'a')+b-1)%29];
else if(s[k]==' ')m[k]=txt[(a*26+b-1)%29];
else if(s[k]=='.')m[k]=txt[(a*27+b-1)%29];
else if(s[k]==',')m[k]=txt[(a*28+b-1)%29];
else m[k]=s[k];
if(islower(m[k]))n[m[k]-'a']++;
else if(m[k]==' ')n[26]++;
else if(m[k]=='.')n[27]++;
else if(m[k]==',')n[28]++;
}
double g,h;
g=(double)n[26]/511.0;
h=(double)n[4]/511.0;
if(g>0.1&&h>0.1){int i=0;for(i=0;i<511;i++)printf("%c",m[i]);printf("\n________________________________\n");}
}
}
return 0;
}
该代码会对暴力破解结果进行筛选,显示频率满足要求的。
提交结果:
3、列位移密码解密:
分析加密代码,加密原理选取一个行数(1-12),将明文进行分行,纵向读出密文。
解密过程即为逆过程
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
char m[1000];
fgets(m,1000,stdin);
int a=0;
for(int i=0;m[i]!='\n';i++){a++;}
int r=2,i=0,j;
for(r=2;r<13;r++)
{
printf("\n__________________________________\n每行字符数(r值):%d\n",r);
if(a%r==0)
{
int h=a/r;
for(i=0;i<h;i++)
{
for(j=i;j<a;j+=h)
{
printf("%c",m[j]);
}
}
}
else
{
int h=a/r+1;
int c=a%r;
for(i=0;i<h;i++)
{
j=i;
if(i!=h-1)
{
int d=0;
for(d=0;d<c;d++)
{
printf("%c",m[j]);
j+=h;
}
for(d=c;d<r;d++)
{
printf("%c",m[j]);
j=j+h-1;
}
}
else
{
int n=0;
for(n=0;n<c;n++)
{
printf("%c",m[j]);
j+=h;
}
}
}
}
}
}
运行结果: