javarandomcryptographysecure-random

Java: How do I set the nonce when using DRBG SecureRandom?


Java 9 introduced a new SecureRandom called DRBG. I want to use it to deterministically generate random numbers. The problem is that it uses a nonce internally which it always changes, so I don't get the same numbers for the same seeds. It does have an option internally to set that nonce, but I can't find any public methods that can accomplish that. How can I change that nonce?


Solution

  • The SecureRandom class still states:

    Additionally, SecureRandom must produce non-deterministic output.

    Although the DRBG schemes listed are deterministic, they will still be seeded by the runtime environment, which commonly retrieves entropy from the operating system.


    There may be some confusion what "DRBG" means in this respect. Although the underlying algorithm is deterministic in nature that just means that it relies on the entropy in the seed to generate a stream of bits. These random bits are computationally indistinguishable from random, even though they only contain a limited number of entropy. If an adversary can guess the seed then the entire stream becomes known. But if the seed contains enough entropy then this is impossible in practice.

    "DRBG" simply refers to a pre-configured and well defined, NIST standardized algorithm (which one can be seen in the answers to this question). It differs from "SHA1PRNG" because of that; "SHA1PRNG" is a proprietary algorithm by Sun that is completely under-specified and other implementations - such as the one in Android - were both different and insecure. Earlier versions of Java did allow you to deterministically generate secure random values from "SHA1DRBG" you seeded it before you retrieved any output from it.


    You can yourself create a SecureRandomSpi that is deterministic, but then you would violate the contract for SecureRandomSpi. And you'd of course have to implement a provider if you did that.

    Implementing SecureRandomSpi would be the correct way to do it, but note that you can actually inherit from SecureRandom so there is a shortcut, if a bit of a hack.

    To have a fast, deterministic "random" implementation you probably want to use a stream cipher underneath. That's more efficient than a DRBG and it doesn't have functions for e.g. reseeding which you can definitely do without. Possibly you'd also implement a KDF to generate the key required for the DRBG.

    If you go this way than please clearly specify your protocol, otherwise developers will have to reverse engineer your code just to get to the algorithm used.