Snippets

Masafumi Yabu katagaitai #10 differential power without SMT Solver

Created by Masafumi Yabu
1
2
3
4
5
6
7
8
9
$ g++ solve.cpp -O3 -fopenmp -o solve

$ time ./solve
Key Found: (1262572609, 2068465998, 1397049649, 909194877)
./solve  488.32s user 0.08s system 627% cpu 1:17.87 total

$ irb
irb(main):001:0> [1262572609, 2068465998, 1397049649, 909194877].pack("N*")
=> "KATA{JINSEI1616}"
//
// Created by nomeaning on 2/24/18.
//
#include <iostream>
#include <cstdint>
#include <vector>
using namespace std;

const int M = 10; // 入力数
uint32_t vs[M][2] = {{1781623155, 1950693744}, {1163420792, 1415932486}, {1379489906, 1735677043}, {1248945014, 1282699074}, {1145525059, 1869035876}, {1985170249, 1649043810}, {2000243553, 1783645803}, {1665291573, 1312312901}, {1683317838, 1313697141}, {1365789552, 1732340020}};

int data[M][657] = 
#include "data.hpp"
;
const uint32_t delta = 0x9e3779b9;
void  solve_single(vector<uint32_t> &ret, const vector<uint32_t> &vs, uint32_t ham, uint32_t col_idx, int shift, uint32_t k) {
    bool ok = true;
    for(int i = 0; i < vs.size(); i++) {
        uint32_t v = vs[i];
        if (shift >= 0) {
            v = v << shift;
        } else {
            v = v >> (-shift);
        }
        uint32_t v2 = (v + k);
        if (__builtin_popcountll(v ^ v2) != data[i][col_idx]) {
            ok = false; break;
        }
    }
    if (ok) {
        ret.push_back(k);
    }
}
void dfs(vector<uint32_t> &ret, const vector<uint32_t> &vs, uint32_t ham, uint32_t col_idx, int shift, int pos, int h = 0, uint32_t cur = 0) {
    if (pos == 32) {
        solve_single(ret, vs, ham, col_idx, shift, cur);
    } else {
        if (h + (32 - pos) < ham) {
            return;
        }
        if (h < ham) {
            dfs(ret, vs, ham, col_idx, shift, pos + 1, h + 1, cur | (1u << pos));
        }
        dfs(ret, vs, ham, col_idx, shift, pos + 1, h, cur);
    }
}

vector<uint32_t> solve_single(const vector<uint32_t> &vs, uint32_t ham, uint32_t col_idx, int shift) {
    vector<uint32_t> ret;
    dfs(ret, vs, ham, col_idx, shift, 0);
    return ret;
}

bool check(uint32_t k0, uint32_t k1, uint32_t k2, uint32_t k3) {
    vector<uint32_t> v0(M), v1(M);
    for (int i = 0; i < M; i++) {
        v0[i] = vs[i][0];
        v1[i] = vs[i][1];
    }
    uint32_t sum = 0;
    for(int i = 0; i < 32; i++) {
        sum += delta;
        for (int j = 0; j < M; j++) {
            uint32_t v = v1[j] << 4;
            uint32_t vt = v + k0;
            if (__builtin_popcount(v ^ vt) != data[j][i * 20 + 18]) {
                return false;
            }
            v0[j] += ((v1[j]<<4) + k0) ^ (v1[j] + sum) ^ ((v1[j]>>5) + k1);
            v1[j] += ((v0[j]<<4) + k2) ^ (v0[j] + sum) ^ ((v0[j]>>5) + k3);
        }
    }
    return true;
}

void solve_k2_k3(uint32_t k0, uint32_t k1) {
    vector<uint32_t> v0(M);
    vector<uint32_t> v1(M);
    for (int i = 0; i < M; i++) {
        v0[i] = vs[i][0];
        v1[i] = vs[i][1];
        v0[i] += ((v1[i] << 4) + k0) ^ (v1[i] + delta) ^ ((v1[i] >> 5) + k1);
    }
    auto k2c = solve_single(v0, data[0][12], 26, 4),
         k3c = solve_single(v0, data[0][13], 29, -5);
    for (auto k2: k2c) {
        for (auto k3: k3c) {
            // cerr << "Key candidate: " << k0 << ',' << k1 << ',' << k2 << ','  << k3 << endl;
            if (check(k0, k1, k2, k3)) {
                cout << "Key Found: (" << k0 << ", " << k1 << ", "<< k2 << ", " << k3 << ")" << endl;
            }
        }
    }
}

void solve_k0_k1() {
    vector<uint32_t> v1(M);
    for (int i = 0; i < M; i++) {
        v1[i] = vs[i][1];
    }
    auto k0c = solve_single(v1, data[0][10], 18, 4),
         k1c = solve_single(v1, data[0][11], 21, -5);
    #pragma omp parallel for
    for(int i = 0; i < k0c.size() * k1c.size(); i++) {
        solve_k2_k3(k0c[i % k0c.size()], k1c[i / k0c.size()]);
    }
}

int main() {
    solve_k0_k1();
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.