how to make SecureRandom to be constant using seedBytes in JAVA? - java

I have a kotlin android application and I need to use seed bytes to generate a secure random. how can I make the secure random to give the same number for the same seed bytes?
this is my code:
val seedBytes = byteArrayOf(116,-64,24,11,126,59,70,-12,68,-39,-33,65,-38,-88,-75,87,97,-112,-22,-64,12,44,-2,-41,-28,-52,82,107,-109,-66,47,41,-59,-44,-114,-95,80,-83,37,107,27,-93,-38,-116,37,-60,-97,98,-102,-61,-50,-83,69,27,11,-12,116,26,59,21,116,69,-90,-19);
val RANDOM = SecureRandom(seedBytes);
println(RANDOM) // => I want this print to always be the same
but right now for example one time I get
java.security.SecureRandom#c708450
and the other time I get
java.security.SecureRandom#de2e6b1

Your not getting a value from the random, but printing the instance of the random you have created. You cannot make this the same each time however if you call nextInt() for example it will be the same in both cases.

You've done it. You're a bit confused about that output.
System.out.println(someObj)
This is just syntax sugar for System.out.println(someObj.toString());.
The default toString() implementation, as found in java.lang.Object, is this:
public String toString() {
return this.getClass().getName() + "#" + printAsHex(System.identityHashCode(this));
}
In other words, that #c708450 stuff is the system's identity hash code for your SecureRandom instance. This is, vastly oversimplifying, it's memory address. The point is: If you have 2 identical references, the number is the same. That's all it does, it is otherwise meaningless, and every object in the system has this, it has nothing whatsoever to do with Random / SecureRandom, and the location in heap memory where the SecureRandom instance is at, has zero effect on the random numbers it spits out. In other words, that #foo thing is not the seed value. It is a number that has no meaning at all, other than when it is the same as another identity hash code.
The API of Random does not offer a way to get the seed value, nor to get the 'distance' from it. Therefore, it is not immediately obvious how one would ascertain that two separate instances of SecureRandom are going to produce the same sequence forever.
However, in practice, just invoke .nextInt() 100 times on both and if the same 100 numbers fall out? Rest assured.
Thus, if you want to print a 'footprint' of where your secure random is it, print a few invokes of .nextInt() or .nextByte(). This is more involved than just System.out.println(theSecureRandomInstance) - there is no easy way out; you'll have to write a method that does this (and be aware that this will advance the sequence, of course. You also can't shove em back in, either).

So the solution for me was to extend the android's SecureRandom and then re implement it with the java original code that permits generating same secure random with the same seed. it is not possible to do it with Android's built in Secure random because the possibility to create the same random with the same seed has been deprecated in Android N and was removed in Android P

Related

Is this way of generating a securerandom biginteger secure?

So I tried this line of code in java which generates a random integer that is 40 bytes long. I have no clue if it's secure and I wondered if anyone with a little bit more experience than me could explain.
I would like to know if this is cryptographically secure. meaning is this a secure way of generating a random number that's a BigInteger. If it isn't secure what would be a good way to generate a full cryptographically random BigInteger.
SecureRandom random = new SecureRandom();
BigInteger key_limit = new BigInteger("10000000000000000000000000000000000000000");
int key_length = key_limit.bitLength();
BigInteger key_1 = new BigInteger(key_length, random);
You're rolling your own crypto.
Be prepared to fail. The odds that the code you end up writing will actually be secure are infinitesemal. It is very, very, very easy to make a mistake. These mistakes are almost always extremely hard to test for (for example, your algorithm may leak information based on how long it takes to process different input, thus letting an attacker figure out the key in a matter of hours. Did you plan on writing a test that checks if all attempts to decode anything, be it the actual ciphertext, mangled ciphertext, half of ciphertext, crafted input specifically designed to try to derive key info by checking how long it takes to process, and random gobbledygook all take exactly equally long? Do you know what kind of crafted inputs you need to test for, even?)
On the topic of timing attacks, specifically, once you write BigInteger, you've almost certainly lost the game. It's virtually impossible to write an algorithm based on BI that is impervious to timing attacks.
An expert would keep all key and crypto algorithm intermediates in byte[] form.
So, you're doing it wrong. Do not roll your own crypto, you'll mess it up. Use existing algorithms.
If you really, really, really want to go down this road, you need to learn, a lot, before you even start. Begin by analysing a ton of existing implementations. Try to grok every line, try to grok every move. For example, a password hash checking algorithm might contain this code:
public boolean isEqual(byte[] a, byte[] b) {
if (a.length != b.length) throw new IllegalArgumentException("mismatched lengths");
int len = a.length;
boolean pass = true;
for (int i = 0; i < len; i++) {
if (a[i] != b[i]) pass = false;
}
return pass;
}
and you may simply conclude: Eh. Weird. I guess they copied it from C or something, or they just didn't know they could have removed that method entirely and just replaced it with java.util.Arrays.equals(a, b);. Oh well, it doesn't matter.
and you would be wrong - that's what I mean by understand it all. Assume no mistakes are made. Arrays.equals can be timing-attacked (the amount of time it takes for it to run tells you something: The earlier the mismatch, the faster it returns. This method takes the same time, but only 'works' if the two inputs are equal in length, so it throws instead of returning the seemingly obvious false if that happens).
If you spend that much time analysing them all, you'll have covered this question a few times over.
So, with all that context:
This answer is a bazooka. You WILL blow your foot off. You do not want to write this code. You do not want to do what you are trying to do. BigInteger is the wrong approach.
new BigInteger(8 * 40, secureRandom); will get the job done properly: Generates a random number between (0 and 2^320-1), inclusive, precisely 40 bytes worth. No more, no less.
40 bytes worth of randomness can be generated as follows:
byte[] key = new byte[40];
secureRandom.nextBytes(key);
But this is, really, still a grave error unless you really, really, really know what you are doing (try finding an existing implementation that has some reliable author or has been reviewed by an expert).
You will get a BigInteger containing a securely generated random number that way.
However, that method for calculating the bit length is (to say the least) odd. I don't know about you, but most programmers would find it difficult to work out how many zeros there are in that string. Then, the computation is going to give you a bit count such that 2bits is less than the number.
It would make a lot more sense (to me) to just specify a bit count directly and code it, and add a comment to explain it.
To a first approximation1 2(10*N) is 1000N. However, the former is slightly greater than the latter. That means if your code is intended to give you 40 byte random keys, your computed key length will be off by one.
1 - Experienced programmers remember that ... and inexperienced programmers can use a programmer's calculator.

Is a generated UUID from a String reversible?

If I generate a UUID from a "seed" string as follows, is there any way for someone to re-generate the original string?
UUID uuid = null;
try {
uuid = UUID.nameUUIDFromBytes(("seedString").getBytes("utf8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("UUID: " + uuid.toString());
I would assume it isn't possible, as I believe this person found here: Convert UUID to bytes
However, I see that the same UUID is generated every time from a certain String/bytes, and since it has to be unique, simple "seed" values could just be guessed? For example, UUID of f is 8fa14cdd-754f-31cc-a554-c9e71929cce7 so if I see that I know it was generated from "f".
Since you are getting the UUID by casting bytes to a UUID, and you are always using the same starting bytes to cast from, the uuid would always be the same UUID across multiple runs.
I think you've confused a random seed with the "from bytes" method in the UUID routines. It is more like a cast than a seed initialization. And even if it was like a seed initialization, initializing with a constant seed would only mean that you always walk the "same" pseudo-random path (meaning that after walking it once, you can know the next step(s)).
aug also makes an excellent point, which I'll elaborate a bit on here. A UUID is an identifier, which is assumed to be unique only by virtue of there being so many to choose from; however, if you create a routine that returns the same one(s) repeatedly, it's not going to be unique due to your selection mechanism. The actual mechanism doesn't assure uniqueness; even less so when using a routine guaranteed to return identical values.
As they are not guaranteed to be unique (UUIDs have a fixed number of bits and eventually all combinations can be exhausted), one can imagine that there are more inputs than UUIDs (although there's a lot of UUIDs) so UUID collision is inevitable (even if it would theoretically take more time than the heat death of the universe). From a practical side of things, you probably have little to worry about; but, it could still (minuscule chance) happen.
This also means that one can (in theory) guarantee that some two inputs out there can wind up with the same UUID, and as a result, UUIDs are not generally reversible (however, in specific (limited) cases, perhaps they could be made reversible).
There are an infinite number of strings that may generate a given UUID, so even if somebody guesses the string you used to create a given UUID, they may never be sure.

Achieve more randomness through user input in Java

I want to achieve more randomness in my key generation implemented in java since the key strength is depending on it.
I want to use the java.security.KeyPairGenerator to create private and public keys.
A seed can be defined with the SecureRandom object.
SecureRandom random = new SecureRandom();
byte[] rand = new byte[8]; // or only one byte
Imagine I create the random byte[] as follows:
// new KeyPress registered
long currentTime = System.currentTimeMillis();
long time = currentTime - lastTime;
lastTime = currentTime;
byte = time % Byte.MAX_VALUE;
// add byte to array or to the SecureRandom object
random.setSeed(byte);
The initialize method allows to add the seed to the generator object. This should increase
the randomness of the keys.
// adds the seed to the generator
keyGen.initialize(4096, random);
The question is shall I set the seed of the key generator after all user inputs or after for example 8 bytes?
I know that the randomness gained here depends on the precision of the system clock. But I assume that the currentTimeMillis() method is precise.
Do you think this is a solution for more randomness?
Or do you think this does not change anything?
EDIT 1 03.12.13
First, thank you for your comments and thoughts!
#Quincunx "I would say that SecureRandom is probably random enough."
Enough for what? I mean I think it depends on what you need it for. Right?
And the question was how can I even increase the randomness?!
#IT-Pro yeah, I could use the square of the time, but I think the user input is more random, right?
Did you mean by saying after user input to collect an array of bytes and pass it after the user finished all his inputs to the generator?
EDIT 2 03.12.13
#Erickson
I think what you are saying is not true!
"these system level devices are already gathering entropy from key presses"
Can you please share a link to this?
You might have some more understanding in this topic than me, but please, if you say something like that I would like to read some more details about it!
This isn't necessary. It won't hurt your security, but it will hurt the readability—and credibility—of your code.
Providers of SecureRandom will seed the generator for you. The SUN provider and other quality providers will use a source of entropy from the underlying system, like /dev/random or /dev/urandom; these system level devices are already gathering entropy from key presses and other, less predictable source, or even from truly random physical processes.
So, I would suggest that you not bother. At best, key press timing will only give you a bit or two of entropy per key press, and that's only if the system source hasn't already included that event.
You could always take the cube root of currentTimeMillis()*currentTimeMillis()
That's a pretty random seed.
And yes. It seems that after user input is the best solution.

Making a line of code difficult to read

Im writing a way of checking if a customers serial number matches my hard coded number. Is there a way of making this as hard to read as possible in case an undesirable gets their hands on the code?
I am working in java.
For instance (pseudo code)
if (x != y) jump out of code and return error
Cheers , apologies if this is a bit of an odd one
Security through obscurity is always a bad idea. You don't need to avoid it, but you should not trust solely on it.
Either encrypt your serials with a key you type in at startup of the service, or just specify the serials as hex or base64, not ASCII.
The normal way to do this would be to use a hash.
Create a hash of your serial code.
To validate the client serial, hash that using the same function.
If the hashes match, the serial was correct, even though the serial itself was not in the code.
By definition, a from the hash it's almost impossible to deduce the original code.
Making the code look complex to avoid being hacked never helps!
You can try SHA1 or some other one-way encrypting (MD5 not so secure but it's pretty good). Don't do this:
if (userPassword equals myHardCodedpassword)
Do this:
if (ENCRYPTED(userPassword) equals myhardcodedEncryptedpassword)
So the code-reader only can see an encrypted (and very very very difficult to decrypt) value.
Tangle the control structure of the released code?
e.g feed the numbers in at a random point in the code under a different variable and at some random point make them equal x and y?
http://en.wikipedia.org/wiki/Spaghetti_code
There is a wikipedia article on code obfuscation. Maybe the tricks there can help you =)
Instead of trying to make the code complex, you can implement other methods which will not expose your hard-coded serial number.
Try storing the hard coded number at some permanent location as encrypted byte array. That way its not readable. For comparison encrypt the client serial code with same algorithm and compare.

Java: Can (new Random()).nextInt(5) always return the same number?

Sometimes this piece of code always returns the same number (and sometimes it works fine):
(new Random()).nextInt(5)
I have suspicions where the problem is - it probably always creates a new Random with the same seed. So what would be the best solution:
create a static var for Random() and
use it instead.
use Math.random() * 5
(looks like it uses a static var
internally)
or something else? I don't need anything fancy just something that looks random.
Also it would be helpful if someone can explain why the original code sometimes works and sometimes it doesn't.
Thanks.
The javadoc for java.util.Random is clear:
If two instances of Random are created
with the same seed, and the same
sequence of method calls is made for
each, they will generate and return
identical sequences of numbers.
The default constructor is also clear:
Creates a new random number generator.
This constructor sets the seed of the
random number generator to a value
very likely to be distinct from any
other invocation of this constructor.
In other words, no guarantees.
If you need a more random algorithm, use java.security.SecureRandom.
...Sometimes this piece of code [..] returns the same number (and sometimes it works fine)...
So it works randomly??? :) :) :)
Ok, ok, downvote me now!!
If you're calling that line of code on successive lines, then yes, the two Random instances you're creating could be created with the same seed from the clock (the clock millisecond tick count is the default seed for Random objects). Almost universally, if an application needs multiple random numbers, you'd create one instance of Random and re-use it as often as you need.
Edit: Interesting note, The javadoc for Random has changed since 1.4.2, which explained that the clock is used as the default seed. Apparently, that's no longer a guarantee.
Edit #2: By the way, even with a properly seeded Random instance that you re-use, you'll still get the same random number as the previous call about 1/5 of the time when you call nextInt(5).
public static void main(String[] args) {
Random rand = new Random();
int count = 0;
int trials = 10000;
int current;
int previous = rand.nextInt(5);
for(int i=0; i < trials; ++i)
{
current = rand.nextInt(5);
if( current == previous )
{
count++;
}
}
System.out.println("Random int was the same as previous " + count +
" times out of " + trials + " tries.");
}
In Java 1.4, the default seed of of a new Random instance was specified in the API documentation to be the result of System.currentTimeMillis(). Obviously, a tight loop could create many Random() instances per tick, all having the same seed and all producing the same psuedo-random sequence. This was especially bad on some platforms, like Windows, where the clock resolution was poor (10 ms or greater).
Since Java 5, however, the seed is set "to a value very likely to be distinct" for each invocation of the default constructor. With a different seed for each Random instance, results should appear random as desired.
The Javadoc for Random isn't explicit about this, but the seed it uses is probably dependent on the current system time. It does state the random numbers will be the same for the same seed. If you use the call within the same millisecond, it will use the same seed. The best solution is probably to use a static Random object and use it for subsequent calls to the method.
The best way to approximate uniform distribution is to use the static method Random.nextInt(n) to produce integers in the range [0, n-1] (Yes, n is excluded). In your particular example, if you want integers in the range 0 to 5, inclusive, you would call Random.nextInt(6).

Categories

Resources