Sorry I didn't put enough details on my last question, I didn't expect that there is really lots of factors, so most answers were left for speculations. In this question, I will give the scenario I am looking at:

This is the code

 //seed is 64xF Hex
 //example 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

   var extra = 'something-1'
   var hmacSeed = createHmac('sha512', seed);   
   var hmacSeedWithExtra = hmaxSeed.update(extra).digest('hex'); 

 //get first 5 digits of the hex
   var first5hex = hmacSeedWithExtra.substring(0,  5);

 //convert first 5 hex to integer
   var first5 = parseInt(first5hex , 16);

 //random is   
   var random = (result % 10000) / 100;

This should produce a number between 0 and 100, if it is larger, we try with next 5 digits of the hash.

so my question, is this sort of system predictable? given we don't know the seed, but only the extra 'something-1', 'something-2'.... Is having the first 100 or even 1000 generated numbers help knowing what comes next? or even knowing the range of what comes next?

Please if you think there is still missing information, don't submit an answer, and just put a comment, so I can update the question

  • $\begingroup$ Remember, converting bits into base 10 has a bias. $\endgroup$ – kelalaka Oct 9 '19 at 19:10
  • $\begingroup$ Is this about the parseInt method? $\endgroup$ – Mocas Oct 9 '19 at 19:22
  • $\begingroup$ Noting is done with first5; and result is used but not set. I guess they are the same. My coding style would be to aggregate the last four statements into one: var random = parseInt(hmaxSeed.update(extra).digest('hex').substring(0, 5), 16) % 10000 / 100; That gets rid of three single-use variables (four counting the misnamed result). Such variables can eat memory and increase the risk that secrets will leak. Oh wait, we are not a code review site. As pointed elsewhere, the outcome random is noticeably biased towards values in a lower fragment of the output range. $\endgroup$ – fgrieu Oct 10 '19 at 9:41

Generally we operate on bits and bytes, not hexadecimals. Hexadecimals are just a convenient way for humans to look at the value of the bytes. Furthermore, you seem to try and define your own KDF using HMAC. This is not likely a problem, but you do not use a well vetted scheme if you do so.

Presuming that the seed is secret and random, you have 32 bytes or 256 bits for the HMAC key. You are however not decoding them but using them as if they are a 512 bit key for HMAC configured with SHA-512. That's not as it should be - your 512 bit key has only 256 bits of security after all, but it is not a security issue due to the size of the key - presuming the values are (pseudo-)randomly chosen and kept secret of course.

Then you update with a seemingly unique value, extra-1. This is fine, but if synchronization is ever lost then you may start regenerating previously issues values, as the nonce may then repeat.

You then take the 5 hex digits of the value. That means that the maximum value is $16^5-1$ or $1,048,575$. You'll then mod with $10,000$ which however means that you introduce bias: if the value is above $1,040,000$ then it will never be between $1,048,575$ and $1,049,999$ after all. That will only happen less than 1% of the time, but it still introduces bias.

The division with $100$ afterwards doesn't make any sense at all, unless if it is just to retrieve a monetary value with two digits after the dot. If you want to have an integer value between $0$ and $99$ then you can better just use $% 100$, because that will introduce less bias. You could even do this for the entire hash value seen as positive number if you use a big integer library. That will introduce only a minor amount of bias.

So yeah, the returned value is kind of random if you don't know the seed, but it contains bias and some design decisions are odd. It is certainly possible to improve on the scheme.

| improve this answer | |
  • $\begingroup$ Thank you for the answer. Yes, the random number needs to be between 0 and 99.99, including two decimal points. What I would like to know is whether I can predict the next number in a sequence without knowing the seed, is this possible? Or even the range $\endgroup$ – Mocas Oct 9 '19 at 21:44
  • $\begingroup$ No for the first question, although self made, this is essentially a KDF. However, I am not sure what you mean with "or even the range". An adversary can of course guess the min and max with growing certainty. $\endgroup$ – Maarten Bodewes Oct 9 '19 at 22:32
  • $\begingroup$ By the range I mean predicting that the next number will be less than 30 for example, or higher than 80. If that's the case, how can this be achieved? The probability of the next number to be above 30 is 70%, is there a way of predicting when is it likely to be higher? $\endgroup$ – Mocas Oct 10 '19 at 7:08
  • $\begingroup$ No, but since there is bias towards the lower numbers, the chance that it is lower than 50 is just over 50%, and of course a full 100 may never be reached if everything gets rounded down... I think. $\endgroup$ – Maarten Bodewes Oct 10 '19 at 10:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.