You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
the_difference_analysis_of_des/hack.h

291 lines
9.0 KiB

#ifndef DES6_HACK_H
#define DES6_HACK_H
#include <iostream>
#include <random>
#include "const.h"
#include "did_table.h"
#include <ctime>
#include <cassert>
#include <set>
#include <algorithm>
using namespace std;
independent_bits_engine<default_random_engine, 64, ull> random_engine;
static DidTable did;
class DesHackHelper {
private:
ull l_match;
ull r_match;
size_t avail_index_num;
int avail_index[8];
public:
DesHackHelper(int mode) {
if (mode == 1) {
l_match = 0x40080000;
r_match = 0x04000000;
avail_index_num = 5;
avail_index[0] = 2;
avail_index[1] = 5;
avail_index[2] = 6;
avail_index[3] = 7;
avail_index[4] = 8;
}
else {
l_match = 0x00200008;
r_match = 0x00000400;
avail_index_num = 2;
avail_index[0] = 1;
avail_index[1] = 4;
}
}
bool inputCheck(const ull& inA, const ull& inB) {
ull inD = calcIp(inA) ^ calcIp(inB);
ull l = left32(inD);
ull r = right32(inD);
return (l == l_match && r == r_match);
}
bool availCheck(const ull& inA, const ull& inB, const ull& outA, const ull& outB) {
return hack(inA, inB, outA, outB, nullptr);
}
bool hack(const ull& inA,
const ull& inB,
const ull& outA,
const ull& outB,
vector<set<int> >* ret_key = nullptr) {
if (!inputCheck(inA, inB)) return false;
ull outD = calcInvPi(outA ^ outB);
ull r6D = right32(outD);
ull c = calcInvPerm(r6D ^ r_match);
ull eA = calcExt(left32(calcInvPi(outA)));
ull eB = calcExt(left32(calcInvPi(outB)));
ull eD = eA ^ eB;
for (unsigned int i = 0; i < avail_index_num; i++) { // each sbox available
int index = avail_index[i] - 1;
int shift_e = (7 - index) * 6;
int sub_eD = (int)((eD & (63ULL << shift_e)) >> shift_e);
int sub_eA = (int)((eA & (63ULL << shift_e)) >> shift_e);
int shift_c = (7 - index) * 4;
int sub_c = (int)((c & (15ULL << shift_c)) >> shift_c);
vector<int> cdt; // candidate
did.get(index, sub_eD, sub_c, cdt);
if (cdt.empty()) {
return false;
}
if (ret_key != nullptr) {
set<int> t;
t.clear();
for (unsigned int j = 0; j < cdt.size(); j++) {
int key_maybe = cdt[j] ^ sub_eA;
if ((*ret_key)[index].count(key_maybe)) {
t.insert(key_maybe);
}
}
(*ret_key)[index].clear();
for (int j : t) {
(*ret_key)[index].insert(j);
}
}
}
return true;
}
void constructCipherPlaintexts(const ull& key, ull& inA, ull& inB, ull& outA, ull& outB, ull in = 0) {// <20><><EFBFBD><EFBFBD>key<65><79><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>
while (true) {
if (in == 0)
inA = random_engine();
else {
inA = in; // ʹ<>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
ull diff = (l_match << 32) | r_match;
inB = calcInvIp(calcIp(inA) ^ diff);
pre_l3 = 0;
outA = desEncrypt(inA, key);
outB = desEncrypt(inB, key);
if (pre_l3 == ((r_match << 32) | l_match)) {
if (availCheck(inA, inB, outA, outB)) {
//<2F>ҵ<EFBFBD><D2B5>˺<EFBFBD><CBBA>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>
printf("--- new cp ---\n");
print_long_hex(inA);
print_long_hex(inB);
print_long_hex(outA);
print_long_hex(outB);
return;
}
}
}
}
};
class DesHacker {
private:
struct PairCp { // a pair of cipher and plaintext һ<><D2BB><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD>
ull inA, inB, outA, outB;
PairCp(const ull& inA, const ull& inB, const ull& outA, const ull& outB) :
inA(inA), inB(inB), outA(outA), outB(outB) {}
};
vector<PairCp> cp_m1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>
vector<PairCp> cp_m2; // <20><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>
DesHackHelper hackerA;
DesHackHelper hackerB;
vector<set<int> > ret_sub_key; // <20><><EFBFBD>뵽ÿ<EBB5BD><C3BF>S<EFBFBD>п<EFBFBD><D0BF>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>64<36>п<EFBFBD><D0BF><EFBFBD><EFBFBD><EFBFBD>
vector<int> enum_binary_position; // <20><>Ҫö<D2AA>ٵ<EFBFBD>14<31><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>λ<EFBFBD><CEBB>
bool found_key; // <20>Ƿ<EFBFBD><C7B7>ҵ<EFBFBD><D2B5><EFBFBD>Կ
ull ret_key; // <20><><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>Կ
ull invPc(ull pc2_out) {
ull pc2_in = calcInvPc2(pc2_out);
ull l = left28(pc2_in);
ull r = right28(pc2_in);
for (int j = 0; j < 10; j++) {
l = (0x0fffffff & (l >> 1)) | ((0x00000001 & l) << 27); // right shift
r = (0x0fffffff & (r >> 1)) | ((0x00000001 & r) << 27);
}
ull pc1_out = (l << 28) | r;
ull pc1_in = calcInvPc1(pc1_out);
return pc1_in;
}
int cur_process = 0; // <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
int max_process = 0;
void binaryEnum(ull num) { // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>ö<EFBFBD><C3B6>
cur_process++;
if (cur_process % 100 == 0)
printf("process: %d/%d\n", cur_process, max_process);
if (cur_process > max_process) {
cur_process = max_process;
}
int enum_max = (1 << enum_binary_position.size()) - 1;
// if ((target_key & invPc(0xfff03fffffff)) == num)
for (int i = 0; i < enum_max; i++) {
int bin = i; //ö<>ٵ<EFBFBD>14λ<34><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ull key = num;
for (int j : enum_binary_position) {
if (bin & 1) {
key |= (1ULL << j);
}
bin >>= 1;
}
if (desEncrypt(cp_m1[0].inA, key) == cp_m1[0].outA) {
ret_key = key;
found_key = true;
break;
}
}
}
void combine(int deep, ull num) { //<2F><>ÿ<EFBFBD><C3BF>S<EFBFBD>п<EFBFBD><D0BF>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>ʹ<EFBFBD><CAB9>DFS
if (deep >= 8) {
ull out = invPc(num);
binaryEnum(out);
return;
}
if (deep == 2) {
combine(deep + 1, num);
return;
}
for (int i : ret_sub_key[deep]) {
int shift = (7 - deep) * 6;
ull cur = num | (((ull)i) << shift);
combine(deep + 1, cur);
if (found_key) return;
}
}
public:
// ull target_key;
DesHacker() :hackerA(1), hackerB(2), found_key(false), ret_key(0) {
random_engine.seed((ull)time(nullptr));
ret_sub_key.resize(8);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 64; j++) {
ret_sub_key[i].insert(j); // һ<><D2BB>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD>
}
}
cp_m1.clear();
cp_m2.clear();
enum_binary_position.clear();
ull enum_mask = calcInvPc1((1ULL << 56) - 1);
ull pc_mask = invPc(0xfff03fffffff) ^ (~enum_mask); // <20><><EFBFBD>е<EFBFBD><D0B5><EFBFBD>0<EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ʱö<CAB1>ٵģ<D9B5>һ<EFBFBD><D2BB>14λ
ull t = pc_mask;
for (int i = 0; i < 64; i++) {
if (!(t & 1))
enum_binary_position.push_back(i);
t >>= 1;
}
}
bool addCipherPlaintexts(ull in1, ull in2, ull out1, ull out2) {
if (hackerA.inputCheck(in1, in2)) {
cp_m1.push_back(PairCp(in1, in2, out1, out2));
return true;
}
else if (hackerB.inputCheck(in1, in2)) {
cp_m2.push_back(PairCp(in1, in2, out1, out2));
return true;
}
else
return false;
}
bool hack() {
found_key = false;
if (cp_m1.empty() || cp_m2.empty()) {
printf("At least one pair of cipher and plaintexts for each mode...\n");
return false;
}
for (unsigned int i = 0; i < cp_m1.size(); i++) {
if (!hackerA.hack(cp_m1[i].inA, cp_m1[i].inB, cp_m1[i].outA, cp_m1[i].outB, &ret_sub_key))
return false;
}
for (unsigned int i = 0; i < cp_m2.size(); i++) {
if (!hackerB.hack(cp_m2[i].inA, cp_m2[i].inB, cp_m2[i].outA, cp_m2[i].outB, &ret_sub_key))
return false;
}
max_process = 1; // <20><><EFBFBD><EFBFBD>չʾ<D5B9><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < 8; i++) {
if (i == 2) continue;
max_process *= ret_sub_key[i].size();
}
combine(0, 0ULL); // <20><>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><DCB5><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>ö<EFBFBD><C3B6>
return found_key;
}
ull getKey() {
if (found_key)
return ret_key;
else {
printf("Key not found...\n");
return 0;
}
}
};
void constructCipherPlaintexts(const ull& key, int mode,
ull& inA, ull& inB, ull& outA, ull& outB,
const ull& given_inA = 0) {
DesHackHelper hacker(mode);
hacker.constructCipherPlaintexts(key, inA, inB, outA, outB, given_inA);
}
#endif //DES6_HACK_H
#pragma once