2DES

什么是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分钟左右 视电脑配置而定
求出可能性解之后就修改枚举范围(每一位不确定的都修改)

筛选完后根据题目要求作出后续操作

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值