การสร้างรหัสผ่านแบบสุ่ม ทำไมพกพานี้ไม่ได้?


21

ฉันต้องการสร้างรหัสผ่านแบบสุ่มและฉันชอบ:

</dev/urandom tr -dc [:print:] | head -c 64

บนแล็ปท็อปของฉันซึ่งใช้งาน Ubuntu สิ่งนี้จะสร้างตัวอักษรที่พิมพ์ได้ตามที่ตั้งใจ แต่เมื่อฉันเข้าสู่เซิร์ฟเวอร์ของโรงเรียนซึ่งรัน Red Hat Enterprise Linux และเรียกใช้ที่นั่นฉันจะได้ผลลัพธ์เช่น3!ri�b�GrӴ��1�H�<�oM����&�nMC[�Pb�|L%MP�����9��fL2q���IFmsd|l�Kที่จะไม่ทำเลย เกิดอะไรขึ้นที่นี่

คำตอบ:


34

มันเป็นเรื่องของสถานที่และTRปัญหา

ปัจจุบันGNU trรองรับอักขระไบต์เดียวอย่างเต็มที่ ดังนั้นในโลแคลที่ใช้การเข้ารหัสหลายไบต์เอาต์พุตสามารถเป็นสิ่งที่แปลก:

$ </dev/urandom LC_ALL=vi_VN.tcvn tr -dc '[:print:]' | head -c 64
`�pv���Z����c�ox"�O���%�YR��F�>��췔��ovȪ������^,<H ���>

เชลล์จะพิมพ์อักขระหลายไบต์อย่างถูกต้อง แต่ GNU trจะลบไบต์ที่คิดว่าไม่สามารถพิมพ์ได้

หากคุณต้องการให้เสถียรคุณต้องตั้งค่าภาษา:

$ </dev/urandom LC_ALL=C tr -dc '[:print:]' | head -c 64
RSmuiFH+537z+iY4ySz`{Pv6mJg::RB;/-2^{QnKkImpGuMSq92D(6N8QF?Y9Co@

14
+1 เพราะสิ่งนี้ทำให้ฉันรู้ (มีการใช้เชลล์บน Unix / Linux เพียงประมาณ 30 ปี) การเปลี่ยนเส้นทาง stdin / stdout / stderr ไม่จำเป็นต้องถูกวางตำแหน่งหลังจากคำสั่งที่ใช้
Anthon

เพียงความคิดเห็นหากมีการตั้งค่าภาษาแปลก ๆ ไว้เชลล์จะไม่สามารถพิมพ์อักขระได้อย่างถูกต้องแม้ว่าพวกเขาจะไม่ใช่ ASCII? อย่างน้อยเชลล์ที่มีความสามารถ (ยกเว้น xterm แน่นอน)
orion

2
@orion: เชลล์จะพิมพ์อักขระได้อย่างถูกต้อง ในกรณีนี้นั่นเป็นปัญหาที่เกิดขึ้น มันลบไบต์ที่คิดว่าไม่สามารถพิมพ์ได้ทำให้ผลลัพธ์แปลก
cuonglm

@orion กระแสไบต์สุ่มแบบสม่ำเสมอจะไม่เป็นกระแสแบบสุ่มอย่างสม่ำเสมอของการเข้ารหัสอักขระ UTF-8 ที่มีรูปแบบที่ดี
zwol

นอกจากว่าคุณเว้นวรรคในรหัสผ่านของคุณคุณควรใช้:graph:แทน:print::</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
edan

11

พิจารณาแทน

$ dd if=/dev/urandom bs=48 count=1 status=none | base64
imW/X60Sk9TQzl+mdS5PL7sfMy9k/qFBWWkzZjbYJttREsYpzIguWr/uRIhyisR7

นี่มีข้อดีสองข้อ:

  • คุณอ่าน 48 ไบต์เท่านั้นจากอุปกรณ์สุ่มไม่ใช่ ~ 8KB หากกระบวนการอื่น ๆ บนโฮสต์เดียวกันต้องการตัวเลขสุ่ม 8KB ที่ระบายได้ทั้งหมดในครั้งเดียวอาจเป็นปัญหาร้ายแรง (ใช่ว่าไม่มีใครควรใช้อุปกรณ์สุ่มบล็อกแต่คนทำ )

  • ผลลัพธ์ของbase64มีเกือบไม่มีอักขระที่มีความหมายพิเศษ (สำหรับไม่มีเลยให้ตะปูหัว| tr +/ -_ท้ายและ (ตามตัวอย่าง) ตรวจสอบให้แน่ใจว่าจำนวนไบต์ที่ป้อนไปbase64เป็นผลคูณของ 3)

รหัสผ่านที่สร้างขึ้นด้วยวิธีนี้มีเอนโทรปี 384 บิตซึ่งค่อนข้างน้อยกว่าสิ่งที่คุณทำ (บันทึก2 96 64 ≈ 421.4) แต่มากเกินพอสำหรับจุดประสงค์ส่วนใหญ่ (เอนโทรปี 256 บิตปลอดภัยใน "ยังเดาได้เมื่อ ดวงอาทิตย์แผดเผา "อาณาเขตยกเว้นคีย์ RSA, AFAIK)


3

คนอื่น ๆ ชี้ให้เห็นแล้วว่าสถานที่นั้นเป็นตัวกำหนดความ[:print:]หมาย อย่างไรก็ตามอักขระบางตัวที่พิมพ์ได้ไม่เหมาะสำหรับรหัสผ่าน (ไม่ใช่แม้แต่ใน ascii) คุณไม่ต้องการช่องว่างแท็บและ # $% ^ ใช่หรือไม่ ในรหัสผ่านของคุณ - ไม่ใช่เรื่องยากที่จะจำ แต่ก็อาจเป็นอันตรายต่อระบบการรับรองความถูกต้องพื้นฐานซึ่งอาจเป็นไปไม่ได้ที่จะป้อนในฟิลด์อินพุตและอื่น ๆ ในกรณีนี้คุณควรเลือกอักขระ "สติ" ด้วยตนเอง:

LC_ALL=C </dev/urandom tr -dc '[:alnum:]_' | head -c 64

หรือเพียงแค่

</dev/urandom tr -dc 'A-Za-z0-9_' | head -c 64

หรือดีกว่าใช้base64ตามคำแนะนำในคำตอบอื่น ๆ


รหัสผ่านที่เป็นปัญหาจะไม่ถูกป้อนโดยมนุษย์ (ถ้าเป็นฉันจะใช้ Diceware แทน) และฉันค่อนข้างแน่ใจว่าระบบพื้นฐานสามารถจัดการอักขระพิเศษได้โดยไม่มีปัญหา ขอบคุณอยู่ดี
Taymon

4
สิ่งที่คุณพูดผิดอย่างสิ้นเชิง การบังคับให้ผู้ใช้ใช้ตัวอักษรตัวเลขและขีดเส้นใต้ ASCII เท่านั้นจึงลดขนาดตัวอักษรได้มากทำให้การแบ่งรหัสผ่านสำหรับผู้โจมตีง่ายขึ้น ระบบตรวจสอบความถูกต้องที่ไม่สามารถจัดการได้?หรือ^เลวร้ายเกินกว่าที่จะดำเนินการอย่างจริงจัง
Bakuriu

2
หากระบบรับรองความถูกต้องหรือช่องป้อนข้อมูลของคุณทำให้สัญลักษณ์ ASCII ปกติ ... แสดงว่าคุณกำลังทำอะไรผิดพลาดและไม่น่าเชื่อถือสำหรับข้อมูลส่วนตัวของฉัน ไม่มีเหตุผลใดที่จะไม่ยอมรับอักขระทุกตัว (รวมถึงช่องว่าง) ในรหัสผ่านของคุณ
nzifnab

2
ดูเหมือนว่านี่ไม่ใช่กรณีที่นี่ แต่เมื่อมันมาถึงการป้อนข้อมูลของมนุษย์มันง่ายกว่าที่จะจำรหัสผ่านตัวอักษรและตัวเลขที่ยาวซึ่งมีความหมายเฉพาะกับเจ้าของมากกว่าสัญลักษณ์ที่สั้นลง นอกจากนี้ยังมีปัญหาในการป้อนอักขระเหล่านี้บนแป้นพิมพ์ต่างๆ (ไม่ใช่ทุกคนที่มี ^ ในระดับแรกและคนส่วนใหญ่ไม่รู้ด้วยซ้ำว่าแบ็คทิคคืออะไร) กล่องป้อนข้อมูลแทบจะไม่สามารถจัดการอักขระแท็บได้ จำนวนเว็บฟอร์มที่น่าประหลาดใจยังคงมีความเสี่ยงต่อข้อผิดพลาดในการตรวจสอบความถูกต้องของการฉีด sql หรือแม้แต่ความไวของตัวพิมพ์เล็ก
orion

1
เพียงข้อสังเกต: ใน[:print:]คลาสC locale จะไม่มีแท็บ มันเป็นเพียง[:alnum:]+ [:punct:]+ ช่องว่าง (เว้นวรรคเดียวไม่ใช่ [:space:] )
jimmij

2

เกี่ยวกับอะไร

tr -dc [:print:] < /dev/urandom | head -c 64 | strings

สตริงควรพิมพ์ผลลัพธ์ของ urandom ในรูปแบบที่พิมพ์ได้


สิ่งนี้จะช่วยให้-bash: /dev/urandom: Permission denied
Anthon

ขอโทษลืมแมวชั้นนำ
Blindstealer

2

ฉันไม่รู้ว่ามีเหตุผลใดที่คุณใช้/dev/randomสร้างรหัสผ่าน แต่ฉันขอแนะนำให้คุณใช้ pwgen เพื่อบรรเทาความเจ็บปวดของคุณ

$ pwgen -s 10 1

โดยที่ 10 คือความยาวของรหัสผ่าน

http://man.cx/pwgen


1
#Chars allowed in password (I don't like l,o,O, etc):
P="0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz"

#Or such:
#P="a-zA-Z0-9"

head -c 8 < /dev/urandom | tr '\000-\377' "$P$P$P$P$P"
echo

วิธีนี้ IMHO ฉลาดกว่าเมื่อใช้ข้อมูลจาก / dev / urandom สตริงที่วางเป็น $ P $ P $ P ... ต้องมีอย่างน้อย 256 ตัวอักษร

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