2015-05-27 14 views
6

Tôi cần tạo dữ liệu ngẫu nhiên mã hóa an toàn trong C++ 11 và tôi lo rằng việc sử dụng random_device cho tất cả dữ liệu sẽ hạn chế hiệu suất nghiêm trọng (xem slide 23 của Stephan T. Lavavej "rand() Considered Harmful") thử nghiệm nó (trên hệ thống của mình), random_device là 1,93 MB/s và mt19937 là 499 MB/s) vì mã này sẽ chạy trên thiết bị di động (Android thông qua JNI và iOS) có thể chậm hơn so với các con số ở trên. Ngoài ra, tôi biết rằng mt19937 không an toàn về mặt mã hóa, từ wikipedia: "quan sát đủ số lần lặp (624 trong trường hợp của MT19937, vì đây là kích thước của vectơ trạng thái mà từ đó các lần lặp lại trong tương lai được tạo ra) cho phép người ta dự đoán tất cả các lần lặp lại trong tương lai ".Tôi có thể tạo dữ liệu ngẫu nhiên bảo mật mã hóa từ sự kết hợp của random_device và mt19937 với khả năng chèn lại không?

Lấy tất cả các thông tin trên vào tài khoản, tôi có thể tạo dữ liệu ngẫu nhiên mã hóa an toàn bằng cách tạo một hạt giống ngẫu nhiên mới từ random_device cứ 624 lần lặp lại mt19937 không? Hoặc (có thể) tốt hơn, mỗi lần lặp X mà X là một số ngẫu nhiên (từ random_device hoặc mt19937 seeded bởi random_device) giữa 1 và 624?

+1

'random_device' thậm chí không bắt buộc phải không xác định, vì vậy tôi nghĩ đây không phải là ý tưởng hay. Nếu bạn thực sự cần dữ liệu không xác định, sử dụng bất cứ API mã hóa nào mà hệ điều hành cung cấp có lẽ là cách để đi. – Praetorian

+0

@Praetorian Trên iOS, LLVM sử dụng/dev/urandom như là nguồn được bảo đảm an toàn về mặt mã hóa theo [this] (https://www.apple.com/br/ipad/business/docs/iOS_Security_Oct12.pdf) (Trang 7). Trên Android, gcc sử dụng/dev/random hoặc/dev/urandom như nguồn của nó, do đó tôi có thể chọn khởi tạo bằng "/ dev/random" được OpenSSl và những người khác sử dụng và đảm bảo (với khả năng tốt nhất của Android) rằng nó không xác định –

+2

Nếu bạn biết một nguồn 'random_device' được ưu tiên phù hợp để sử dụng như một CSPRNG, thì rõ ràng đó là một lựa chọn phù hợp. Nhưng tôi vẫn sẽ cảnh giác với ý tưởng 'mt19937' của bạn. Một quy tắc đơn giản khi nói đến mật mã nên, trừ khi bạn là một chuyên gia trong lĩnh vực này, luôn luôn thích một giải pháp đã được chứng minh hiện có hơn là làm một cái gì đó có vẻ thông minh. Có một xác suất lớn hơn nhiều khi bạn vặn vẹo thứ gì đó hơn là đưa ra một ý tưởng thật sự mới lạ. Bạn đã thử nghiệm thông lượng ý tưởng của mình chưa? 'mt19937' có 19937 bit trạng thái, do đó việc tái nhập lại thường xuyên có thể không hoạt động tốt hơn' random_device' – Praetorian

Trả lời

6

Đừng làm điều này. Nghiêm túc, chỉ cần không. Đây không chỉ là yêu cầu rắc rối - nó giống như yêu cầu và cầu xin cho rắc rối bằng cách đi vào phần tội phạm nhất của thành phố nguy hiểm nhất mà bạn có thể tìm thấy, mang theo rất nhiều vật có giá trị.

Thay vì cố gắng tái hạt giống MT 19937 thường đủ để che đậy mức độ không an toàn, tôi khuyên bạn nên tạo số ngẫu nhiên bằng cách chạy AES ở chế độ truy cập. Điều này yêu cầu bạn nhận được một (nhưng chỉ một) số ngẫu nhiên tốt có kích thước phù hợp để sử dụng làm "hạt giống" ban đầu cho máy phát điện của bạn.

Bạn sử dụng khóa đó làm khóa cho AES và chỉ cần sử dụng khóa đó để mã hóa số liên tiếp để có luồng đầu ra trông ngẫu nhiên nhưng dễ tái tạo.

Điều này có nhiều lợi thế. Đầu tiên, nó sử dụng một thuật toán thực sự được nghiên cứu rất nhiều, và thường được cho là khá an toàn. Thứ hai, điều đó có nghĩa là bạn chỉ cần phân phối một số ngẫu nhiên (khá nhỏ) làm "khóa" cho toàn bộ hệ thống. Thứ ba, nó có thể cung cấp thông lượng tốt hơn. Cả hai Intel's và (dường như) independent tests cho thấy một loạt các thông lượng mà bắt đầu cạnh tranh với những gì bạn đang trích dẫn cho MT 19937 ở mức thấp, và lên đến khoảng 4-5 lần nhanh hơn ở đầu cuối. Với cách bạn đang sử dụng nó, tôi hy vọng sẽ thấy bạn nhận được kết quả gần (và thậm chí có thể vượt quá) đầu cuối của phạm vi mà chúng hiển thị.

Điểm mấu chốt: AES ở chế độ truy cập rõ ràng là giải pháp tốt hơn cho vấn đề trong tầm tay. Điều tốt nhất bạn có thể hy vọng là MT 19937 kết thúc gần như nhanh và gần như an toàn. Trong thực tế, nó có thể sẽ thất vọng cả những hy vọng, và kết thúc cả hai chậm hơn và đáng kể ít an toàn.


1. Làm thế nào nó sẽ vượt quá những kết quả đó? Đó chắc chắn là dựa trên việc mã hóa dữ liệu hàng loạt - nghĩa là đọc một khối dữ liệu từ RAM, mã hóa nó và ghi kết quả trở lại RAM. Trong trường hợp của bạn, bạn không cần phải đọc kết quả từ RAM - bạn chỉ cần tạo ra các số liên tiếp trong CPU, mã hóa chúng và ghi lại kết quả.

5

Câu trả lời ngắn gọn là, không bạn không thể. Các yêu cầu đối với một RNG mã hóa an toàn rất nghiêm ngặt, và nếu bạn phải đặt câu hỏi này ở đây, thì bạn không đủ nhận thức về các yêu cầu đó.Như Jerry nói, AES-CTR là một lựa chọn, nếu bạn cần lặp lại. Một tùy chọn khác, không cho phép lặp lại, sẽ tìm kiếm một triển khai của Yarrow hoặc Fortuna cho hệ thống của bạn. Nói chung, tốt hơn hết là tìm CSRNG trong thư viện hơn là cuộn của riêng bạn. Nhà văn thư viện nhận thức đầy đủ các yêu cầu đối với một CSRNG tốt.

Các vấn đề liên quan