3

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!

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
tilpner
  • 4,351
  • 2
  • 22
  • 45
  • Either they are predictable, or they are not. If you want them to be predictable, use the same seed. But as long as the seed is shared, there is a way for an attacker to get it. – etienne Apr 09 '13 at 15:46
  • The seed is not shared, I don't know it, only the user knows it. So if the same seed is input by the user, the same random numbers should be output. – tilpner Apr 09 '13 at 15:50
  • Oh, right. Then try to use `SecureRandom sec = SecureRandom.getInstance("SHA1PRNG");` and check if it outputs the same results on Android and on a standard JVM – etienne Apr 09 '13 at 15:53
  • I tried that before writing my post (its written in there), and the output IS different... – tilpner Apr 09 '13 at 15:55
  • It sounds like you want to use a hash algorithm instead of a random number generator http://stackoverflow.com/questions/1515489/java-compute-sha-1 – Zim-Zam O'Pootertoot Apr 09 '13 at 15:55
  • Whatever RNG you use must use a common seed. – Hot Licks Apr 09 '13 at 15:55
  • Yeah, I know about the hashing approach, but what if I need more random data than the hashing method will provide? – tilpner Apr 09 '13 at 15:55
  • @HotLicks I DO use a common seed. – tilpner Apr 09 '13 at 15:56
  • But some RNGs may not let you set the seed. (At least not the entire seed.) – Hot Licks Apr 09 '13 at 16:00
  • @HotLicks But using the default JRE SHA1PRNG, it is reproducable. – tilpner Apr 09 '13 at 16:03
  • Then maybe one of the implementations is wrong. Or it factors in the device serial, or some such. – Hot Licks Apr 09 '13 at 16:04
  • @HotLicks That exactly might be the problem, that the implementations are different. How would I then *carry over* an implementation? – tilpner Apr 09 '13 at 16:08
  • If you can't find a built-in RNG that is consistent across your platforms, you'll need to find the source for an "acceptable" one and port it to your various platforms. (In fact, if this is important for on-going support and not simply testing, it may be wisest to do the latter, since it's hard to tell when existing support might change in this "inconsequental" way and break you.) – Hot Licks Apr 09 '13 at 16:19
  • (But seem my comment below. Perhaps the simplest solution to your problem is to use an encryption algorithm to encrypt a known/dummy string of text (though you'd need to use a known "salt", etc).) – Hot Licks Apr 09 '13 at 16:26
  • for future reference, this question finds its correct answer at http://stackoverflow.com/questions/9151852/reproducibility-of-java-pseudo-random-numbers-across-systems-and-versions – Erich Eichinger Jan 03 '16 at 09:57

4 Answers4

1

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...

tilpner
  • 4,351
  • 2
  • 22
  • 45
0

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

Zim-Zam O'Pootertoot
  • 17,888
  • 4
  • 41
  • 69
  • 1
    That's not quite what I need. There is (or I haven't seen it) no way to make it output the same, several times. – tilpner Apr 09 '13 at 15:49
0

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.

Lee Meador
  • 12,829
  • 2
  • 36
  • 42
  • I edited my post: The seed is generated based on user input. Also: I doubt this is as cryptographically safe as SHA1PRNG. It may not be predictable, guessing from one byte to the next, but the first byte should be predictable when you know the seed... – tilpner Apr 09 '13 at 16:01
  • I would maintain, and you may disagree, that the way you want it repeatable makes "cryptographically safe" an illusion, at best. – Lee Meador Apr 09 '13 at 16:05
  • Lets call it 'reproducible', not 'repeating'. – tilpner Apr 09 '13 at 16:30
0

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.)

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • Is this supposed to be an answer? (Don't want to sound stupid, but none of this is new to me, neither does it help my problem) How about including your comment in this? – tilpner Apr 09 '13 at 16:28
  • @StackOverflowException - Basically it's just a comment that's too long to fit in a comment. – Hot Licks Apr 09 '13 at 16:29
  • Sorry, I read your 'comment' after reading this 'comment-post'. – tilpner Apr 09 '13 at 16:31