Score:1

จะวนซ้ำคีย์ที่ได้รับจาก Scrypt อย่างปลอดภัยและสุ่มได้อย่างไร

ธง de

ฉันกำลังพัฒนาวิธีสร้างคีย์ส่วนตัวที่กำหนดขึ้นสำหรับเส้นโค้งวงรีตามอำเภอใจโดยอิงตามอินพุตของผู้ใช้ (กระเป๋าเงินสมอง) ขณะนี้ ฉันกำลังใช้อัลกอริทึมการแฮชรหัสผ่าน Scrypt พร้อมพารามิเตอร์ความยากที่มีประสิทธิภาพเพื่อแฮชพารามิเตอร์อินพุตจำนวนหนึ่งลงในคีย์

เอาต์พุตของ Scrypt ควรกระจายอย่างสม่ำเสมอระหว่างกัน $[0, 2^{b})$ ที่ไหน ${b}$ คือจำนวนบิตเอาต์พุตที่ใช้จากเอาต์พุตอัลกอริทึม Scrypt แต่คีย์ส่วนตัวของเส้นโค้งวงรีที่ถูกต้องต้องน้อยกว่าลำดับของฟิลด์จำกัดของเส้นโค้ง $N$, กระจายเท่า ๆ กันในหมู่ $[0, น)$. ดังนั้น การใช้เอาต์พุตของ Scrypt โดยตรงเป็น mod คีย์ส่วนตัว $N$ จะสร้างอคติเล็กๆ น้อยๆ ในผลลัพธ์ของคีย์ที่สร้างขึ้น ซึ่งก็คือข่าวร้าย ดังนั้นฉันจึงต้องหลีกเลี่ยงสิ่งนั้น

โดยปกติ หากคุณสร้างคีย์ส่วนตัวโดยใช้ RNG ที่ปลอดภัย คุณจะต้องลอง RNG ใหม่อีกครั้งจนกว่าจะได้ตัวเลขที่น้อยกว่า $N$และคุณสามารถใช้เป็นคีย์ส่วนตัวได้อย่างปลอดภัย

มีวิธีที่ปลอดภัยในการทำซ้ำเอาต์พุตของ Scrypt หรือไม่ ในลักษณะที่เราจะรักษาการกระจายแบบสุ่มหลอกของเอาต์พุตของ Scrypt โดยไม่ต้องเรียกใช้ Scrypt ซ้ำด้วยพารามิเตอร์ใหม่

วิธีหนึ่งที่ฉันพิจารณาคือแฮชผลลัพธ์ของการเข้ารหัสด้วย SHA256 หรือ SHA512 จนกว่าจะน้อยกว่า $N$แต่จะทำงานได้ไม่ดีนักสำหรับเส้นโค้งที่มีขนาดใหญ่กว่า 512 บิต เช่น P521

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

Score:1
ธง my

ดังนั้น การใช้เอาต์พุตของ Scrypt โดยตรงเป็นคีย์ส่วนตัว $\bmod N$ จะสร้างอคติเล็กๆ น้อยๆ ในผลลัพธ์ของคีย์ที่สร้างขึ้น ซึ่งก็คือข่าวร้าย ดังนั้นฉันจึงต้องหลีกเลี่ยงสิ่งนั้น

อันที่จริง ความลำเอียงนั้นไม่ใหญ่พอที่จะใช้ประโยชน์ได้ อย่างไรก็ตามสมมติว่าคุณต้องการหลีกเลี่ยงสิ่งนั้นทั้งหมด ...

มีวิธีที่ปลอดภัยในการทำซ้ำเอาต์พุตของ Scrypt หรือไม่ ในลักษณะที่เราจะรักษาการกระจายแบบสุ่มหลอกของเอาต์พุตของ Scrypt โดยไม่ต้องเรียกใช้ Scrypt ซ้ำด้วยพารามิเตอร์ใหม่

สองแนวทางที่ชัดเจน:

  • ให้ Scrypt สร้าง (พูด) $log_2 ไม่มี + 128$ บิตและประเมินว่า $\bmod N$; ความลำเอียงที่เกิดขึ้นจะน้อยมากจนวัดไม่ได้และใช้ประโยชน์ได้น้อยกว่ามาก

  • ส่งเอาต์พุตของ Scrypt ไปที่ เขย่า; แล้วบีบออก $\lceil log_2 N \rceil$ บิต (อาจเป็นจำนวนคู่ของไบต์ หากทำให้การใช้งานง่ายขึ้น) และถ้าค่าที่ส่งคืนเกิดขึ้นมีขนาดใหญ่กว่า $N$บีบออกบิตมากขึ้น

ประการที่สองคล้ายกับแนวคิดของคุณกับ SHA256 หรือ SHA512; อย่างไรก็ตาม เนื่องจาก SHAKE ช่วยให้เราสามารถบีบบิตออกได้มากเท่าที่ต้องการ เราจึงสามารถขยายเพื่อจัดการ P521 ได้อย่างง่ายดาย

โอ้และเมื่อคุณถามว่า:

มีเส้นโค้งทั่วไปใดบ้างที่มีลำดับ $N$ ไม่ใช่เศษส่วนที่มีนัยสำคัญของกำลังสูงสุดถัดไปของสองใช่หรือไม่

ก็ คลังสมอง ความโค้งอยู่ในใจ - ฉันไม่รู้ว่าการใช้มันเป็นเรื่องธรรมดาอย่างไม่น่าเชื่อ แต่ฉันเชื่อว่ามันถูกใช้ในบางโอกาส

Gilles 'SO- stop being evil' avatar
FIPS 186-4 §B.4 อนุญาตทั้งสองแนวทาง โดยมีกระบวนการเฉพาะในแต่ละกรณี ขอเพียง 64 บิตพิเศษสำหรับแนวทางอคติเล็กน้อยขนาดอินพุตคงที่
JoeJafarTheJenie avatar
de flag
ว้าวเจ๋ง! ฉันไม่รู้เกี่ยวกับแฮช SHAKE จนกว่าจะอ่านคำตอบของคุณ นี่เป็นวิธีแก้ปัญหาที่สะอาดมาก (แม้ว่าจะไม่มีขอบเขต) ขอบคุณสำหรับเคล็ดลับเกี่ยวกับ Brainpool คำสั่งโค้งของพวกเขาดูแย่มาก ต้องการทราบข้อมูลเพิ่มเติมว่าทำไมการเพิ่มบิตเอาต์พุต scrypt พิเศษจึงช่วยลดอคติได้
Score:0

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

ดังที่ได้กล่าวไปแล้ว ในการรับคีย์เส้นโค้งวงรีตามที่กำหนด ขั้นตอนแรกคือการพิจารณาประเภทของเส้นโค้ง

  • สำหรับ Curve25519 และ Curve448 คีย์จะคำนวณจากสตริงบิตที่มีการกระจายอย่างสม่ำเสมอตามที่ระบุใน RFCÂ 7748 §5. มีกระบวนการที่แม่นยำในการรับอินพุตแบบกระจาย 256 บิตหรือ 448 บิต บังคับบิตบางบิต ตีความบิตเป็นตัวเลข (little-endian) และลดค่าเป็นโมดูโลตัวแทนแบบบัญญัติ $p$. เพราะ $p$ ใกล้เคียงกับกำลังถัดไปของ $2$การลดโมดูโลจะทำให้จำนวนไม่เปลี่ยนแปลงด้วยความน่าจะเป็นที่ท่วมท้น การใช้งาน Curve25519/Curve448 โดยทั่วไป (âMUSTâ) ยอมรับคีย์ในรูปแบบที่ไม่เป็นที่ยอมรับ คุณจึงไม่ต้องทำอะไรนอกจากระบุสตริง 32 ไบต์หรือ 56 ไบต์ที่กระจายอย่างสม่ำเสมอ

  • สำหรับ Ed25519 และ Ed448 มีการระบุคีย์ส่วนตัวใน RFC8032 §5.1.5 และ §5.2.5 เป็นสตริง 32 ไบต์หรือ 57 ไบต์แบบเดียวกันตามลำดับ กระบวนการลายเซ็นเริ่มต้นด้วยการแฮชอินพุตนี้ (เชื่อมกับสตริงอื่น) และใช้ผลลัพธ์เป็นจำนวนเต็ม

  • สำหรับเส้นโค้ง NIST และเส้นโค้งทั่วไปในรูปแบบ Weierstrass ไม่มีกระบวนการใดที่เป็นที่ยอมรับในระดับสากลในการเปลี่ยนจากสตริงบิตไปเป็นคีย์ส่วนตัว ม.ป.ป.186-4 §B.4 อธิบายวิธีที่เป็นไปได้สองวิธีในการสร้างคีย์ส่วนตัวจากเอาต์พุตของตัวสร้างแบบสุ่ม และวิธีการเหล่านี้ใช้ได้เท่าเทียมกันในการรับคีย์ส่วนตัวจากบิตสตรีมที่มีการกระจายอย่างสม่ำเสมอซึ่งได้รับจากอัลกอริทึมการได้มาของคีย์สมมาตร ในการรับรหัสส่วนตัวบนเส้นโค้งที่มีลำดับ $p$ เป็น $n$- บิตไพรม์:

    1. (âบิตสุ่มเพิ่มเติมâ) รับ $n + 64$ บิตของอินพุตลับที่กระจายอย่างสม่ำเสมอ ((หลอก-) แบบสุ่ม) ตีความอินพุตนั้นเป็นจำนวนเต็ม big-endian ลดค่าเป็นโมดูโล $p-1$ และเพิ่ม $1$ เพื่อให้ได้ตัวเลขในช่วง $[1, หน้า-1]$. คีย์บางคีย์มีโอกาสมากกว่าคีย์อื่นเล็กน้อย แต่เนื่องจากมีอคติ $2^{-64}$มันไม่มีประโยชน์ในทางปฏิบัติแก่ศัตรู
    2. (âทดสอบผู้สมัครâ) รับ $n$ บิตของอินพุตลับที่กระจายอย่างสม่ำเสมอ ((หลอก-) แบบสุ่ม) แปลความหมายอินพุตนั้นเป็นจำนวนเต็มแบบ big-endian ถ้าผลเป็น $\ge พี-1$ให้เริ่มกระบวนการใหม่ตั้งแต่ต้น มิฉะนั้นเพิ่ม $1$. สิ่งนี้ไม่มีอคติเลยและไม่ต้องการการจัดการตัวเลขที่มากกว่า $n$ บิต แต่มีข้อเสียคือคุณไม่รู้ล่วงหน้าว่าคุณต้องการอินพุตแบบกระจายสม่ำเสมอมากน้อยเพียงใด ซึ่งอาจไม่มีขอบเขต

    โดยทั่วไปวิธีแรกจะสะดวกกว่าเนื่องจากคุณทราบแน่ชัดว่าต้องใช้อินพุตสุ่ม (เทียม-) เท่าใด

หากคุณต้องการเชื่อมโยงสิ่งนี้กับอัลกอริธึมการสืบทอดคีย์ที่ใช้รหัสผ่าน เช่น scrypt มีสองวิธี

  • วิธีโดยตรงคือการขออินพุตมากเท่าที่คุณต้องการจาก scrypt สำหรับเส้นโค้งไวเออร์สตราส ทำให้วิธีการทดสอบของผู้เข้าสอบใช้ไม่ได้ผล ดังนั้นรับ 32 ไบต์จาก scrypt สำหรับ Curve25519 หรือ Ed25519 40 ไบต์สำหรับ P256R1 หรือ P256K1; 56 ไบต์สำหรับ P384R1 หรือ P384K1; 57 ไบต์สำหรับ Ed448 เป็นต้น
  • วิธีทางอ้อมคือการขอจำนวนบิตคงที่จาก scrypt สิ่งนี้จะต้องเพียงพอที่จะไม่สามารถเดาได้ด้วยกำลังดุร้าย 128 บิต (16 ไบต์) จะทำได้ดี ใช้สิ่งนี้เป็นจุดเริ่มต้นสำหรับฟังก์ชันการสืบทอดคีย์ธรรมดา (ไม่ใช่รหัสผ่าน) เช่น หนึ่งรายการจาก NIST SPÂ 800-108 หรือ HKDFหรือเป็นเมล็ดสำหรับอัลกอริทึมกำเนิดเทียมเช่น หนึ่งตัวจาก NIST SPÂ 800-90A. ใช้เอาต์พุต PRNG นั้นเพื่อรับรหัสส่วนตัว
JoeJafarTheJenie avatar
de flag
ขอบคุณสำหรับสิ่งนี้! ฉันทราบดีถึงปัญหาที่เกิดขึ้นในคีย์ที่สร้างขึ้นตามกำหนด แต่สำหรับกรณีการใช้งานเฉพาะของฉัน ปัญหาเหล่านี้ไม่เกี่ยวข้องกัน
JoeJafarTheJenie avatar
de flag
โซลูชัน "ผู้สมัครทดสอบ" ฉันคิดว่าใช้ไม่ได้เพราะนั่นหมายถึงการขอรหัสผ่านใหม่จากผู้ใช้ (โซลูชัน 'ไม่หรูหรา' ที่ฉันอธิบายไว้ใน OP) “บิตสุ่มพิเศษ” ดูเหมือนจะเป็นตัวเลือกที่ดี คุณช่วยฉันเข้าใจหน่อยได้ไหมว่าทำไมการเพิ่มบิตสุ่มอีก 64 บิตจึงลดความเอนเอียงลงเหลือ $2^{-64}$
Gilles 'SO- stop being evil' avatar
@JoeJafarTheJenie เราได้รับ $2^{n-1} \le p \le 2^n-1$ ให้ $(q,r)$ เป็นผลหารและเศษเหลือของการหาร $2^{n+64}-1$ โดย $p-1$ เราวาด $X$ อย่างสม่ำเสมอใน $[0, 2^{n+64}-1]$ และหา $X \bmod (p-1)$ ตัวเลขในช่วง $[0,r]$ มี $q+1$ มาก่อน และตัวเลขในช่วง $[r+1, p-2]$ มี $q$ มาก่อน ดังนั้น ค่าที่น้อยกว่า $r$ คือ $1 + 1/q$ เท่าของค่าที่มากกว่า $r$ $q = \lfloor (2^{n+64}-1) / (p-1) \rfloor \ge \lfloor (2^{n+64}-1) / (2^n-1) \rfloor \ ประมาณ 2^{64}$ ดังนั้นอคติ $1/q$ จึงน้อยกว่า $2^{-64}$

โพสต์คำตอบ

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