Question

I need/want to get random (well, not entirely) numbers to use for password generation.

What I do: Currently I am generating them with SecureRandom.
I am obtaining the object with

SecureRandom sec = SecureRandom.getInstance("SHA1PRNG", "SUN");

and then seeding it like this

sec.setSeed(seed);

Target: A (preferably fast) way to create random numbers, which are cryptographically at least a safe as the SHA1PRNG SecureRandom implementation. These need to be the same on different versions of the JRE and Android.

EDIT: The seed is generated from user input.

Problem: With SecureRandom.getInstance("SHA1PRNG", "SUN"); it fails like this: java.security.NoSuchProviderException: SUN. Omitting , "SUN" produces random numbers, but those are different than the default (JRE 7) numbers.

Question: How can I achieve my Target?

You don't want it to be predictable: I want, because I need the predictability so that the same preconditions result in the same output. If they are not the same, its impossible hard to do what the user expects from the application.

EDIT: By predictable I mean that, when knowing a single byte (or a hundred) you should not be able to predict the next, but when you know the seed, you should be able to predict the first (and all others). Maybe another word is reproducible.

If anyone knows of a more intuitive way, please tell me!

Was it helpful?

Solution

I ended up isolating the Sha1Prng from the sun sources which guarantees reproducibility on all versions of Java and android. I needed to drop some important methods to ensure compatibility with android, as android does not have access to nio classes...

OTHER TIPS

I recommend using UUID.randomUUID(), then splitting it into longs using getLeastSignificantBits() and getMostSignificantBits()

If you want predictable, they aren't random. That breaks your "Target" requirement of being "safe" and devolves into a simple shared secret between two servers.

You can get something that looks sort of random but is predicatable by using the characteristics of prime integers where you build a set of integers by starting with I (some specific integer) and add the first prime number and then modulo by the 2nd prime number. (In truth the first and second numbers only have to be relatively prime--meaning they have no common prime factors--not counting 1, in case you call that a factor.

If you repeat the process of adding and doing the modulo, you will get a set of numbers that you can repeatably reproduce and they are ordered in the sense that taking any member of the set, adding the first prime and doing the modulo by the 2nd prime, you will always get the same result.

Finally, if the 1st prime number is large relative to the second one, the sequence is not easily predictable by humans and seems sort of random.

For example, 1st prime = 7, 2nd prime = 5 (Note that this shows how it works but is not useful in real life)

Start with 2. Add 7 to get 9. Modulo 5 to get 4. 4 plus 7 = 11. Modulo 5 = 1.

Sequence is 2, 4, 1, 3, 0 and then it repeats.

Now for real life generation of numbers that seem random. The relatively prime numbers are 91193 and 65536. (I chose the 2nd one because it is a power of 2 so all modulo-ed values can fit in 16 bits.)

int first = 91193;
int modByLogicalAnd = 0xFFFF;

int nonRandomNumber = 2345; // Use something else
for (int i = 0; i < 1000 ; ++i) {
    nonRandomNumber += first;
    nonRandomNumber &= modByLogicalAnd;
    // print it here
}

Each iteration generates 2 bytes of sort of random numbers. You can pack several of them into a buffer if you need larger random "strings".

And they are repeatable. Your user can pick the starting point and you can use any prime you want (or, in fact, any number without 2 as a factor).

BTW - Using a power of 2 as the 2nd number makes it more predictable.

Ignoring RNGs that use some physical input (random clock bits, electrical noise, etc) all software RNGs are predicable, given the same starting conditions. They are, after all, (hopefully) deterministic computer programs.

There are some algorithms that intentionally include the physical input (by, eg, sampling the computer clock occasionally) in attempt to prevent predictability, but those are (to my knowledge) the exception.

So any "conventional" RNG, given the same seed and implemented to the same specification, should produce the same sequence of "random" numbers. (This is why a computer RNG is more properly called a "pseudo-random number generator".)

The fact that an RNG can be seeded with a previously-used seed and reproduce a "known" sequence of numbers does not make the RNG any less secure than one where your are somehow prevented from seeding it (though it may be less secure than the fancy algorithms that reseed themselves at intervals). And the ability to do this -- to reproduce the same sequence again and again is not only extraordinarily useful in testing, it has some "real life" applications in encryption and other security applications. (In fact, an encryption algorithm is, in essence, simply a reproducible random number generator.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top