Đọc từ / dev / ngẫu nhiên không tạo ra bất kỳ dữ liệu nào


19

Tôi thường sử dụng lệnh

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

để tạo mật khẩu giả ngẫu nhiên. Điều này không làm việc với /dev/random.

Đặc biệt

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' sản xuất đầu ra
  • cat /dev/random | strings --bytes 1 sản xuất đầu ra
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t ' không sản xuất đầu ra

Lưu ý: Khi sử dụng, /dev/randombạn có thể phải vẫy chuột hoặc bấm phím (ví dụ: ctrl, shift, v.v.) để tạo entropy.

Tại sao ví dụ cuối cùng không hoạt động? trmột số loại bộ đệm nội bộ lớn /dev/urandomđầy nhanh chóng nhưng /dev/randomkhông?

PS tôi đang sử dụng 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

phân phối của bạn, phiên bản kernel của bạn là gì? trên Cygwin cả hai giá trị trả về.
Kiwy

@Kiwy Xem chỉnh sửa.
Aaron J Lang

1
Bạn có biết pwgen, đặc biệt pwgen -s?
MvG

2
Việc -schuyển đổi làm cho chúng ít đáng nhớ hơn, thực sự ngẫu nhiên hơn. @Boyd: makepasswd có sẵn rộng rãi ngoài các bản phát hành dựa trên Debian không? Theo cách tôi thấy, pwgen có sẵn cho CentOS trong khi makepasswd thì không .
MvG

1
@BoydStephenSmithJr. Tôi đồng ý với @ MvG makepasswdkhông khả dụng trên nền tảng của tôi, dù sao cũng cảm ơn
Aaron J Lang

Câu trả lời:


27

Nó cuối cùng sẽ.

Trong:

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

cat sẽ không bao giờ đệm, nhưng dù sao nó cũng không cần thiết vì không có gì để nối ở đây.

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

stringsmặc dù, vì đầu ra của nó không dài hơn nên một thiết bị đầu cuối sẽ đệm đầu ra của nó bằng các khối (có dạng như 4 hoặc 8kB) trái ngược với các dòng khi đầu ra đi đến một thiết bị đầu cuối.

Vì vậy, nó sẽ chỉ bắt đầu ghi vào thiết bị xuất chuẩn khi đã tích lũy được 4kB ký tự để xuất ra, điều /dev/randomnày sẽ mất một thời gian.

trđầu ra đi đến một thiết bị đầu cuối (nếu bạn đang chạy nó tại dấu nhắc shell trong thiết bị đầu cuối), vì vậy nó sẽ đệm dòng đầu ra của nó. Bởi vì bạn đang xóa \n, nó sẽ không bao giờ có một dòng đầy đủ để viết, vì vậy thay vào đó, nó sẽ ghi ngay khi một khối đầy đủ được tích lũy (như khi đầu ra không đi đến một thiết bị đầu cuối).

Vì vậy, trcó khả năng không viết bất cứ điều gì cho đến khi stringsđã đọc đủ từ /dev/randomđó để ghi 8kB (2 khối có thể nhiều hơn nữa) dữ liệu (vì khối đầu tiên có thể sẽ chứa một số dòng mới hoặc tab hoặc ký tự khoảng trắng).

Trên hệ thống này, tôi đang thử điều này, tôi có thể nhận được trung bình 3 byte mỗi giây từ /dev/random(trái ngược với 12MiB trở đi /dev/urandom), vì vậy trong trường hợp tốt nhất (4096 byte đầu tiên /dev/randomlà tất cả có thể in được), chúng tôi nói chuyện 22 phút trước khi trbắt đầu xuất ra bất cứ điều gì. Nhưng nhiều khả năng sẽ là hàng giờ (trong một thử nghiệm nhanh, tôi có thể thấy stringsviệc viết một khối cứ sau 1 đến 2 khối được đọc và các khối đầu ra chứa khoảng 30% ký tự dòng mới, vì vậy tôi mong muốn nó cần đọc ít nhất 3 khối trước trcó 4096 ký tự để xuất).

Để tránh điều đó, bạn có thể làm:

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

stdbuf là một lệnh GNU (cũng được tìm thấy trên một số BSD) làm thay đổi bộ đệm stdio của các lệnh thông qua thủ thuật LD_PRELOAD.

Lưu ý rằng thay vì strings, bạn có thể sử dụng tr -cd '[:graph:]'cũng sẽ loại trừ tab, dòng mới và không gian.

Bạn cũng có thể muốn sửa miền địa phương Cđể tránh những bất ngờ có thể xảy ra trong tương lai với các ký tự UTF-8.


wow giải thích ấn tượng.
Kiwy

2
Kinh ngạc! Giải thích và giải pháp tuyệt vời. Tôi đã luôn sử dụng cat'vô dụng' bởi vì tôi chưa bao giờ thích chuyển hướng stdin ở cuối đường ống, bây giờ tôi có thể 'lưu một quy trình' và vẫn có các lệnh có thể đọc được. Giải pháp cuối cùng của tôi là< /dev/random stdbuf -o0 tr -Cd '[:graph:]' | stdbuf -o0 head --bytes 32
Aaron J Lang

@AaronJLang, điểm hay về [:graph:]. Tôi đã quên mất điều đó.
Stéphane Chazelas

@AaronJLang, bạn không cần stdbufcho head -c32trừ khi bạn muốn cho phép nó ghi dữ liệu ngay khi có dữ liệu (như trong một số đoạn thay vì một đoạn 32byte ngay khi có))
Stéphane Chazelas

2
Theo tôi, / dev / urandom là đủ để sử dụng cho tác giả. Nếu ai đó tò mò về cách, cụ thể, urandom hoạt động so với ngẫu nhiên, tôi khuyên bạn nên đọc các nhận xét ở đầu trình điều khiển trong trình điều khiển / char / Random.c của cây nguồn kernel. Các ý kiến ​​đề cập đến một phân tích về PRNG và nó được thực hiện. Hy vọng rằng, bài viết này sẽ trả lời câu hỏi "chỉ là ngẫu nhiên ít nhiều ngẫu nhiên so với ngẫu nhiên?" Có sẵn tại đây: eprint.iacr.org/2012/251.pdf
etherfish

5

Tạo số ngẫu nhiên cho nhiều ứng dụng bảo mật đòi hỏi phải có đủ entropy - entropy đo mức độ ngẫu nhiên không thể đoán trước. Bộ xử lý xác định không thể tạo ra entropy, do đó, entropy phải đến từ bên ngoài - từ một thành phần phần cứng có hành vi không xác định hoặc từ các yếu tố khác đủ khó để tái tạo, chẳng hạn như thời gian hành động của người dùng (đó là khi lắc chuột vào đi). Khi có đủ entropy, mật mã có thể được sử dụng để tạo ra một luồng số ngẫu nhiên thực tế không giới hạn.

Linux hoạt động bằng cách tích lũy entropy trong một nhóm, sau đó sử dụng mật mã để tạo ra các số ngẫu nhiên chấp nhận được cả thông qua /dev/random/dev/urandom. Sự khác biệt là /dev/randomáp dụng một phép tính entropy cực kỳ bảo thủ làm giảm ước tính của entropy trong nhóm cho mỗi byte mà nó tạo ra, trong khi /dev/urandomkhông liên quan đến số lượng entropy trong nhóm.

Nếu ước tính của entropy trong nhóm quá thấp, /dev/randomcác khối cho đến khi nhiều entropy có thể được tích lũy. Điều này có thể làm tê liệt nghiêm trọng tốc độ /dev/randomcó thể tạo ra sản lượng. Đây là những gì bạn đang quan sát ở đây. Nó không có gì để làm với tr; nhưng stringsđọc đầu ra với bộ đệm, do đó nó phải đọc một bộ đệm đầy đủ (một vài KB) từ /dev/randomchỉ để tạo ra ít nhất một byte đầu vào.

/dev/urandomlà hoàn toàn chấp nhận được để tạo khóa mật mã , vì entropy thực tế không giảm theo bất kỳ cách nhận biết nào. (Nếu bạn giữ cho máy hoạt động lâu hơn vũ trụ đã tồn tại, bạn không thể bỏ qua những cân nhắc này, nhưng nếu không thì bạn vẫn ổn.) Chỉ có một trường hợp /dev/urandomkhông tốt, đó là trên một hệ thống mới được cài đặt. Chưa có thời gian để tạo entropy hoặc hệ thống khởi động mới khởi động từ phương tiện chỉ đọc.

Loại bỏ stringskhỏi chuỗi khởi động của bạn có thể sẽ tăng tốc quá trình của bạn. Dưới đây trsẽ lọc các ký tự không in:

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

Nhưng bạn có thể sử dụng /dev/urandomở đây , miễn là bạn cẩn thận không tạo mật khẩu trên hệ thống chưa có thời gian để tích lũy đủ entropy. Bạn có thể kiểm tra mức độ nhóm entropy của Linux trong /proc/sys/kernel/random/entropy_avail(nếu bạn sử dụng /dev/random, con số trong tệp này sẽ bảo thủ, có thể rất nhiều).


1

Bạn nên sử dụng /dev/urandomđể có được các số ngẫu nhiên (giả) chất lượng cao và /dev/randomchỉ khi bạn thực sự cần các số ngẫu nhiên thực sự không thể đoán trước. Kẻ tấn công dưới tài nguyên của NSA sẽ có một thời gian rất khó để bẻ khóa /dev/urandom(và đừng quên về mật mã ống cao su ). Hạt nhân lấp đầy một bộ đệm với các byte "thực sự ngẫu nhiên", đó là những gì /dev/randommang lại. Đáng buồn thay, tốc độ mà những người được tạo ra là thấp, vì vậy đọc rất nhiều từ /dev/random sẽ chờ đợi sự ngẫu nhiên.

Bạn có thể cân nhắc sử dụng Random.org hoặc trình tạo mật khẩu của nó hoặc một trong số rất nhiều trình tạo mật khẩu ngẫu nhiên đang trôi nổi, hãy xem ví dụ trang này để biết một số mẹo về dòng lệnh (không phải tôi muốn giới thiệu tất cả chúng , nhưng họ sẽ cung cấp cho bạn các ý tưởng) hoặc bạn có thể sử dụng một cái gì đó như mkpasswd(1)(ở đây trên phần 19 của Fedora expect-5.45-8.fc19.x86_64).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.