View Single Post
  #5  
Old 10-08-2016, 16:49
dila dila is offline
Friend
 
Join Date: Jan 2010
Posts: 60
Rept. Given: 12
Rept. Rcvd 32 Times in 14 Posts
Thanks Given: 35
Thanks Rcvd at 74 Times in 20 Posts
dila Reputation: 32
Congrats ArC for getting the key(s).

I forgot to post my solution program here before:

Code:
#include <iostream>
#include <sstream>
#include <stdint.h>
#include <vector>
#include <set>

int main(int argc, char* argv[])
{
  /* identity matrix */
  int bits[64][64] = {0};
  for (int i = 0; i < 64; ++i) {
    bits[i][i] = 1;
  }

  /* build the parity check matrix */
  uint32_t s = 0;
  for (int i = 0; i < 10000; ++i) {
    s = s * 1664525 + 1013904223;
    int j = s % 64;
    for (int i = 0; i < 64; ++i) {
      int t = bits[0][i];
      bits[0][i] ^= bits[j][i];
      bits[j][i] ^= t;
    }
  }

  /* right-hand side "known" vector */
  uint64_t r = 0x3141592653589793 ^ 0x1221777f1c3e4341;
  int rv[64] = {0};
  for (int i = 0; i < 64; ++i) {
    rv[i] = (r >> i) & 1;
  }

  /* initialize row permutation lookup table */
  int p[64] = {0};
  for (int i = 0; i < 64; ++i) {
    p[i] = i;
  }

  /* run gaussian elimination */
  std::set<int> bf;
  std::set<int> pbf;
  for (int i = 0; i < 64; ++i) {
    bool ok = false;
    for (int j = i; j < 64; ++j) {
      if (bf.find(p[j]) != bf.end()) {
        continue;
      }
      if (bits[p[j]][i]) {
        int t = p[i];
        p[i] = p[j];
        p[j] = t;
        ok = true;
        break;
      }
    }
    if (!ok) {
      /* system is singular */
      /* reduce it from an NxN system to a (N-1)x(N-1) system */
      pbf.insert(p[i]); /* brute force this bit later */
      bf.insert(i);
      continue;
    }
    for (int j = i+1; j < 64; ++j) {
      if (pbf.find(p[j]) != pbf.end()) {
        continue;
      }
      if (bits[p[j]][i]) {
        for (int k = 0; k < 64; ++k) {
          bits[p[j]][k] ^= bits[p[i]][k];
        }
        rv[p[j]] ^= rv[p[i]];
      }
    }
  }

  std::vector<int> bfv;
  bfv.insert(bfv.end(), bf.begin(), bf.end());

  /* back-substitute to solve */
  std::set<int> solved;
  int bf_max = 1 << bf.size();
  for (int bfc = 0; bfc < bf_max; ++bfc) {
    int v[64] = {0};
    for (size_t i = 0; i < bfv.size(); ++i) {
      v[bfv[i]] = (bfc >> i) & 1; /* insert the bits we are brute forcing */
      solved.insert(bfv[i]);
    }
    for (int i = 0; i < 64; ++i) {
      int j = 64 - i - 1;
      if (bf.find(j) != bf.end()) {
        continue; /* we are guessing this */
      }
      int s = -1;
      int t = rv[p[j]];
      for (int k = 0; k < 64; ++k) {
        if (bits[p[j]][k]) {
          if (solved.find(k) != solved.end()) {
            t ^= v[k];
          } else {
            s = k;
          }
        }
      }
      if (s != -1) {
        /* solved one bit */
        v[s] = t;
        solved.insert(s);
      }
    }

    /* copy the solution to an int */
    uint64_t sol = 0;
    for (int i = 0; i < 64; ++i) {
      sol |= (uint64_t(v[i]) << i);
    }

    /* run the original algorithm */
    uint64_t key = sol;
    uint32_t s = 0;
    for (int i = 0; i < 10000; ++i) {
      s = s * 1664525 + 1013904223;
      int j = s % 64;
      uint64_t a = (key >> j) & 1;
      uint64_t b = (key & 1) << j;
      key ^= a ^ b;
    }

    /* test the soluton */
    r = key ^ 0x1221777f1c3e4341;
    if (r == 0x3141592653589793) {
      std::cout << std::hex << sol << std::endl;
    }

    /* repeat to find all keys */
    solved.clear();
  }

  return 0;
}
Reply With Quote
The Following User Says Thank You to dila For This Useful Post:
Kjacky (10-09-2016)