1
$\begingroup$

What are the best cryptographically secure pseudo-random number generator algorithms, and what are their strengths/weaknesses? I can't seem to come up with a list of them (or maybe I do, but they have such weird names that I don't recognize them).

I'm trying to write a simple program that takes a message and a key and encrypts or decrypts the message by using the key as the seed to a psuedo-random number generator that then generates the key to be used to encrypt/decrypt the message. However, I keep getting frustrated at how hard it is to find a good, safe random function no matter what language I try, so I decided to try to make one myself.

$\endgroup$
  • $\begingroup$ What are the best is off-topic here. See Wikipedia. Instead describe your problem better, which cryptographic algorithm are you using to encrypt? $\endgroup$ – kelalaka Dec 12 '18 at 18:38
  • $\begingroup$ @kelalaka “What are the best” is not answerable, but “what criteria do I need to use to pick one” is, provided that the question describes a specific use case, which this question does. $\endgroup$ – Gilles Dec 12 '18 at 19:33
  • $\begingroup$ @Gilles that is why asked to describe your problem better... he did not say keystream, so I just wondered the encryption algorithm. $\endgroup$ – kelalaka Dec 12 '18 at 19:40
  • $\begingroup$ The question puts me in mind of a key derivation algorithm. If this is desired, my suggestion is Argon2. It can slow brute force attacks to a crawl, even against a very capable and well-equipped adversary. $\endgroup$ – WDS Dec 13 '18 at 12:07
  • 1
    $\begingroup$ Then Gilles answer is fine for you. It is a stream cipher. $\endgroup$ – kelalaka Dec 13 '18 at 16:05
2
$\begingroup$

takes a message and a key and encrypts or decrypts the message by using the key as the seed to a psuedo-random number generator that then generates the key to be used to encrypt/decrypt the message.

This sounds like a stream cipher. You should probably stop looking for a pseudorandom generator and instead look for a stream cipher. But “stream cipher” is both overspecific — why a stream cipher rather than another type of cipher? — and not enough — a stream cipher only encrypts, it doesn't guarantee authenticity. Without authenticity, many systems are vulnerable to oracle attacks which can allow an attacker to recover plaintext by submitting modifications of the ciphertext. So in fact you probably need an authenticated encryption (AEAD) algorithm. If in doubt, use crypto_box from NaCl or libsodium, but pretty much any AEAD interface in any reasonably modern cryptography library would be fine.

I keep getting frustrated at how hard it is to find a good, safe random function no matter what language I try, so I decided to try to make one myself.

If you want to implement a random generator as a learning exercise, go ahead, it's a good learning exercise. But keep in mind that this is only a learning exercise. A well-established crypto library will almost surely do it better than you. Does your implementation properly wipe memory after use? Does your implementation properly report any failure of the entropy source? Might your implementation reveal confidential data via side channels such as timing and memory access patterns? Decried as it is, the authors of OpenSSL have thought about such things. If you haven't then they've done a better job than you.

For the sake of people who came here because the question's title is about PRNG choice: If you really need a pseudorandom number generator, it may help to know that another common name is “deterministic random bit generator” (DRBG). Any of the three algorithms from NIST SP 800-90A (Hash_DRBG, HMAC_DRBG, CTR_DRBG) is a good choice. But once again, note a PRNG has an interface which includes periodic reseeding; you can't easily use it directly to build a stream cipher. If what you want is to encrypt a message then what you want is not a PRNG. A PRNG is what you'd use to generate the key and the IV/nonce. And keep in mind that if you think you need to implement a PRNG, you're probably wrong. Use your operating system and your cryptographic library's random generator interface — as I explain above, they've done a better job than you're likely to.

$\endgroup$
1
$\begingroup$

If you're going to make one yourself I suggest looking at NIST's "Recommendation for Random Number Generation Using Deterministic Random Bit Generators" document and you can pick one of the method's presented there to implement.

Java now includes implementations of these (as do other platforms and libraries) so there's plenty of examples out there for you to look at. You can find the OpenJDK 11 implementations here.

$\endgroup$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.