Các byte mà bạn XOR với thông báo để lấy bản mã được gọi là luồng khóa. Có thể an toàn khi tạo luồng khóa bằng cách sử dụng CSPRNG, trình tạo số giả ngẫu nhiên an toàn bằng mật mã và hạt giống tĩnh.
Tuy nhiên, có những vấn đề thực tế nếu bạn sử dụng CSPRNG của hệ thống:
- đôi khi nó có thể quyết định (tái) gieo hạt;
- thuật toán có thể thay đổi theo thời gian hoặc giữa các hệ thống;
- cách các byte ngẫu nhiên được trích xuất có thể thay đổi (ví dụ: có thể quyết định căn chỉnh các từ).
Vì vậy, bạn phải chắc chắn rằng thao tác CSPRNG được đúc kết trước khi bạn sử dụng nó để mã hóa thứ gì đó. Trong trường hợp xấu nhất, dữ liệu ngẫu nhiên được đưa vào để khởi tạo mật mã của bạn, trong trường hợp đó, dữ liệu sẽ bị mất một cách hiệu quả. Cái này đã xảy ra trước đây khi "SHA1PRNG" của Sun trước tiên được thay thế bằng một thuật toán khác và sau đó là dữ liệu ngẫu nhiên OpenSSL trên Android.
Về mặt lý thuyết, mật mã luồng - hoặc mật mã khối ở chế độ luồng - đều là CSPRNG khi có một hạt giống (sự kết hợp giữa khóa và IV/nonce), một thuật toán cụ thể và cách truy xuất luồng khóa theo quy định. Vì vậy, nói chung, câu trả lời nhàm chán là sử dụng AES-CTR để tạo luồng khóa và sử dụng AES-GCM - sử dụng AES-CTR trong nội bộ - nếu bạn cũng yêu cầu xác thực thư. Trên các hệ thống không có khả năng tăng tốc phần cứng, có thể sử dụng mật mã dòng như ChaCha20 để thay thế.
Ít nhàm chán hơn một chút, bạn cũng có thể tạo mật mã luồng từ hàm băm bằng cách sử dụng chế độ bộ đếm. Tốt hơn là bạn nên sử dụng cấu trúc MAC, chẳng hạn như HMAC cho điều đó. Trên thực tế, hầu hết CSPRNG mà các hệ thống cung cấp không nhiều hơn thế - nhưng như đã nêu, chúng thường được thiết kế để cung cấp dữ liệu ngẫu nhiên, không phải dữ liệu xác định. Và vâng, nhìn chung các thuật toán này chậm hơn so với mật mã luồng chuyên dụng hoặc mật mã khối được tăng tốc phần cứng - chúng phức tạp hơn hơn là ít phức tạp hơn.