壊れた暗号を破る


12

乗算およびモジュラス法を使用して、2つの数値をカオス的に循環させる単純なランダムジェネレーターを設計しました。そのためにうまく機能します。

しかし、暗号ジェネレータとして使用する場合、攻撃者が一連の乱数からシードをリバースエンジニアリングできるため、既知のプレーンテキスト攻撃に対して脆弱です。

暗号が壊れていることを証明するために、可能な限り少ない電力、CPU時間などを使用して、[0; 255]の範囲で連続して7つのゼロを生成するシード値の正当なペアを見つけます。

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日間、ネタバレ禁止ません。回答には数字のセットのみを含める必要があり、もちろん、以前のソルバーが投稿したものとは異なるセットにする必要があります。その後、コードを投稿してアプローチを説明することをお勧めします。

編集、隔離が終了しました:
回答には、解決方法を文書化するための一意の数値セットと説明とコードの両方を含める必要があります。

最もエレガントなソリューションが勝ちます。

記録のために:
ソリューションをすばやく見つけることができるプログラムを書くことはエレガントです。
GPUの機能を効率的に利用してさらに高速に実行するプログラムを作成するのはエレガントです。
「ミュージアムウェア」で仕事をするのはエレガントです。
ペンと紙だけを使用して実行可能な解決方法を見つけることは非常にエレガントです。
有益でわかりやすい方法でソリューションを説明するのはエレガントです。

複数の、または非常に高価なコンピューターを使用するのは洗練されていません。


これに対する答えがありますか?
ワイリーE.コヨーテ

はい、256個まであります。また、最新のPCと適切なプログラミングがあれば、数分で答えを見つけることができると確信しています。
aaaaaaaaaaaa

不思議に思うのは、なぜGPUは洗練されているのにマルチCPUではないのですか?
JB

CPUよりも効率的にプログラムするのは難しいからです。実際にGPUを使用していることを確認する必要があります。他のサブシステムがボトルネックになっているため、ほとんどのシェーダーをアイドル状態にすることは意味がありません。そしてもちろん、大きなポイントを獲得するための効率的なアルゴリズムを実装する必要があります。
aaaaaaaaaaaa

作業コードを送信すると、ほとんどのシードペアを送信したように見えます。もうゲーム終了?
JB

回答:


6

C ++、44014022/164607120

C ++であり、1 GBのメモリを使用し、この最初のペアを見つけるのに約45秒かかりました。それらがすべて見つかったら、時間を更新します。

以下のコード。最初に4つのゼロを生成するすべてのペアを見つけてから、単純な試行によってそれらを切り詰めます(checkメソッドを参照)。2つの大きな配列を生成して4つのゼロを生成するペアを見つけます。1つはstate1ジェネレーターの最初の4つの下位バイトを含み、2つ目はstate2ジェネレーターの最初の4つの下位バイトの負を含みます。次に、これらの配列はソートされ、一致するものが検索されます。一致は、開始する4つのゼロを出力するジェネレーター全体に対応します。

配列は大きすぎてメモリに格納できないため、メモリにちょうど収まるサイズのバッチで作業を行います。

完全な実行には約12時間かかります。

編集:コードを改善して、可能なすべてのシードを取得するのに1時間しかかからないようにしました。現在では、出力の最初のバイトごとに1つずつ、256の異なるファイルにテーブルを生成します。その後、各ファイルを個別に処理できるため、データを再生成する必要はありません。

編集:256個のサブテーブルを一度にすべてではなく個別に生成できるため、ディスクは不要です。256MBを使用すると、最大15分までの実行時間。

#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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.