การอ่านจาก / dev / random ไม่ได้สร้างข้อมูลใด ๆ


19

ฉันมักจะใช้คำสั่ง

cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' | head --bytes 32

เพื่อสร้างรหัสผ่านแบบหลอกเทียม /dev/randomนี้ไม่ได้ทำงานกับ

เฉพาะ

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' ผลิตผล
  • cat /dev/random | strings --bytes 1 ผลิตผล
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t ' ไม่สร้างผลผลิต

หมายเหตุ: เมื่อใช้/dev/randomคุณอาจต้องขยับเมาส์หรือกดปุ่ม (เช่น ctrl, shift, etc. ) เพื่อสร้างเอนโทรปี

เหตุใดตัวอย่างสุดท้ายไม่ทำงาน ไม่trได้มีชนิดของบัฟเฟอร์ภายในขนาดใหญ่บางอย่างที่/dev/urandomเติมได้อย่างรวดเร็ว แต่/dev/randomไม่?

ป.ล. ฉันใช้ CentOS 6.5

cat /proc/version
Linux version 2.6.32-431.3.1.el6.x86_64 (mockbuild@c6b10.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Jan 3 21:39:27 UTC 2014

รุ่นเคอร์เนลของคุณคืออะไร? บน Cygwin ทั้งสองค่ากลับมา
Kiwy

@Kiwy ดูการแก้ไข
Aaron J Lang

1
คุณรู้ไหมpwgenโดยเฉพาะpwgen -s?
MvG

2
-sสวิทช์ที่ทำให้พวกเขาที่น่าจดจำน้อยมากขึ้นอย่างแท้จริงสุ่ม @Boyd: makepasswdมีให้บริการอย่างกว้างขวางนอกเหนือจาก Debian ที่ใช้หรือไม่ วิธีที่ฉันเห็นมันpwgen สามารถใช้ได้สำหรับการ CentOSขณะmakepasswd ไม่
MvG

1
@BoydStephenSmithJr ฉันเห็นด้วยกับ @ MvG ที่makepasswdไม่สามารถใช้ได้บนแพลตฟอร์มของฉันขอบคุณ
Aaron J Lang

คำตอบ:


27

มันจะในที่สุด

ใน:

cat /dev/random | strings --bytes 1 | tr -d '\n\t '

cat จะไม่บัฟเฟอร์ แต่มันฟุ่มเฟือยอยู่แล้วเพราะไม่มีอะไรมาต่อกันที่นี่

< /dev/random strings --bytes 1 | tr -d '\n\t '

stringsแม้ว่าเนื่องจากเอาต์พุตไม่ได้อีกต่อไปเทอร์มินัลจะบัฟเฟอร์เอาต์พุตโดยบล็อก (ของบางอย่างเช่น 4 หรือ 8kB) ตรงข้ามกับบรรทัดเมื่อเอาต์พุตไปยังเทอร์มินัล

ดังนั้นมันจะเริ่มเขียนถึง stdout เฉพาะเมื่อมันได้สะสมตัวอักษรไปยังเอาท์พุท 4kB ซึ่ง/dev/randomจะใช้เวลาสักครู่

trเอาต์พุตจะไปที่เทอร์มินัล (หากคุณกำลังเรียกใช้ที่เชลล์พรอมต์ในเทอร์มินัล) ดังนั้นมันจะบัฟเฟอร์บรรทัดเอาต์พุตของมัน เนื่องจากคุณลบ\nมันจะไม่มีบรรทัดเต็มในการเขียนดังนั้นจึงจะเขียนทันทีที่เต็มบล็อกสะสม (เช่นเมื่อเอาต์พุตไม่ได้ไปที่เทอร์มินัล)

ดังนั้นtrมีโอกาสที่จะไม่เขียนอะไรจนกว่าจะstringsได้อ่านเพียงพอ/dev/randomเพื่อที่จะเขียนข้อมูล 8kB (อาจเป็นมากกว่า 2 บล็อก) (ตั้งแต่บล็อกแรกอาจมีการขึ้นบรรทัดใหม่หรือแท็บหรืออักขระเว้นวรรค)

ในระบบนี้ฉันพยายามทำสิ่งนี้ฉันสามารถรับค่าเฉลี่ย 3 ไบต์ต่อวินาทีจาก/dev/random(ตรงข้ามกับ 12MiB บน/dev/urandom) ดังนั้นในสถานการณ์กรณีที่ดีที่สุด (4096 ไบต์แรกจาก/dev/randomทั้งหมดที่สามารถพิมพ์ได้) เรา การพูดคุย 22 นาทีก่อนที่จะtrเริ่มทำอะไร แต่น่าจะเป็นชั่วโมงมากกว่า (ในการทดสอบอย่างรวดเร็วฉันสามารถเห็นstringsการเขียนบล็อกอ่านทุก ๆ 1 ถึง 2 บล็อกและบล็อกเอาต์พุตมีอักขระขึ้นบรรทัดใหม่ประมาณ 30% ดังนั้นฉันคาดหวังว่าจะต้องอ่าน อย่างน้อย 3 บล็อกก่อนtrมี 4096 ตัวอักษรเพื่อส่งออก)

เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถทำได้:

< /dev/random stdbuf -o0 strings --bytes 1 | stdbuf -o0 tr -d '\n\t '

stdbuf เป็นคำสั่ง GNU (พบใน BSD บางตัว) ซึ่งจะเปลี่ยน stdio การบัฟเฟอร์คำสั่งผ่านทางเคล็ดลับ LD_PRELOAD

โปรดทราบว่าแทนที่จะใช้stringsคุณสามารถใช้tr -cd '[:graph:]'ซึ่งจะยกเว้นแท็บขึ้นบรรทัดใหม่และช่องว่างด้วย

คุณอาจต้องการแก้ไขโลแคลCเพื่อหลีกเลี่ยงความประหลาดใจในอนาคตที่อาจเกิดขึ้นกับตัวอักษร UTF-8


ว้าวคำอธิบายที่น่าประทับใจ
Kiwy

2
! ที่น่าตื่นตาตื่นใจ คำอธิบายและการแก้ปัญหาที่ยอดเยี่ยม ฉันมักจะใช้cat'ไร้ประโยชน์' เสมอเพราะฉันไม่เคยชอบเปลี่ยนเส้นทาง stdin ที่ส่วนท้ายของไพพ์ไลน์ตอนนี้ฉันสามารถ 'บันทึกโปรเซส' และยังมีคำสั่งที่อ่านได้ ทางออกสุดท้ายของฉันคือ< /dev/random stdbuf -o0 tr -Cd '[:graph:]' | stdbuf -o0 head --bytes 32
Aaron J Lang

@AaronJLang [:graph:]จุดที่ดีเกี่ยวกับ ฉันลืมเรื่องนั้นไป
Stéphane Chazelas

@AaronJLang คุณไม่จำเป็นต้องstdbufสำหรับhead -c32ถ้าคุณต้องการที่จะให้มันเขียนข้อมูลเร็วที่สุดเท่าที่มันมีมัน (เหมือนในหลายชิ้นแทนก้อน 32byte หนึ่งเร็วที่สุดเท่าที่มันมีพวกเขา)
Stéphane Chazelas

2
ในความคิดของฉัน / dev / urandom เพียงพอสำหรับการใช้งานของผู้เขียน หากมีคนสงสัยว่าด้วยวิธีใดโดยเฉพาะอย่างยิ่ง urandom ทำงานเมื่อเทียบกับการสุ่มฉันขอแนะนำให้อ่านความคิดเห็นที่ด้านบนของไดรเวอร์ในไดร์เวอร์ / char / random.c ของแผนผังซอร์สเคอร์เนล ความคิดเห็นที่กล่าวถึงการวิเคราะห์ของ PRNG และการใช้งาน หวังว่าบทความนี้จะตอบคำถามว่า "การสุ่มแบบสุ่มนั้นมากหรือน้อยเพียงใดเมื่อเทียบกับการสุ่ม?" มีให้ที่นี่: eprint.iacr.org/2012/251.pdf
etherfish

5

การสร้างตัวเลขสุ่มสำหรับแอปพลิเคชั่นความปลอดภัยจำนวนมากนั้นต้องการเอนโทรปีพอเพียง - วัดเอนโทรปีที่วัดว่าการสุ่มนั้นไม่แน่นอน หน่วยประมวลผลที่กำหนดขึ้นไม่สามารถสร้างเอนโทรปีได้ดังนั้นเอนโทรปีจึงต้องมาจากภายนอก - ไม่ว่าจะเป็นส่วนประกอบฮาร์ดแวร์ที่มีพฤติกรรมที่ไม่สามารถกำหนดค่าได้หรือจากปัจจัยอื่น ๆ ที่ยากต่อการทำซ้ำเช่นเวลาของการกระทำของผู้ใช้ เข้ามา). เมื่อมีการใช้งานเอนโทรปีเพียงพอการเข้ารหัสสามารถใช้เพื่อสร้างกระแสสุ่มจำนวนไม่ จำกัด

ลินุกซ์ทำงานโดยการสะสมเอนโทรปีในสระว่ายน้ำแล้วใช้การเข้ารหัสในการผลิตตัวเลขสุ่มที่ยอมรับได้ทั้งผ่านและ/dev/random /dev/urandomความแตกต่างคือการ/dev/randomใช้การคำนวณเอนโทรปีแบบอนุรักษ์นิยมอย่างมากซึ่งจะลดการประมาณค่าเอนโทรปีในสระว่ายน้ำสำหรับทุกไบต์ที่มันสร้างขึ้นในขณะที่/dev/urandomไม่เกี่ยวข้องกับปริมาณเอนโทรปีในสระ

หากค่าประมาณของเอนโทรปีในสระว่ายน้ำต่ำเกินไป/dev/randomบล็อกจนสามารถสะสมพลังงานได้มากขึ้น สิ่งนี้สามารถทำลายอัตราที่/dev/randomสามารถส่งออกอย่างรุนแรง นี่คือสิ่งที่คุณกำลังสังเกตที่นี่ มันไม่มีอะไรเกี่ยวข้องกับtr; แต่stringsอ่านเอาต์พุตด้วยการบัฟเฟอร์ดังนั้นจึงต้องอ่านบัฟเฟอร์แบบเต็ม (ไม่กี่ KB) จาก/dev/randomการสร้างอินพุตอย่างน้อยหนึ่งไบต์

/dev/urandomเป็นที่ยอมรับได้อย่างสมบูรณ์แบบสำหรับการสร้างคีย์การเข้ารหัสเพราะเอนโทรปีไม่ได้ลดลงในความเป็นจริง (หากคุณให้เครื่องของคุณทำงานได้นานกว่าจักรวาลที่มีอยู่คุณไม่สามารถละเลยข้อควรพิจารณาเหล่านี้ได้ แต่อย่างอื่นคุณก็ดี) มีเพียงกรณีเดียวที่/dev/urandomไม่ดีซึ่งอยู่บนระบบที่ติดตั้งใหม่ ยังไม่มีเวลาในการสร้างเอนโทรปีหรือระบบบูทใหม่ที่บู๊ตจากสื่อแบบอ่านอย่างเดียว

การกำจัดออกstringsจากเชนการบูตของคุณอาจทำให้กระบวนการของคุณเร็วขึ้น ด้านล่างtrจะกรองตัวอักษรที่ไม่ได้พิมพ์:

</dev/random LC_ALL=C tr -dc '!-~'

แต่คุณสามารถใช้/dev/urandomที่นี่ได้ตราบใดที่คุณระวังที่จะไม่สร้างรหัสผ่านบนระบบที่ไม่มีเวลาสะสมเอนโทรปีเพียงพอ คุณสามารถตรวจสอบระดับของเอนโทรปีของลีนุกซ์ได้/proc/sys/kernel/random/entropy_avail(ถ้าคุณใช้/dev/random, ตัวเลขในไฟล์นี้จะเป็นแบบอนุรักษ์นิยม, อาจจะเป็นอย่างนั้น)


1

คุณควรใช้/dev/urandomเพื่อรับตัวเลขสุ่มที่มีคุณภาพสูง (หลอก) และ/dev/randomเฉพาะเมื่อคุณต้องการตัวเลขสุ่มที่คาดเดาไม่ได้จริงๆ ผู้โจมตีด้านล่างทรัพยากรเอ็นเอสเอจะมีมากเวลาที่ยากที่จะแตก/dev/urandom(และอย่าลืมเกี่ยวกับท่อยางเข้ารหัส ) เคอร์เนลเติมบัฟเฟอร์ด้วยไบต์ "สุ่มจริงๆ" นั่นคือสิ่งที่/dev/randomให้ น่าเศร้าที่อัตราการสร้างเหล่านั้นอยู่ในระดับต่ำดังนั้นการอ่านจำนวนมากจากความ/dev/random ตั้งใจที่จะรอการสุ่ม

คุณอาจลองใช้random.orgหรือเครื่องมือสร้างรหัสผ่านหรือหนึ่งในเครื่องกำเนิดรหัสผ่านแบบสุ่มจำนวนมากที่ลอยอยู่ดูตัวอย่างหน้านี้สำหรับเคล็ดลับบรรทัดคำสั่งบางคำ แต่พวกเขาควรให้แนวคิดกับคุณ) หรือคุณสามารถใช้บางอย่างเช่นmkpasswd(1)(ที่นี่ในส่วนของ Fedora 19 expect-5.45-8.fc19.x86_64)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.