Kırık şifreyi kır


12

Bir çarpma ve modül yöntemi kullanarak iki sayıyı kaotik bir şekilde çevreleyen basit bir rastgele jeneratör tasarladım. Bunun için harika çalışıyor.

Bir şifre üreticisi olarak kullanacak olsaydım, saldırganın hesaplamayı etkili bir şekilde bir dizi rastgele sayının tohumunu tersine çevirebileceği göz önüne alındığında, bilinen bir düz metin saldırısına karşı savunmasız olurdu.

Şifrenin kırıldığını kanıtlamak için , mümkün olduğunca az güç, CPU zamanı vb. Kullanarak [0; 255] aralığında bir satırda 7 sıfır üreten yasal bir tohum değeri çifti bulun.

JavaScript ile yazılmış rasgele oluşturucu:

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>")
}

Aday sayı çiftlerini test etmek için bir araç yaptım, burada bulunabilir .

Önümüzdeki 3 gün boyunca, hiçbir spoyler izin verilmez , bir cevap sadece bir sayı kümesi içermelidir ve elbette önceki çözücüler tarafından gönderilenlerden farklı bir set olmalıdır. Daha sonra kod yazmanız ve yaklaşımınızı açıklamanız teşvik edilir.

Düzenleme, karantina bitti:
Cevaplar, çözme yöntemini belgelemek için hem benzersiz bir sayı kümesi hem de açıklama ve kod içermelidir.

En zarif çözüm kazanır.

Kayıt için:
Hızlı bir şekilde çözüm bulabilen bir program yazmak zariftir.
Bir GPU'nun özelliklerini daha hızlı yapmak için verimli bir şekilde kullanan bir program yapmak zariftir.
Bir işi "müze" parçası üzerinde yapmak zariftir.
Sadece kalem ve kağıt kullanarak uygulanabilir bir çözüm yöntemi bulmak çok zariftir.
Çözümünüzü öğretici ve kolay anlaşılır bir şekilde açıklamak zariftir.

Birden çok veya çok pahalı bilgisayarlar kullanmak yetersizdir.


Bunun için bir cevap olduğundan emin misiniz?
Dogbert

Evet, bunlardan ~ 256 tanesi var. Ayrıca, modern bir bilgisayar ve doğru programlama göz önüne alındığında, birkaç dakika içinde bir cevap bulmanın mümkün olduğundan da eminim.
aaaaaaaaaaaa

Merak ediyorum, neden GPU'lar zarif ama birden fazla CPU değil?
JB

Çünkü verimli bir şekilde programlamak CPU'lardan daha zordur. GPU'yu gerçekten kullandığınızdan emin olmalısınız, gölgelendiricilerin çoğunun rölantiye alınmasına gerek yok, çünkü diğer bazı alt sistemler tıkanıyor. Ve elbette hala büyük puanları elde etmek için etkili bir algoritma uygulamanız gerekiyor.
aaaaaaaaaaaa

Çalışma kodumu gönderirsem, neredeyse bir sürü tohum çifti göndermiş gibiyim. Oyun zaten bitti mi?
JB

Yanıtlar:


6

C ++, 44014022/1600607120

C ++ 'dadır, 1 GB bellek kullanır ve bu ilk çifti bulmak yaklaşık 45 saniye sürdü. Hepsini bulduğunda zamanı güncelleyeceğim.

Aşağıdaki kod. Önce 4 sıfır üreten tüm çiftleri bulur, sonra bunları basit bir deneme ile kısır ( checkyönteme bakınız ). Biri state1 jeneratörünün ilk 4 düşük dereceli baytını ve ikincisi state2 jeneratörünün ilk 4 düşük dereceli baytının negatifini içeren iki büyük dizi oluşturarak 4 sıfır üreten çiftler bulur. Bu diziler daha sonra sıralanır ve bir eşleşme aranır, bu da başlaması için 4 sıfır çıkaran toplam jeneratöre karşılık gelir.

Diziler bellekte depolanamayacak kadar büyüktür, bu nedenle işi sadece belleğe sığacak şekilde boyutlandırılmış gruplar halinde yapar.

Tam çalışma ~ 12 saat sürecek gibi görünüyor.

Düzenleme : Olası tüm tohumların elde edilmesi sadece ~ 1 saat sürecek şekilde kod geliştirildi. Şimdi tabloları 256 farklı dosyaya, her çıktı baytına bir tane oluşturur. Daha sonra her dosyayı bağımsız olarak işleyebiliriz, böylece verileri yeniden oluşturmamız gerekmez.

Edit : Görünüşe göre 256 alt tabloları tek tek yerine tek tek oluşturabilirsiniz, böylece disk gerekmez. 256MB kullanarak ~ 15 dakikaya kadar çalışma süresi.

#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++;
      }
    }
  }
}

Bir sabit diskin görev için verimli olacak kadar hızlı olacağını düşünmemiştim. İlginç.
aaaaaaaaaaaa
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.