Ashwin
Ashwin

Reputation: 13537

Using secure random to generate a long number

I have seeded my secure random object with a long number. Now I want to extract another long number. But there is only a function called nextBytes(byte[] b) which gives a random byte[].

Is there any way to get a long number?

SecureRandom ranGen1 = new SecureRandom();
   ranGen1.setSeed(1000);
   SecureRandom ranGen2 = new SecureRandom();
   ranGen2.setSeed(1000);
   byte[] b1= new byte[3];
   byte[] b2=new byte[3];
   ranGen1.nextBytes(b1);
   ranGen2.nextBytes(b2);
   int a1=b1[0];
   int a2=b1[1];
   int a3=b1[2];

   int c1=b2[0];
   int c2=b2[1];
   int c3=b2[2];

   System.out.println(a1+", "+a2+", "+a3);//genearated by ranGen1
   System.out.println(c1+", "+c2+", "+c3);//generated by ranGen2

   System.out.println(ranGen1.nextLong());//genearated by ranGen1

System.out.println(ranGen2.nextLong());//generated by ranGen2

result:

4, -67, 69
4, -67, 69

   -3292989024239613972  //this is using nextLong()
-3292989024239613972 

The Output for Peter Lawrey's code:(Using secure random)

-7580880967916090810 -7580880967916090810
7364820596437092015 7364820596437092015
6152225453014145174 6152225453014145174
6933818190189005053 6933818190189005053
-2602185131584800869 -2602185131584800869
-4964993377763884762 -4964993377763884762
-3544990590938409243 -3544990590938409243
8725474288412822874 8725474288412822874
-8206089057857703584 -8206089057857703584
-7903450126640733697 -7903450126640733697

They are exaclty the same. How could you get different numbers?

This is the output that I am getting after using Peter Lawrey's second update(I am using windows operating system and he seems to be using some other operaing system which has created the confusion)

SHA1PRNG appears to produce the same values with the same seed
The default PRNG on this system is SHA1PRNG

Upvotes: 6

Views: 16872

Answers (4)

Alex Florescu
Alex Florescu

Reputation: 5151

Revised again, this is the correct answer! (and I should follow my own advice and read the documentation more carefully)

Is this what you're using? If so, it extends Random so it has an inherited nextLong() method. As it overrides next() all the typical Random methods will be using the SecureRandom PRNG method.

(see in the comments why my second answer is incorrect.. or rather unnecessary)

I would suggest creating a long by just composing it out of the next 8 bytes or of two ints (returned by next). There's no problem with doing that and I can't see any reason why you wouldn't be able to touch all the long values (think that either of the two 32-bit halves can have values from 0 to 2^32, with equal probability) or why one would be more probable than another (which would mean it's not pseudo-random).

I do not completely understand why the Random documentation indicates that limitation for nextLong(), but I believe it is a limitation of the linear algorithm that it uses (I think linear algorithms have a much shorter cycle - i.e. when they start repeating numbers - than modern PRNGs). I think that's worth exploring on crypto stack exchange for curiosity.

Upvotes: 6

Peter Lawrey
Peter Lawrey

Reputation: 533530

Note: With Random, a given seed will always produce the same results. With SecureRandom it will not. The seed just adds to the randomness.

Have you ever user secure random? The whole point of seed is to produce the same sequesnce of numbers. This is also the case with secure random. Two secure random numbers seeded with the same value produce same sequence of random numbers.

public static void main(String... args) throws NoSuchProviderException, NoSuchAlgorithmException {
    testRNG("NativePRNG");
    testRNG("SHA1PRNG");
    System.out.println("The default PRNG on this system is " + new SecureRandom().getAlgorithm());
}

private static void testRNG(String prng) throws NoSuchAlgorithmException, NoSuchProviderException {
    SecureRandom sr1 = SecureRandom.getInstance(prng, "SUN");
    SecureRandom sr2 = SecureRandom.getInstance(prng, "SUN");
    sr1.setSeed(1);
    sr2.setSeed(1);
    for (int i = 0; i < 10; i++) {
        if (sr1.nextLong() != sr2.nextLong()) {
            System.out.println(prng + " does not produce the same values with the same seed");
            return;
        }
    }
    System.out.println(prng + " appears to produce the same values with the same seed");
}

prints

NativePRNG does not produce the same values with the same seed
SHA1PRNG appears to produce the same values with the same seed
The default PRNG on this system is NativePRNG

go and try it first

Good advice, but just trying it doesn't always give you the whole answer in this case.

Upvotes: 2

Rasmus Faber
Rasmus Faber

Reputation: 49647

BigInteger randomNumber = new BigInteger(numBits, random);

Upvotes: 2

JB Nizet
JB Nizet

Reputation: 691765

SecureRandom extends Random, and Random has a nextLong() method: http://docs.oracle.com/javase/6/docs/api/java/util/Random.html#nextLong%28%29

Upvotes: 4

Related Questions