Score:0

เป็นไปได้ไหมที่จะถอดรหัส Linear Congruential Generator ถ้าฉันรู้แค่โมดูลัสของเอาต์พุต

ธง sz

แก้ไขที่แนะนำโดย fgrieu:

ฉันมีจำนวนเต็มหนึ่งร้อย $\{0,1,2,3,4,5\}$ ที่ฉันสงสัยว่าเป็นค่าต่อเนื่องของ $\lfloor x_n/2^{16}\rfloor\bmod6$ คำนวณเป็น $x_{n+1}:=a\cdot x_n+b\bmod m$, กับ $m=2^{31}$, และ $(a,b)\in{(214013,2531011),(22695477,1)}$. ฉันจะตรวจสอบสมมติฐานนั้นได้อย่างไร ค้นหา $(ก,ข)$ ใช้และทำนายสิ่งที่ตามมาในลำดับ?


คำถามเกี่ยวกับ "การใช้งานที่มีความสามารถในภาษาที่คอมไพล์จะใช้เวลาเพียงวินาทีเดียวบนเดสก์ท็อปพีซีสมัยใหม่"

ฉันเขียนโค้ดบางส่วน แต่คาดว่าจะทำงาน 20 ชั่วโมง

ฉันกำลังพยายามหาเมล็ดพันธุ์แบบสุ่ม ก่อนอื่น ฉันป้อนข้อมูลในอาร์เรย์ เนื่องจากฉันไม่รู้ว่าข้อมูลแรกของฉันคือตัวเลขใดที่สร้างโดยเซิร์ฟเวอร์ ฉันจึงต้องค้นหาข้อมูลนั้น ฉันรู้แค่ว่าเซิร์ฟเวอร์ปิดทุกวันพฤหัสบดี 14:00 น. และรีสตาร์ทประมาณ 14:45-15:45 น. ในวันเดียวกัน เมื่อเปิดเซิร์ฟเวอร์ ir จะสร้างตัวเลข 3 ตัวทุกๆ 45 วินาที ข้อมูลที่ฉันมีรวบรวมในวันศุกร์ เวลา 01:50 น. ดังนั้นข้อมูลแรกของฉันอาจเป็นหมายเลข 2400-2640 ของ LCG

ฉันเรียกใช้แรนด์ครั้งแรก 2399 ครั้งเพื่อทิ้งหมายเลข 2399 แรก ต่อไป ฉันวนซ้ำ 241 ครั้งเพื่อค้นหาข้อมูลแรกของฉันคือหมายเลขใดที่สร้างโดยเซิร์ฟเวอร์ (ความไม่แน่นอนของเวลารีสตาร์ทเซิร์ฟเวอร์ 14:45-15:45 น. 240 หมายเลขต่อชั่วโมง)

วิธีการของฉันคือ: ถ้า 2400 x บิต 16 เท่ากับบิต 0 ของ $y_1$จากนั้นฉันจะตรวจสอบบิต 16 ของ x 2401 และบิต 0 ของ $y_2$และอื่น ๆ ถ้าไม่เท่ากันให้เลิกลูปแล้วเริ่มลูปใหม่ เปรียบเทียบ 2401 x กับบิต 0 ของ $y_1$.

วิธีที่ดีกว่าที่จะทำคืออะไร? ฉันเพิ่งเริ่มเรียนรู้ c++ เมื่อสองสัปดาห์ก่อน โปรดยกโทษให้กับความไม่รู้ของฉัน

#รวม <stdio.h>
#รวม <stdlib.h>
#รวม <stdint.h>
#รวมถึง <iostream>
#รวม <inttypes.h>

ใช้เนมสเปซ std;

const int ผลลัพธ์ [3][7] = {
    {0,1,0,1,1,1,1},
    {1,0,1,0,0,0,0},
    {0,1,1,0,1,0,0}
};

ยาว x;

int test_rand (เป็นโมฆะ)
{
    x = 214013 * x + 2531011; // หรือเป็น 22695477*x+1
    กลับ (int)((x >> 16) & 0x7FFF);
};

int onlyx16 (โมฆะ)
{
    x = 214013 * x + 2531011; // หรือเป็น 22695477*x+1
    กลับ (x >> 16) & 1;
};

เป็นโมฆะ chk_seed (เมล็ดยาวที่ไม่ได้ลงนาม)
{
    int d1[241]{};
    int d2[241]{};
    int d3[241]{};

    x = เมล็ดพันธุ์;

    สำหรับ (int i = 0; i < 2399; i++) {
        test_rand();
    }

    สำหรับ (int i = 0; i < 241; i++)
    {
        d1[i] = onlyx16();
        d2[i] = onlyx16();
        d3[i] = onlyx16();
    };

    int ถูกต้อง = 0;

    สำหรับ (int k = 0; k < 236; k++)
    {
        ถูกต้อง = 0;
        สำหรับ (int i = 0; i < 7; i++)
        {
            ถ้า ((d1[i + k]) == ผลลัพธ์[0][i])
            {
                ถูกต้อง += 1;
            }
            อื่น {
                ถูกต้อง = 0;
                หยุดพัก;
            };
            ถ้า ((d2[i + k]) == ผลลัพธ์[1][i])
            {
                ถูกต้อง += 1;
            }
            อื่น {
                ถูกต้อง = 0;
                หยุดพัก;
            };
            ถ้า ((d3[i + k]) == ผลลัพธ์[2][i])
            {
                ถูกต้อง += 1;
            }
            อื่น {
                ถูกต้อง = 0;
                หยุดพัก;
            };
        };
        ถ้า (ถูกต้อง == 21)
        {
            printf("seed 0x%d ใช้ได้\n", seed);
            printf("การคาดการณ์ผลลัพธ์:\n");
            สำหรับ (รอบ int = 0; รอบ < 5; รอบ ++)
            {
                printf("ปัด%d ", ปัด + 1);
                int new_d[3]{};
                สำหรับ (int i = 0; i < 3; i++)
                {
                    new_d[i] = test_rand()% 6;
                    printf("%d", new_d[i]);
                };
                printf("\n");
            }
        };
    }
};

int หลัก ()
{
    สำหรับ (เมล็ดยาวที่ไม่ได้ลงนาม = 0; เมล็ด < 0x100000000; seed++)
        chk_seed(เมล็ดพันธุ์);
};

$x_{n+1} = (a \cdot x_{n} + b) \mod m$

ในสถานการณ์ปกติ $x_{n+1}$ และ $x_n$ เป็นที่รู้จัก. แต่ตอนนี้ฉันรู้แค่ว่า $x_n\mod 6$ และ $x_{n+1}\mod 6$.

ฉันค้นหาเว็บไซต์มากมายบน google แต่พบเพียงคำถามเดียวที่พูดถึงปัญหานี้

การทำนายค่าจาก Linear Congruential Generator

อย่างไรก็ตาม มันไม่ชัดเจนนักและฉันก็ยังไม่รู้ว่าฉันควรทำอย่างไรหลังจากอ่านแล้ว ฉันหวังว่าจะมีคนให้รหัสทางคณิตศาสตร์หรือรหัสตัวอย่างได้ เพื่อที่ฉันจะได้เรียนรู้จากการลองผิดลองถูก

ฉันต้องการค้นหา a, b, m จากนั้นใช้ซอร์สโค้ด C ++ ที่ฉันพบที่นี่เพื่อบังคับเมล็ดพันธุ์

ฉันพบคำตอบที่นี่ซึ่งพูดถึงวิธีหา m แต่ฉันไม่รู้ $x_{n+1}$ และ $x_n$.

https://security.stackexchange.com/questions/4268/cracking-a-linear-congruential-generator

ฉันยังใหม่กับหัวข้อนี้ แต่ฉันอยากจะถอดรหัส PRNG นี้อย่างยิ่ง PRNG นี้ทำให้ฉันทรมานมาก ฉันตัดสินใจเรียนรู้การเขียนโปรแกรมเพราะ PRNG นี้ ขอขอบคุณสำหรับความช่วยเหลือของคุณ!

fgrieu avatar
ng flag
ความยากขึ้นอยู่กับว่า $a$, $b$, $m$ ได้รับหรือไม่ ถ้า $m$ เป็นกำลังของสอง และ ซึ่ง; และมี $x_n\bmod 6$ กี่ตัว หากปัญหาถูกถามสำหรับ LCG เริ่มต้นของ Java: คุณทำ _not_ รับ $n\bmod6$ ที่เอาต์พุต! `rand` ของ MSVC และ Borland ไม่ส่งคืน $x_n$มีรายงานว่าส่งคืนบิต 30..16 (นั่นคือ 15 บิต) ของ $x_n$ ดู [นี้](https://stackoverflow.com/q/6793065/903600) และ [นี้](https://stackoverflow.com/ คิว/14672358/903600). ดังนั้นฉันจึงสงสัยว่า «รู้ ​​$x_n\bmod6$»
fairytale avatar
sz flag
@fgrieu ฉันรู้หนึ่งร้อย $x_n\bmod 6$ ฉันตรวจสอบไฟล์ .exe ในโฟลเดอร์ คอมไพเลอร์ของคนหนึ่งคือ MSVC คอมไพเลอร์ของอีกคนคือ Borland C++ ดังนั้นฉันจึงลองใช้ MSVC และ Borland rand แต่พวกเขาไม่สามารถให้ผลลัพธ์ในอนาคตที่ถูกต้องกับฉันได้ ฉันได้รับ 0-5 เป็นเอาต์พุตเท่านั้น ดังนั้นฉันคิดว่ามันเกิดจาก "%6" from-rand ฉันคิดว่ามันเป็นเรื่องธรรมดาในการรับตัวเลขสุ่มเฉพาะช่วง [แก้ไขโดย mod เพื่อย่อหลายความคิดเห็น]
fgrieu avatar
ng flag
แต่คุณไม่มีข้อบ่งชี้ว่าเป็น $x_n$ ซึ่งนำมา $\bmod6$ ตามที่เขียนไว้ในคำถาม หากเป็นกรณีนี้ และถ้า $m$ เป็นคู่และ $a$ คี่เหมือนปกติ ตัวเลขที่คุณได้รับจะเป็นเลขคี่และเลขคู่แทน คำถามที่คุณต้องการถามอาจเป็น: «ฉันมีจำนวนเต็มหนึ่งร้อยใน $\{0,1,2,3,4,5\}$ ซึ่งฉันสงสัยว่าเป็นค่าติดต่อกันของ $\lfloor x_n/2^{16 }\rfloor\bmod6$ คำนวณเป็น $x_{n+1}:=a\cdot x_n+b\bmod m$, กับ $m=2^{31}$, และ $(a,b)\in\{ (214013,2531011),(22695477,1)\}$ ฉันจะตรวจสอบสมมติฐานนั้นได้อย่างไร ค้นหา $(a,b)$ ที่ใช้ และทำนายสิ่งที่ตามมาในลำดับ?»
fairytale avatar
sz flag
@fgrieu ตกลงลองใช้วิธีนี้กัน ขอบคุณสำหรับข้อเสนอแนะของคุณ ฉันจะ [แก้ไข] คำถามในภายหลังและลองใช้วิธีการของคุณ ตอนนี้ฉันไม่สามารถใช้คอมพิวเตอร์ได้ [แก้ไขโดย mod เพื่อย่อหลายความคิดเห็น]
Fractalice avatar
in flag
กระดาษ "การสร้างตัวแปรจำนวนเต็มแบบตัดทอนใหม่เพื่อให้สอดคล้องกับความสอดคล้องเชิงเส้น" อาจมีความเกี่ยวข้องมาก
Score:3
ธง ng

ตามความคิดเห็นที่แก้ไข คำถามเดิม: OP คาดเดาว่า 100 หลัก $y_n$ ใน $\{0,1,2,3,4,5\}$ ในความครอบครองของพวกเขาจะได้รับโดยใช้นิพจน์ C (++) ที่เทียบเท่ากับ แรนด์()%6 กับ แรนด์() ใช้ PRNG (ไม่ใช่การเข้ารหัส) ตาม Linear Congruential Generator โดยมีรหัสเทียบเท่ากับ

ยาว x;
int rand (โมฆะ) {
  x = 214013*x+2531011; // หรือเป็น 22695477*x+1
กลับ (int)((x>>16)&0x7FFF);
}

สังเกตว่า $x$ เป็นอย่างน้อย 32 บิต แต่มีเพียง 31 บิตลำดับล่างเท่านั้นที่สำคัญเนื่องจาก (x>>16)&0x7FFF และ C การแสดง ไม่ได้ลงนามยาว การคูณด้วยการตัดทอนบิตลำดับสูงที่ไม่พอดีกับตัวแปร

สรุปรายละเอียดการเขียนโปรแกรม การคาดเดาก็คือว่า $x$ วิวัฒนาการต่อ $x_{n+1}:=a\cdot x_n+b\bmod m$ กับ $m=2^{31}$ และ $(ก,ข)$ สำหรับค่าคงที่บางตัวที่เชื่อว่าเป็นอย่างใดอย่างหนึ่ง $(214013,2531011)$ หรือ $(22695477,1)$. และ แรนด์() เอาต์พุตบิต 30â¦16 ของ $x$ ด้วยเหตุนี้ $y_n:=\lชั้น x_n/2^{16}\rชั้น\bmod 6$ จะได้รับสำหรับ $n=0$ ถึง $99$ (โดยเมล็ดเป็นจำนวนเต็มไม่ทราบ $x_{-1}$ ในช่วงที่ไม่มีสาระสำคัญเนื่องจากเท่านั้น $x_{-1}\bmod m$ จะสำคัญ; และเราดีกว่าที่จะพยายามหา $x_0$ ถึงอย่างไร).

OP ถามว่าเป็นไปได้หรือไม่ที่จะยืนยันหรือยืนยันการคาดเดานั้น และ (หากเป็นจริง) จะพบว่าข้อใด $(ก,ข)$ ถูกนำมาใช้และทำนายสิ่งที่ตามมาในลำดับ

ใช่เป็นไปได้ด้วยความมั่นใจที่ยอดเยี่ยม สถานะที่มีประสิทธิภาพของ PRNG ที่พิจารณามี 31 บิต มีเพียงสอง PRNG ที่พิจารณา ซึ่งผ่านได้สำหรับการจำลอง ดังนั้นเราควรจะสามารถค้นหาสถานะของมันและสถานะใดที่ใช้กับอีกเล็กน้อย $31+1=32$ ข้อมูลเล็กน้อย และเราได้รับ $100\cdot\log_2(6)\ประมาณ258.5$ บิตซึ่งจะให้การยืนยันมากมาย

วิธีที่ง่ายที่สุดคือลองคาดเดาทั้งสองอย่าง $(ก,ข)$และสำรวจค่าที่เป็นไปได้ของ $x_0$. มีเพียง $2^{31}$รู้ $y_0$ อนุญาตให้ลดอย่างเป็นระบบโดยปัจจัยของ $6$. ต่อไปนี้ $y_i$ กำจัดเพิ่มเติม $5$ ผู้สมัครออกจาก $6$. หากไม่มีผู้สมัครรายใดรอดทั้งหมด $y_i$, สมมติฐานถูกหักล้าง หากพบการแข่งขันเราจะรู้ว่า $(ก,ข)$ เราใช้ และคำนวณเพิ่มเติมได้ $y_i$. การใช้งานที่มีความสามารถในภาษาที่คอมไพล์จะใช้เวลาเพียงวินาทีเดียวบนเดสก์ท็อปพีซีสมัยใหม่

แต่อาจต้องการทำลายสิ่งนี้แบบเรียลไทม์ด้วย CPU ที่ทันสมัย ​​\$0.5 ที่ทำงานจากแบตเตอรี่ \$0.2 หรือติดอยู่กับ เครื่องคิดเลขที่ตั้งโปรแกรมได้ของปี 1970หรือ อีเนียค. สังเกตว่า $6$ เป็นเลขคู่ และตัวหารคือ $2^{16}$. มันเป็นไปตาม $y_n\bmod 2$ เป็นบิต $16$ ของ $x_n$. ยังตั้งข้อสังเกตว่าตั้งแต่ $m$ เป็นกำลังสอง การเปลี่ยนแปลงบิตอิน $x_n$ ไม่เผยแพร่ไปยังบิตลำดับล่างของ $x_{n+1}$. ถ้าเป็นไปตามนั้นบิต 16 ของ $x_n$ ขึ้นอยู่กับเพียง 17 บิตต่ำของ $x_0$. เรารู้บิต 16 ของ $x_0$จึงต้องทดสอบมากที่สุด $2^{16}$ ตัวเลือกสำหรับบิต 15â¦0 ของ $x_0$. จากนั้นเราสามารถหาอีก 14 บิตตามด้านบน ที่ แบ่งแยกและพิชิต วิธีการจะช่วยให้จัดการกับพารามิเตอร์ที่ใหญ่กว่ามากได้ เช่น ตัวแปร x ประเภท uin64_t และ กลับ x>>33บนซีพียูสมัยใหม่

ฉันสงสัยว่าเราจะทำอย่างไรถ้า $a$, $ข$ และ/หรือ $m$ ไม่เป็นที่รู้จัก


หมายเหตุด้านบน:

  • มันใช้แบบแผนหลักในวิทยาการคอมพิวเตอร์ (และการเข้ารหัสโดยมีข้อยกเว้นเล็กน้อยเช่น DES): บิตจะนับจาก 0 (บิตลำดับต่ำ) ดังนั้นหากจำนวนเต็มไม่เป็นลบ $v$ แสดงเป็นเลขฐานสองเป็น $k$ บิต $b_j$, แล้ว $v=\sum b_j$ กับ $0\le j<k$. ในการประชุม big-endian บิต 0 เขียนไว้ทางด้านขวา: $6\times7=42$ เป็นทศนิยม $110\times111=101010$ ในไบนารี่
  • ตัวแปรคอมพิวเตอร์ x เป็นอย่างน้อย 32 บิต แต่เป็นเพียงลำดับต่ำ 31 บิต (0 ถึง 30) และใช้ใน $x_n$, ดังนั้น $0\le x_n<m=2^{31}$. ผลลัพธ์ของ แรนด์() เป็นอย่างน้อย 16 บิต แต่มีเพียงลำดับต่ำ 15 บิต (0 ถึง 14) สสาร และอื่น ๆ ทั้งหมดเป็นศูนย์ ดังนั้น $0\le$แรนด์()$\le$RAND_MAX$=2^{15}-1$. ถ้า $0\le ฉัน<15$ จากนั้นบิต $เจ$ ของเอาต์พุตของ แรนด์() จับคู่บิต $ญ+16$ ของ x. มันตามด้วยบิต 0 ของ $y_n$ ตรงกับบิต 16 ของ $x_n$.

(นอกเรื่อง) ความคิดเห็นเกี่ยวกับ รหัสปัจจุบัน:

  • มันพยายามใช้การเร่งความเร็วที่ทำได้โดย 6 แม้กระทั่ง ฉันขอยืนยันว่านี่คือ ไม่ ต้องถึงเวลาดำเนินการเป็นวินาที ถ้า
    • เรา สำรวจค่าที่เป็นไปได้ของ $x_0$มากกว่าเมล็ดพันธุ์หลายขั้นตอนก่อนหน้านี้
    • เราใช้สิ่งนั้น $x_0$ เป็น 31 บิต ดังนั้นเราจึงสามารถจำกัดการค้นหาภายนอกเป็น [0, 0x7ffffffff] นั่นคือ $2^{31}$ ผู้สมัคร $x_0$.
    • เราใช้สิ่งที่เรารู้ $y_0$ดังนั้น $x_0=2^{16}\cdot(6\cdot u+ y_0)+v$ สำหรับ $0\le u<\lceil2^{15}/6\rceil$ และ $0\le v<2^{16}$ซึ่งจำกัดไว้ประมาณ $2^{31}/6$ ผู้สมัครรับเลือกตั้ง $x_0$.
    • เราเพิ่มประสิทธิภาพการทดสอบสำหรับการตรวจสอบผู้สมัคร $x_0$ ต่อต้าน $y_1$ ในวงในบน $v$.
  • สาระสำคัญของ ไม่จำเป็น เร่งความเร็ว 6 เป็นเลขคู่ คือให้หาบิต 16â¦0 ของ $x_0$ จับคู่ค่า $y_0$ รวบรวมแล้วบิต 30â¦17 รหัสไม่ได้ทำอย่างนั้น! ด้วยการเร่งความเร็วนั้น เวลาในการดำเนินการจะลดลงเหลือมิลลิวินาที
  • เราต้องการค่าเต็มของ $y_n$ รวบรวมไว้ (ทั้งในการค้นหาที่ไม่ได้ปรับให้เหมาะสม และส่วนที่สองของการค้นหาที่ปรับให้เหมาะสม) แต่ดูเหมือนว่าจะไม่มีในอินพุต ซึ่งผมเดาว่า $y_n\bmod2$. นอกจากนี้ ฉันไม่เข้าใจว่าทำไมมันถึงอยู่ในอาร์เรย์สองมิติ ผลลัพธ์[3][7].
  • เมื่อไร $x_0$ พบ ถ้าจำเป็นต้องค้นหาเมล็ด (หรือค่อนข้างบิต 30â¦0 ของจำนวนนั้น) จำนวนขั้นตอนที่ทราบมาก่อน ซึ่งสามารถทำได้อย่างมีประสิทธิภาพโดยการเดินกลับ LCG โดยใช้ $x_{n-1}:=a^{-1}\,(x_n-b)\bmod m$ ที่ไหน $a^{-1}$ คือ ผกผันแบบแยกส่วน ของ $a$ โมดูโล $m$.

นี่คือรหัสการทำงาน ปราศจาก ตัวเลือกการเร่งความเร็ว (จึงสามารถทำงานกับโมดูลัสการลดขั้นสุดท้ายแบบคี่ได้ $r$ ที่คำถามมี 6). ลองออนไลน์!

#รวม <stdint.h>
#รวม <stdio.h>
#รวม <inttypes.h>

#define A 214013 // สำหรับ VC; 22695477 สำหรับ พ.ศ
#กำหนด B 2531011 // สำหรับ VC; 1 สำหรับ BC
#define R 6 // โมดูลัส ใน [2, 32768]
// static_assert(A > 0 && A % 8 == 5, "mod 8 ต้องเป็น 5");
// static_assert(B > 0 && B % 2 == 1, "B mod 2 ต้องเป็น 1");
// static_assert(R >= 2 && R <= 32768, "R ต้องอยู่ใน [2, 32768]");

// ตัดสินใจว่าโมดูโลลดลงเมื่อ R เป็นกำลังสอง
#define M ((uint32_t)(((R-1)&R)!=0 ? 0x8000 : R)<<16)

// ลำดับของ yn สำหรับ VC (a=214013, b=2531011), n=6, seed=1639326023
// ถ้า R เป็นกำลังสอง ceil(16/log2(R))+1 รายการก็เพียงพอแล้ว
// มิฉะนั้น นั่นคือรายการ ceil(31/log2(R)) ดังนั้น 12 สำหรับ R=6
const int16_t y[] = {
  0,5,3,0,4,3,1,0,4,5,4,4,4,5,5,3,0,2,0,5,4,5,0, // 0, 2,5,1,3,5,5,5,
};

// INVA ผกผันโมดูลาร์ของ A โมดูโล M
#กำหนด INVA (IN_A(IN_A(IN_A(IN_A((uint32_t)A))))&(M-1))
#กำหนด IN_A(v) (v*(2-v*A))

int main (โมฆะ) {
  // ตัดสินใจเริ่มต้น x0 เพื่อให้ตรงกับ y0
  const uint32_t y0 = y[0], y1 = y[1];
  int32_t x0 = (int32_t)(((M >> 16) - y0) / R * R + y0) << 16 | 0xffff;
  uint32_t พบ = 0;
  printf("ตัวสร้าง: ((int)((x = %" PRIu32 " * x + %" PRIu32 ") >> 16) & 0x7fff) %% %u\n",
    (uint32_t)A, (uint32_t)B, (ไม่ได้ลงชื่อ)R);
  ในขณะที่ (x0 >= 0) {
    uint32_t x1 = A * (uint32_t)x0 + B;
    ทำ {
      // ยืนยัน ( (x0 >> 16) % R == y0);
      // ยืนยัน ( x1 == A * (uint32_t)x0 + B);
      ถ้า (((x1 >> 16) & 0x7fff) % R == y1) {
        uint32_t x = x1;
        int n;
        สำหรับ (n = 2; n < sizeof(y) / sizeof(*y); ++n)
          ถ้า ((((x = A * x + B) >> 16) & 0x7fff) % R != y[n])
            ไปที่ nxt;
        // พบวิธีแก้ปัญหา
        x = (INVA * ((uint32_t)x0 - B)) & (M - 1);
        printf("x0 สามารถเป็น %" PRId32 " นั่นคือ seed=%" PRIu32
          " โมดูโล 0x%" PRIx32 ", ผลตอบแทน:\n", x0, x, M);
        // พิสูจน์ประเด็นโดยการแสดงผลลัพธ์
        สำหรับ (n = 0; n < sizeof(y) / sizeof(*y) + 8; ++n)
          printf(" %d", ((int)((x = A * x + B) >> 16) & 0x7fff) % R);
        printf("\n");
        ++พบ;
      }
    nxt: x1 -= (uint32_t)A;
    } ในขณะที่ (((x0--) & 0xffff) != 0);
    x0 -= (int32_t)(R - 1) << 16;
  }
  printf("found %" PRIu32 " solution%s\n", พบ, พบ > 1 ? "s" : "");
  กลับ 0;
}

// ยอมแพ้:
// ตัวสร้าง: ((int)((x = 214013 * x + 2531011) >> 16) & 0x7fff) % 6
// x0 สามารถเป็น 531633902 นั่นคือ seed=1639326023 โมดูโล 0x80000000 ซึ่งให้ผลลัพธ์:
// 2 3 4 1 5 1 1 5 4 0 3 2 2 5 5 3 5 5 3 4 0 1 1 4 1 3 3 2 5 4 4
// พบ 1 วิธีแก้ไข
fairytale avatar
sz flag
ถ้า $x_n$ เป็น 32768(1000 0000 0000 0000) บิต 16 คือ 0 ถ้า $y_n\bmod 2$ เป็น 0 ด้วย ดังนั้น $y_n$ นี้จะตรงกับ $x_n$ จากนั้นฉันทดสอบ $x_n$ ถัดไป ฉันถูกไหม? (ฉันถือว่าบิตนับจากซ้ายถ้าคุณไม่พูดว่า "ต่ำ")
fgrieu avatar
ng flag
@เทพนิยาย: เอ่อ ไม่ ดูส่วนใหม่ "_หมายเหตุด้านบน_" โดยเฉพาะสองประโยคสุดท้าย
fairytale avatar
sz flag
ลำดับของฉันคือ 4,5,0,1,4,3,4,5,1,1,0,2,1,2,3,1,0,2,5,2,0 น่าเสียดาย ไม่พบ... ฉันได้ลอง 1103515245 และ 12345 (glibc rand) แล้ว แต่ก็ยังไม่พบ ถอนหายใจ โปรแกรมนี้เก่ามาก เขียนก่อนปี 2549 และไม่เกี่ยวข้องกับวัตถุประสงค์ที่จริงจัง ดังนั้นฉันเชื่อว่ามันไม่ใช่ PRNG ที่ปลอดภัยด้วยการเข้ารหัสตอนนี้ฉันเดาว่าผู้เขียนอาจใช้ A,B,M ของเขาเอง หรือเขาใช้ Mersenne Twister
fgrieu avatar
ng flag
@fairytale: คำถามที่ปรับโครงสร้างใหม่จะได้รับคำตอบในเชิงลบ คุณมีไฟล์ปฏิบัติการ ("_I ตรวจสอบไฟล์. exe แล้ว _") ดังนั้นจึงยังคงมีแนวทางการดำเนินการของวิศวกรรมย้อนกลับ ยกเลิกการคอมไพล์หรือ/และสังเกตโปรแกรมที่ทำงานในสภาพแวดล้อมที่มีเครื่องมือวัด นั่นเป็นเรื่องที่นอกประเด็นใน crypto-SE มากกว่าการเขียนโปรแกรมเสียอีก แต่อาจจะเป็นใน [reverseengineering-SE](https://reverseengineering.stackexchange.com/)?

โพสต์คำตอบ

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