ทำลายตัวเลขที่หัก


12

ฉันได้ออกแบบตัวสร้างแบบสุ่มอย่างง่ายที่วนสองตัวเลขด้วยวิธีที่วุ่นวายโดยใช้วิธีการคูณและโมดูลัส มันใช้งานได้ดีสำหรับการที่

ถ้าฉันจะใช้มันเป็นเครื่องกำเนิดไฟฟ้ารหัส แต่มันจะมีความเสี่ยงต่อการโจมตีธรรมดาที่รู้จักเนื่องจากผู้โจมตีสามารถย้อนกลับวิศวกรเมล็ดจากชุดของตัวเลขสุ่มในลักษณะที่มีประสิทธิภาพในการคำนวณ

หากต้องการพิสูจน์ตัวเลขที่เสียหายให้ค้นหาคู่ค่าทางกฎหมายที่สร้างค่า 7 ศูนย์ในหนึ่งแถวในช่วง [0; 255] โดยใช้พลังงานเพียงเล็กน้อยเวลา CPU ฯลฯ เท่าที่จะทำได้

นี่คือตัวสร้างแบบสุ่มที่เขียนใน 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 อย่างมีประสิทธิภาพในการทำมันให้เร็วขึ้นเป็นสิ่งที่สวยงาม
การทำงานบนชิ้นส่วนของ "Museumware" นั้นสง่างาม
การค้นหาวิธีการแก้ปัญหาที่สามารถนำมาใช้อย่างเป็นไปได้โดยใช้เพียงปากกาและกระดาษนั้นสวยงามมาก
การอธิบายวิธีการแก้ปัญหาของคุณในลักษณะที่ให้คำแนะนำและเข้าใจได้ง่ายนั้นสง่างาม

การใช้คอมพิวเตอร์หลายเครื่องหรือมีราคาแพงมากนั้นไม่เหมาะสม


คุณแน่ใจหรือไม่ว่ามีคำตอบสำหรับเรื่องนี้?
Dogbert

ใช่มี ~ 256 คน และฉันก็มั่นใจว่าเป็นไปได้ที่จะหาคำตอบในไม่กี่นาทีจากพีซีที่ทันสมัยและการเขียนโปรแกรมที่เหมาะสม
aaaaaaaaaaaa

แค่สงสัยว่าทำไม GPU ถึงมีความสวยงาม แต่ไม่ใช่ซีพียูหลายตัว
JB

เพราะพวกเขายากที่จะเขียนโปรแกรมอย่างมีประสิทธิภาพกว่า CPU คุณต้องทำให้แน่ใจว่าคุณใช้ GPU อย่างแท้จริงไม่มีจุดที่จะทำให้คนขี้เกียจทำงานหนักเพราะระบบย่อยอื่น ๆ กำลังติดขัด และแน่นอนคุณยังต้องใช้อัลกอริธึมที่มีประสิทธิภาพเพื่อทำคะแนนใหญ่
aaaaaaaaaaaa

ถ้าฉันส่งรหัสการทำงานของฉันมันเกือบจะเหมือนกับว่าฉันส่งคู่เมล็ดจำนวนมาก จบเกมแล้วเหรอ?
JB

คำตอบ:


6

C ++, 44014022/164607120

มันอยู่ใน C ++ ใช้หน่วยความจำ 1 GB และใช้เวลาประมาณ 45 วินาทีเพื่อหาคู่แรกนี้ ฉันจะอัปเดตเวลาที่พบพวกเขาทั้งหมด

รหัสด้านล่าง ก่อนอื่นจะพบคู่ทั้งหมดที่สร้างศูนย์ 4 จากนั้นก็ whittles เหล่านั้นลงโดยการทดลองง่าย ๆ (ดูcheckวิธีการ) พบคู่ที่สร้าง 4 ศูนย์โดยการสร้างอาร์เรย์ขนาดใหญ่สองอาร์เรย์อันหนึ่งซึ่งประกอบด้วยไบต์ลำดับต่ำ 4 อันดับแรกของตัวสร้าง state1 และตัวที่สองซึ่งมีค่าลบของไบต์ลำดับต่ำสุด 4 อันดับแรกของตัวสร้าง state2 อาร์เรย์เหล่านี้จะถูกจัดเรียงและค้นหาการจับคู่ซึ่งสอดคล้องกับตัวสร้างโดยรวมที่ส่งออก 4 ศูนย์เพื่อเริ่มต้น

อาร์เรย์มีขนาดใหญ่เกินไปที่จะเก็บไว้ในหน่วยความจำดังนั้นจึงทำงานในขนาดที่พอดีกับหน่วยความจำ

ดูเหมือนว่าการดำเนินการทั้งหมดจะใช้เวลาประมาณ 12 ชั่วโมง

แก้ไข : ปรับปรุงรหัสเพื่อใช้เวลาเพียง 1 ชั่วโมงในการรับเมล็ดที่เป็นไปได้ทั้งหมด ตอนนี้มันสร้างตารางเป็น 256 ไฟล์ที่แตกต่างกันหนึ่งไฟล์สำหรับแต่ละไบต์แรกของเอาต์พุต จากนั้นเราสามารถประมวลผลแต่ละไฟล์อย่างอิสระดังนั้นเราไม่จำเป็นต้องสร้างข้อมูลใหม่

แก้ไข : ปรากฎว่าคุณสามารถสร้าง 256 subtables ทีละรายการแทนที่จะเป็นทั้งหมดพร้อมกันดังนั้นไม่จำเป็นต้องใช้ดิสก์ เวลาที่ลดลงเหลือ ~ 15 นาทีโดยใช้ 256MB

#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.