Розбити зламану шифру


12

Я створив простий випадковий генератор, який циклічно перетворює два числа хаотично, використовуючи метод множення та модуля. Це чудово працює для цього.

Якби я використовував його як генератор шифрів, він, однак, був би вразливий до відомої атаки в прямому тексті, враховуючи, що зловмисник може обернути інженеру насіння з ряду випадкових чисел в обчислювально ефективній формі.

Для підтвердження розбиття шифру знайдіть законну пару насіннєвих значень, які генерують 7 нулів підряд у діапазоні [0; 255], використовуючи якомога менше енергії, часу процесора тощо.

Ось випадковий генератор, написаний на JavaScript:

function seed(state1,state2){
    //Constants
    var mod1=4294967087
    var mul1=65539
    var mod2=4294965887
    var mul2=65537
    function random(limit){
        //Cycle each state variable 1 step
        state1=(state1*mul1)%mod1
        state2=(state2*mul2)%mod2
        //Return a random variable
        return (state1+state2)%limit
    }
    //Return the random function
    return random
}

//Initiate the random generator using 2 integer values,
//they must be in the ranges [1;4294967086] and [1;4294965886]
random=seed(31337,42)
//Write 7 random values in the range [0;255] to screen
for(a=0;a<7;a++){
    document.write(random(256)+"<br>")
}

Я зробив інструмент для тестування пар кандидатів, його можна знайти тут .

Протягом наступних 3 днів не дозволено використання спойлерів , відповідь має містити лише набір цифр, і, звичайно, це має бути інший набір, ніж розміщений попередніми вирішувачами. Після цього вам пропонується розмістити код і пояснити свій підхід.

Редагувати, карантин закінчений:
відповіді повинні містити як унікальний набір номерів, так і пояснення та код для документування способу вирішення.

Виграє найелегантніше рішення.

Для запису:
Написання програми, яка швидко знайде рішення, є елегантною.
Зробити програму, яка ефективно використовує функції графічного процесора, щоб зробити це ще швидше, є елегантним.
Робити роботу над фрагментом «музейного посуду» - це елегантно.
Пошук способу рішення, який можливо використати лише ручкою та папером, дуже елегантний.
Пояснити своє рішення в повчальному та легко зрозумілому вигляді - це елегантно.

Використання декількох або дуже дорогих комп’ютерів не є елегантним.


Ви впевнені, що на це існує відповідь?
Догберт

Так, їх є ~ 256. І я також впевнений, що відповідь можна знайти за кілька хвилин, враховуючи сучасний ПК та правильне програмування.
aaaaaaaaaaaa

Цікаво, чому графічні процесори елегантні, але не декілька процесорів?
JB

Тому що їх складніше програмувати ефективно, ніж процесори. Ви повинні переконатися, що ви фактично використовуєте графічний процесор, немає жодних очок для того, щоб більшість шейдерів працювали на холостому ходу, оскільки якась інша підсистема обмежує вузькі місця. І звичайно, вам все ж доведеться реалізувати ефективний алгоритм, щоб набрати великі бали.
aaaaaaaaaaaa

Якщо я подаю свій робочий код, це майже так, як якщо б я подав велику купу насіннєвих пар. Гра вже закінчилася?
JB

Відповіді:


6

C ++, 44014022/164607120

Він знаходиться в C ++, використовує 1 Гб пам'яті, і знадобилося близько 45 секунд, щоб знайти цю першу пару. Я оновлю час, коли він знайде їх усіх.

Код нижче. Він спочатку знаходить усі пари, які генерують 4 нулі, а потім відбиває їх шляхом простого випробування (див. checkМетод). Він знаходить пари, які генерують 4 нулі, генеруючи два великих масиви, один, який містить перші 4 байти низького порядку генератора state1, а другий, який містить від’ємник перших 4 байтів низького порядку генератора state2. Потім ці масиви сортують та шукають відповідність, яка відповідає загальному генератору, що виводить 4 нулі для запуску.

Масиви занадто великі, щоб зберігати їх у пам'яті, тому вона робить роботу партіями розміром, щоб просто вміститись у пам'яті.

Схоже, повний пробіг займе ~ 12 годин.

Редагування : Поліпшений код, щоб отримати лише всі можливі насіння. Тепер він генерує таблиці в 256 різних файлів, по одному на кожен перший байт виводу. Потім ми можемо обробити кожен файл самостійно, щоб нам не довелося регенерувати дані.

Редагувати : Виявляється, ви можете генерувати 256 підтаблиць окремо, а не всі одразу, тому диск не потрібен. Час роботи до ~ 15 хвилин, використовуючи 256 Мб.

#include <stdio.h>
#include <stdint.h>
#include <algorithm>
using namespace std;

#define M1 65539
#define N1 4294967087
#define M2 65537
#define N2 4294965887
#define MATCHES 7

// M^-1 mod N                                                                                                                                                        
#define M1_INV 3027952124
#define M2_INV 1949206866

int npairs = 0;

void check(uint32_t seed1, uint32_t seed2) {
  uint32_t s1 = seed1;
  uint32_t s2 = seed2;
  for (int i = 0; i < MATCHES; i++) {
    s1 = (uint64_t)s1 * M1 % N1;
    s2 = (uint64_t)s2 * M2 % N2;
    if (((s1 + s2) & 0xff) != 0) return;
  }
  printf("%d %u %u\n", npairs++, seed1, seed2);
}

struct Record {
  uint32_t signature; // 2nd through 5th generated bytes                                                                                                             
  uint32_t seed;      // seed that generated them                                                                                                                    
};
// for sorting Records                                                                                                                                               
bool operator<(const Record &a, const Record &b) {
  return a.signature < b.signature;
}

int main(int argc, char *argv[]) {
  Record *table1 = (Record*)malloc((N1/256+1)*sizeof(*table1));
  Record *table2 = (Record*)malloc((N2/256+1)*sizeof(*table2));

  for (int i = 0; i < 256; i++) {  // iterate over first byte                                                                                                        
    printf("first byte %x\n", i);

    // generate signatures (bytes 2 through 5) for all states of generator 1                                                                                         
    // that generate i as the first byte.                                                                                                                            
    Record *r = table1;
    for (uint64_t k = i; k < N1; k += 256) {
      uint32_t sig = 0;
      uint32_t v = k;
      for (int j = 0; j < 4; j++) {
        v = (uint64_t)v * M1 % N1;
        sig = (sig << 8) + (v & 0xff);
      }
      r->signature = sig;
      r->seed = k;
      r++;
    }
    Record *endtable1 = r;

    // generate signatures (bytes 2 through 5) for all states of generator 2                                                                                         
    // that generate -i as the first byte.                                                                                                                           
    r = table2;
    for (uint64_t k = (-i & 0xff); k < N2; k += 256) {
      uint32_t sig = 0;
      uint32_t v = k;
      for (int j = 0; j < 4; j++) {
        v = (uint64_t)v * M2 % N2;
        sig = (sig << 8) + (-v & 0xff);
      }
      r->signature = sig;
      r->seed = k;
      r++;
    }
    Record *endtable2 = r;

    sort(table1, endtable1);
    sort(table2, endtable2);

    // iterate through looking for matches                                                                                                                           
    const Record *p1 = table1;
    const Record *p2 = table2;
    while (p1 < endtable1  && p2 < endtable2) {
      if (p1->signature < p2->signature) p1++;
      else if (p1->signature > p2->signature) p2++;
      else {
        check((uint64_t)p1->seed * M1_INV % N1, (uint64_t)p2->seed * M2_INV % N2);
        // NOTE: may skip some potential matches, if p1->signature==(p1+1)->signature or p2->signature==(p2+1)->signature                                            
        p1++;
      }
    }
  }
}

Я не думав, що жорсткий диск буде досить швидким, щоб бути ефективним для виконання завдання. Цікаво.
aaaaaaaaaaaa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.