Tại sao không thể đọc từ / dev / urandom trên OSX?


35

Một đồng nghiệp đề nghị tạo một khóa ngẫu nhiên thông qua lệnh sau:

tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs

Nó đã cho tôi lỗi:

tr: Chuỗi byte bất hợp pháp

Tôi lo ngại rằng tôi không có /dev/urandomtrên hệ thống của mình. Tôi đã thử googling để tìm ra cách cài đặt tệp này, nhưng tôi đã đến chỗ trống. Tôi đã cố gắng locate urandomvà cũng đến trống rỗng. (thực ra, nó đã tìm thấy trang man, nhưng điều đó không có ích)

Làm cách nào để urandomcung cấp trên hệ thống Mac OSX của tôi? (Sư tử)


3
Sử dụng thú vị của xargs...
sendmoreinfo

Câu trả lời:


49

Dựa trên thông báo lỗi mà bạn nhận được, tôi không nghĩ / dev / urandom là vấn đề. Nếu đúng như vậy, tôi mong đợi một lỗi như "không có tệp hoặc thư mục như vậy".

Tôi đã tìm kiếm thông báo lỗi mà bạn nhận được và tìm thấy thông báo lỗi này, có vẻ như nó có thể liên quan đến vấn đề của bạn: http://nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte- resultence

Về cơ bản, chỉ định miền địa phương bằng cách thêm trlệnh với LC_CTYPE=C:

LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs

Cảm ơn, điều đó thực sự đã lừa Bất cứ ý tưởng tại sao tôi không thể tìm thấy urandomhoặc random? Có phải chúng là những "tập tin" ma thuật đặc biệt không tồn tại trên hệ thống tập tin thực tế? (Ngoài ra tôi đã đề xuất một chỉnh sửa để giúp giảm thiểu tình trạng thối liên kết)
Kirk Woll

1
Tôi tin rằng locatekhông trực tiếp tìm kiếm hệ thống tập tin của bạn, mà là tìm kiếm truy vấn của bạn bằng cơ sở dữ liệu dựng sẵn. Cơ sở dữ liệu này rất có thể được cấu hình để bỏ qua / dev / và các hệ thống tệp 'đặc biệt' khác.
lk-

đủ công bằng, nhưng tôi không nhìn thấy nó khi tôi nhìn trực tiếp vào /dev. Đi hình. Nhưng cảm ơn một lần nữa vì sự giúp đỡ.
Kirk Woll

1
dường như không hoạt động vào ngày 10.9; vẫn thất bại với thông báo lỗi tương tự. LC_ALL=Ckhông lừa tho.
Erik Allik

1
Vui lòng thay đổi liên kết đó thành nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte- resultence vì hiện tại nó trỏ đến trang blog gần đây nhất không chứa trthông tin.
Jeroen Wiert Pluimers

11

Những trnỗ lực của bạn để diễn giải đầu vào của nó dưới dạng văn bản trong mã hóa UTF-8. Vì vậy, nó sẽ khiếu nại và hủy bỏ chuỗi byte đầu tiên không hợp lệ UTF-8. Tiền tố trLC_ALL=Choặc LC_CTYPE=Csẽ xuất biến đó vào môi trường tr, do đó thay đổi ý tưởng của nó về ký tự cục bộ được đặt thành tiêu chuẩn C, tức là mọi thứ chỉ là một chuỗi các byte mờ.

Nhân tiện, trình tự \)-+trong lệnh của bạn có chủ ý không? Điều này cũng bao gồm *, cái mà bạn đã bao gồm, nhưng không bao gồm -chính nó như bạn có thể dự định. Thay vào đó, tốt hơn là viết một trong số này:

LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()\-+=' < /dev/urandom
LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)\\-+= < /dev/urandom

6

Như những người khác đã chỉ ra, vấn đề của bạn không phải /dev/urandomlà thiếu, mà là cách thức trhoạt động trên OS X. Thay vì loay hoay với các varialbes phát sinh, hãy sử dụng perlthay thế tr:

perl -pe 'binmode(STDIN, ":bytes"); tr/A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+=//dc;' < /dev/urandom | head -c 32; echo

Điều này có lợi thế là có thể di động trên OS X, Redhat và Ubuntu.

(Tôi cũng đã loại bỏ đường ống đến xargs, thay thế phù thủy echo, để có được một dòng mới ở cuối đầu ra.)


Sớm hay muộn, tôi mong Perl sẽ đưa ra binmode ":utf8"tiêu chuẩn, tại thời điểm đó, giải pháp Perl của bạn sẽ có cùng một vấn đề tr.
Đánh dấu

Đã giải quyết mối quan tâm của Mark bằng cách thêm binmode (STDIN, ": byte") vào mẫu mã.
Trenton

2

Đầu tiên, bạn có ý định đưa vào -hoặc *trong danh sách các ký tự hợp lệ không? Tham số trbao gồm chuỗi )-+có nghĩa là "phạm vi byte bắt đầu bằng )và kết thúc bằng +, thực tế )*+.

Thứ hai, thay vì đọc nhiều kilobyte từ nhóm entropy của kernel (và do đó đánh dấu toàn bộ nhóm là không an toàn, sẽ ảnh hưởng đến bất kỳ quy trình nào khác cần entropy an toàn), hãy xem xét chỉ đọc nhiều bit như bạn cần: sử dụng head -c...như bước đầu tiên , và sau đó dịch thay vì loại bỏ các ký tự không mong muốn.

Phiên bản đặc biệt này của vấn đề hơi khác thường ở chỗ sử dụng 76 biểu tượng khác nhau; hầu hết chỉ muốn chữ và số, vì vậy nếu bạn hài lòng chỉ với 64 ký hiệu, thì việc sử dụng base64tiện ích sẽ giảm thiểu mức tiêu thụ của nhóm entropy (lưu ý rằng 24 là 6/8 của 32):

head -c24 < /dev/random | base64

1

Mã hóa ký tự của miền địa phương của bạn (mà bạn có thể biết với locale charmap) là nhiều byte cho mỗi ký tự.

Phổ biến nhất hiện nay là UTF-8 nơi các ký tự có thể được mã hóa trên 1 đến 4 byte. Không phải tất cả các chuỗi byte tạo thành các ký tự hợp lệ trong UTF-8. Mỗi ký tự không phải ASCII trong UTF-8 bắt đầu bằng một byte có hai bit cao nhất được đặt và cho biết có bao nhiêu byte với bit cao nhất (nhưng không cao thứ hai) được đặt theo sau.

/dev/urandomchứa một luồng byte ngẫu nhiên. trphiên âm ký tự, vì vậy nó cần giải mã các byte đó thành ký tự. Các ký tự ASCII trong phạm vi của bạn đều được mã hóa trên một ký tự trong UTF-8, nhưng trvẫn cần giải mã tất cả các ký tự. Ví dụ, có các mã hóa nhiều byte khác trong đó một số ký tự khác không Achứa byte 0x41 (mã cho A).

Bởi vì luồng byte ngẫu nhiên đó bị ràng buộc để chứa các chuỗi không hợp lệ (ví dụ, chính byte 0x80 không hợp lệ trong UTF-8 vì một ký tự không phải ASCII phải bắt đầu bằng một byte lớn hơn 0xc1 (0xc0 và 0xc1 không có UTF- 8 ký tự)), do đó trtrả về với một lỗi khi điều đó xảy ra.

Những gì bạn muốn ở đây là xem luồng byte đó là các ký tự trong một mã hóa có một byte cho mỗi ký tự. Bất cứ điều gì bạn chọn đều không quan trọng vì tất cả các ký tự trong phạm vi của bạn (giả sử là AZ, bạn có nghĩa là ABCDEFGHIJKLMNOPQRSTUVWXYZ và không phải những thứ như Ý, Ê) là một phần của bộ ký tự di động được mã hóa giống nhau trong tất cả các bảng mã được hỗ trợ trên hệ thống của bạn.

Vì thế, bạn sẽ đặt LC_CTYPEbiến nội địa hóa là biến quyết định bộ ký tự nào được sử dụng và những thứ như thế nào blank, alphacác lớp ký tự chứa. Nhưng đối với định nghĩa của phạm vi AZ, bạn cũng sẽ muốn đặt LC_COLLATEbiến (biến quyết định thứ tự chuỗi).

Các Caka POSIXlocale là một trong đó đảm bảo nhân vật đơn byte và AZ là ABCDEFGHIJKLMNOPQRSTUVWXYZ. Bạn có thể làm:

 LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'

(ở đây di chuyển -đến cuối, nếu không, )-+sẽ được coi là một phạm vi như A-Z)

Nhưng lưu ý rằng LC_ALLbiến này ghi đè tất cả các biến khác LC_*LANGbiến. Vì vậy, nếu LC_ALLđã được xác định khác, ở trên sẽ không có hiệu lực. Vì vậy, thay vào đó bạn chỉ có thể làm:

 LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'

Điều đó sẽ ảnh hưởng đến những thứ khác như ngôn ngữ của thông báo lỗi, nhưng dù sao, việc thay đổi LC_CTYPE có thể đã gây ra sự cố cho thông báo lỗi (ví dụ: không có cách nào để thể hiện thông báo lỗi tiếng Nga hoặc tiếng Nhật trong bảng mã của ngôn ngữ C).


0

Theo trang man , / dev / ngẫu nhiên có thể sẽ đủ cho nhu cầu của bạn. Có lẽ Apple đã ngừng tạo / dev / urandom vì nó không cần thiết?


Tôi cũng không có /dev/random.
Kirk Woll

MacOSX nên có cả / dev / ngẫu nhiên và / dev / urandom. Có lẽ Apple không còn bao gồm những tập tin đặc biệt đó nữa? Hoặc có lẽ nó chỉ ở đó nếu bạn cài đặt XCode?
jsbillings

1
FWIW, cả hai thiết bị đều có mặt trên máy trạm Lion được nâng cấp lên Lion của tôi. Tôi tin rằng nó cũng có mặt trên Lion. Các nút cũng khác nhau (13,0 so với 13,1)
mrb
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.