什么是2DES:
就是对明文用不同密钥加密了两次(真正的3DES是用不同的密钥加密再解密再加密)。
为什么不安全:
2DES不安全在于可以中间相遇攻击大幅度减小求密钥的运算量:假设已经获得了明文和密文,对密钥空间2^56的所有可能求明文的加密结果并存储至数组,再对密钥空间所有可能求密文的解密结果看看在不在数组里面,如果在就称为中间相遇,这种攻击方法复杂度只略大于2^57,显著低于加密两次用到112位密钥2^112。
但是2^57对一般的电脑来说运算量依旧很高,所以CTF的题中肯定有条件限制。
实践中发现两个明文加密的时候可能得到相同的密文 不同的位上字节大致变化正负1 因此在中间相遇的时候可以先筛选出一个疑似答案 然后对每一位±5以内再次查找所有可能的值 c++语言实现如下
前提要知道明文,密文
本题要求的是key1和key2
#include <stdio.h>
#include <string.h>
#include <vector>
#include <openssl/des.h>
#pragma comment(lib,"libeay32.lib")
#pragma comment(lib,"ssleay32.lib")
void encrypt(unsigned char bufin[], unsigned char bufout[], unsigned char key[])
{
DES_cblock *pin, *pout;
des_key_schedule ks;
pin = (DES_cblock*)bufin;
pout = (DES_cblock*)bufout;
des_set_key((DES_cblock *)key, ks);
des_ecb_encrypt(pin, pout, ks, DES_ENCRYPT);
}
void decrypt(unsigned char bufin[], unsigned char bufout[], unsigned char key[])
{
DES_cblock *pin, *pout;
des_key_schedule ks;
pin = (DES_cblock*)bufin;
pout = (DES_cblock*)bufout;
des_set_key((DES_cblock *)key, ks);
des_ecb_encrypt(pin, pout, ks, DES_DECRYPT);
}
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
char possible[300];
map<string ,vector<string> > mymap;
string change(unsigned char str[]){
char ans[15];
string ret;
for(int i=0;i<8;i++){
sprintf(ans,"%02x",str[i]);
ret+=ans;
}
return ret;
}
int main(){
int i,j,k,m,q;
for(i=0;i<=25;i++) possible[i]='a'+i;
for(i=26;i<=51;i++) possible[i]='A'+i-26;
for(i=52;i<=61;i++) possible[i]='0'+i-52;
for(i=0;i<=61;i++) printf("%c",possible[i]);
unsigned char key1[]="CTF{0000";//已知量
//对密文进行加密 key1可以枚举
unsigned char bufin[8]={0};
unsigned char bufout[8];
for(i=0;i<=61;i++){
for(j=0;j<=61;j++){
for(k=0;k<=61;k++){
for(m=0;m<=61;m++){
key1[4]=possible[i];
key1[5]=possible[j];
key1[6]=possible[k];
key1[7]=possible[m];
encrypt(bufin,bufout,key1);
string out = change(bufout);
string k = change(key1);
//刚开始求可以map<string,string> 实现 一一对应 不然内存有点受不了
mymap[out].push_back(k);
}
}
}
printf("%d\n",i);//计数器 监视程序运行情况
}
printf("YES");
unsigned char pwd[8]={0xf6,0xff,0x60,0xa7,0xd1,0xc3,0x94,0x90};
unsigned char mid[8];
unsigned char key2[]="0_00000}";
for(i=0;i<=25;i++){
for(j=0;j<=25;j++){
for(k=0;k<=10;k++){
for(m=1;m<=15;m++){
for(q=0;q<=25;q++){
key2[0]=possible[i];
key2[2]=possible[j];
key2[3]=key2[6]=possible[k];
key2[4]=possible[m];
key2[5]=possible[q];
decrypt(pwd,mid,key2);
string M=change(mid);
if(mymap.find(M)!=mymap.end()){
for(int h=0;h<mymap[M].size();h++){
cout<<mymap[M][h];
cout<<change(key2);
//getchar();
}
}
}
}
}
}
cout<<i<<endl;
}
getchar();
return 0;
}
求解大概10分钟左右 视电脑配置而定
求出可能性解之后就修改枚举范围(每一位不确定的都修改)
筛选完后根据题目要求作出后续操作