Random number seeded with custom time - javascript

I am trying to create a random number as below using javascript
function valid(form) {
var input = 0;
var input = document.getElementById('custom1').value;
var final_input = input.charAt(0);
var number = 1000000000 - Math.floor(Math.random() * 1000000000);
final_input = final_input + number;
document.getElementById('custom4').value = final_input;
}
The idea is that it will get the value from "custom1" (which is one of the input fields) and then will get the first character. After that it will add next 9 random digits and puts the final value to custom4 (another input field) of the form. The javascript is working fine so far. However, I will rather have the random digit numbers be seeded with current time. I think that will it will be really random. Is that possible?

The JavaScript standard random API doesn't support explicit seeding (which is a shame). Here's the spec :
Returns a Number value with positive sign, greater than or equal to 0
but less than 1, chosen randomly or pseudo randomly with approximately
uniform distribution over that range, using an
implementation-dependent algorithm or strategy. This function takes no
arguments.
If you really need to seed your generator with a given number, you'll have to use a library like this one (not tested by me).
But the JavaScript random API is implicitly seeded, which ensures you'll have different results. There's no ECMAScript specification regarding how it's seeded but it's probable that all browsers use the time for the seeding. The MDN says
The random number generator is seeded from the current time, as in
Java.

I must correct myself. This is only correct for Mozilla (as far as i know): The JavaScript random API uses already the current time as a seed. No need to do it double (and it's not supported).
The specification doesn't mention a algorithm or strategies how the random number is generated and if and how it is seeded.

Thanks..
finally I have something like below
function valid(form) {
var input = 0;
var input = document.getElementById('custom1').value;
var final_input = input.charAt(0);
var number = new Date().valueOf(); /*1000000000 - Math.floor(Math.random() * 1000000000);*/
final_input = final_input + number;
document.getElementById('custom4').value = final_input;
}

Related

How to generate a GUID with a custom alphabet, that behaves similar to an MD5 hash (in JavaScript)?

I am wondering how to generate a GUID given an input string, such that the same input string results in the same GUID (sort of like an MD5 hash). The problem with MD5 hashes is they just guarantee low collision rate, rather than uniqueness. Instead I would like something like this:
guid('v1.0.0') == 1231231231123123123112312312311231231231
guid('v1.0.1') == 6154716581615471658161547165816154716581
guid('v1.0.2') == 1883939319188393931918839393191883939319
How would you go about implementing this sort of thing (ideally in JavaScript)? Is it even possible to do? I am not sure where to start. Things like the uuid module don't take a seed string, and they don't let you use a custom format/alphabet.
I am not looking for the canonical UUID format, but rather a GUID, ideally one made up of just integers.
What you would need is define a one-to-one mapping of text strings (such as "v1.0.0") onto 40 digit long strings (such as "123123..."). This is also known as a bijection, although in your case an injection (a simple one-to-one mapping from inputs to outputs, not necessarily onto) may be enough. As you note, hash functions don't necessarily ensure this mapping, but there are other possibilities, such as full-period linear congruential generators (if they take a seed that you can map one-to-one onto input string values), or other reversible functions.
However, if the set of possible input strings is larger than the set of possible output strings, then you can't map all input strings one-to-one with all output strings (without creating duplicates), due to the pigeonhole principle.
For example, you can't generally map all 120-character strings one-to-one with all 40-digit strings unless you restrict the format of the 120-character strings in some way. However, your problem of creating 40-digit output strings can be solved if you can accept limiting input strings to no more than 1040 values (about 132 bits), or if you can otherwise exploit redundancy in the input strings so that they are guaranteed to compress losslessly to 40 decimal digits (about 132 bits) or less, which may or may not be possible. See also this question.
The algorithm involves two steps:
First, transform the string to a BigInt by building up the string's charCodeAt() values similarly to the stringToInt method given in another answer. Throw an error if any charCodeAt() is 0x80 or greater, or if the resulting BigInt is equal to or greater than BigInt(alphabet_length)**BigInt(output_length).
Then, transform the integer to another string by taking the mod of the BigInt and the output alphabet's size and replacing each remainder with the corresponding character in the output alphabet, until the BigInt reaches 0.
One approach would be to use the method from that answer:
/*
* uuid-timestamp (emitter)
* UUID v4 based on timestamp
*
* Created by tarkh
* tarkh.com (C) 2020
* https://stackoverflow.com/a/63344366/1261825
*/
const uuidEmit = () => {
// Get now time
const n = Date.now();
// Generate random
const r = Math.random(); // <- swap this
// Stringify now time and generate additional random number
const s = String(n) + String(~~(r*9e4)+1e4);
// Form UUID and return it
return `${s.slice(0,8)}-${s.slice(8,12)}-4${s.slice(12,15)}-${[8,9,'a','b'][~~(r*3)]}${s.slice(15,18)}-${s.slice(s.length-12)}`;
};
// Generate 5 UUIDs
console.log(`${uuidEmit()}
${uuidEmit()}
${uuidEmit()}
${uuidEmit()}
${uuidEmit()}`);
And simply swap out the Math.random() call to a different random function which can take your seed value. (There are numerous algorithms out there for creating a seedable random method, so I won't try prescribing a particular one).
Most random seeds expect numeric, so you could convert a seed string to an integer by just adding up the character values (multiplying each by 10^position so you'll always get a unique number):
const stringToInt = str =>
Array.prototype.slice.call(str).reduce((result, char, index) => result += char.charCodeAt(0) * (10**(str.length - index)), 0);
console.log(stringToInt("v1.0.0"));
console.log(stringToInt("v1.0.1"));
console.log(stringToInt("v1.0.2"));
If you want to generate the same extract string every time, you can take a similar approach to tarkh's uuidEmit() method but get rid of the bits that change:
const strToInt = str =>
Array.prototype.slice.call(str).reduce((result, char, index) => result += char.charCodeAt(0) * (10**(str.length - index)), 0);
const strToId = (str, len = 40) => {
// Generate random
const r = strToInt(str);
// Multiply the number by some things to get it to the right number of digits
const rLen = `${r}`.length; // length of r as a string
// If you want to avoid any chance of collision, you can't provide too long of a string
// If a small chance of collision is okay, you can instead just truncate the string to
// your desired length
if (rLen > len) throw new Error('String too long');
// our string length is n * (r+m) + e = len, so we'll do some math to get n and m
const mMax = 9; // maximum for the exponent, too much longer and it might be represented as an exponent. If you discover "e" showing up in your string, lower this value
let m = Math.floor(Math.min(mMax, len / rLen)); // exponent
let n = Math.floor(len / (m + rLen)); // number of times we repeat r and m
let e = len - (n * (rLen + m)); // extra to pad us to the right length
return (new Array(n)).fill(0).map((_, i) => String(r * (i * 10**m))).join('')
+ String(10**e);
};
console.log(strToId("v1.0.0"));
console.log(strToId("v1.0.1"));
console.log(strToId("v1.0.2"));
console.log(strToId("v1.0.0") === strToId("v1.0.0")); // check they are the same
console.log(strToId("v1.0.0") === strToId("v1.0.1")); // check they are different
Note, this will only work with smaller strings, (probably about 10 characters top) but it should be able to avoid all collisions. You could tweak it to handle larger strings (remove the multiplying bit from stringToInt) but then you risk collisions.
I suggest using MD5...
Following the classic birthday problem, all things being equal, the odds of 2 people sharing a birthday out of a group of 23 people is ( see https://en.wikipedia.org/wiki/Birthday_problem )...
For estimating MD5 collisions, I'm going to simplify the birthday problem formula, erring in the favor of predicting a higher chance of a collision...
Note though that whereas in the birthday problem, a collision is a positive result, in the MD5 problem, a collision is a negative result, and therefore providing higher than expected collision odds provides a conservative estimate of the chance of a MD5 collision. Plus this higher predicted chance can in some way be considered a fudge factor for any uneven distribution in the MD5 output, although I do not believe there is anyway to quantify this without a God computer...
An MD5 hash is 16 bytes long, resulting in a range of 256^16 possible values. Assuming that the MD5 algorithm is generally uniform in its results, lets suppose we create one quadrillion (ie, a million billion or 10^15) unique strings to run through the hash algorithm. Then using the modified formula (to ease the collision calculations and to add a conservative fudge factor), the odds of a collision are...
So, after 10^15 or one quadrillion unique input strings, the estimated odds of a hash collision are on par with the odds of winning the Powerball or the Mega Millions Jackpot (which are on order of 1 in ~300,000,000 per https://www.engineeringbigdata.com/odds-winning-powerball-grand-prize-r/ ).
Note too that 256^16 is 340282366920938463463374607431768211456, which is 39 digits, falling within the desired range of 40 digits.
So, suggest using the MD5 hash ( converting to BigInt ), and if you do run into a collision, I will be more than glad to spot you a lottery ticket, just to have a chance to tap into your luck and split the proceeds...
( Note: I used https://keisan.casio.com/calculator for the calculations. )
While UUID v4 is just used for random ID generation, UUID v5 is more like a hash for a given input string and namespace. It's perfect for what you describe.
As you already mentioned, You can use this npm package:
npm install uuid
And it's pretty easy to use.
import {v5 as uuidv5} from 'uuid';
// use a UUIDV4 as a unique namespace for your application.
// you can generate one here: https://www.uuidgenerator.net/version4
const UUIDV5_NAMESPACE = '...';
// Finally, provide the input and namespace to get your unique id.
const uniqueId = uuidv5(input, namespace);

list fo random numbers separated by commas

Okay so I am making a mario inspired game with randomly generating terrain, It is all working fine however the array of random numbers that randomises the terrain must be the same each time so that the user can enter a seed which is then merged with the larger list to provide a set of random numbers based off of the seed however I cannot think of any way to make this array the same each time without writing it out, and even then making an array of 1000 numbers will be timely. Can anyone suggest a fast way (number generators online dont format it in one single line of numbers separated by numbers so cannot use them)
or could someone provide me with a list that is on a single line separated by numbers that i can easily copy and paste into an array thanks! :)
The following code in Javascript will generate 1000 random numbers separated by commas.
var string = "";
var numberOfRandomNumbers = 1000;
for (var i = 0; i < numberOfRandomNumbers; i++) {
var randomNumber = Math.floor((Math.random() * 1000) + 1); //Will generate random number between 1 and 1000
string += randomNumber+",";
}
console.log(string.substring(0, string.length - 1)); //Print string to console and remove last comma

Javascript: "+" sign concatenates instead of giving sum of variables

I am currently creating a site that will help me quickly answer physics questions.
As it happens, the code didn't run as expected, here is the code
if (option == "dv") {
var Vinitial = prompt("What is the Velocity Initial?")
var acceleration = prompt("what is the acceleration?")
var time = prompt("what is the time?")
Vfinal = Vinitial + acceleration * time
displayV.innerHTML = "v= vf= " + Vfinal + "ms" + sup1.sup();
}
Now, let's say Vinitial was 9, acceleration was 2, and time was 3.
When the code runs, instead of getting 15 for "Vfinal", I get 96.
I figured out that it multiplies acceleration and time fine, and then just concatenates the 9 at the beginning, with 6 (the product of 2 * 3).
I have fixed it for now by using
Vfinal = acceleration * time - (-Vinitial)
which avoids using the "+" sign, but I don't want to have to keep doing this. How do I fix it?
you are dealing with strings here, and math operations on strings will mess up. Remember when ever you are doing math operations you have to convert the data into actual numbers and then perform the math.
Use parseInt() more Details here
Your code should change to
Vfinal = parseInt(Vinitial,10) + parseInt(acceleration,10) * parseInt(time,10);
Edit 1: If the numbers are decimal values then use parseFloat() instead
So the code would be
Vfinal = parseFloat(Vinitial) + parseFloat(acceleration) * parseFloat(time);
Object-Oriented JavaScript - Second Edition: As you already know, when you use the plus sign with two numbers, this
is the arithmetic addition operation. However, if you use the plus
sign with strings, this is a string concatenation operation, and it
returns the two strings glued together:
var s1 = "web";
var s2 = "site";
s1 + s2; // website
The dual purpose of the + operator is a source of errors. Therefore,
if you intend to concatenate strings, it's always best to make sure
that all of the operands are strings. The same applies for addition;
if you intend to add numbers, make sure the operands are numbers.
You can use "+" operator with prompt() to convert returned values from string to int
var Vinitial = +prompt("What is the Velocity Initial?");
var acceleration = +prompt("what is the acceleration?");
var time = +prompt("what is the time?");
Explanation:
var a = prompt('Enter a digit');
typeof a; // "string"
typeof +a; // "number"
If you will enter non-digit data +a gives you NaN. typeof NaN is "number" too :)
You will get the same result with parseInt():
var Vinitial = parseInt(prompt("What is the Velocity Initial?"), 10);
var acceleration = parseInt(prompt("what is the acceleration?"), 10);
var time = parseInt(prompt("what is the time?"), 10);
developer.mozilla.org: parseInt(string, radix);
string: The value to parse.
radix: An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the above mentioned string.
Specify 10 for the decimal numeral system commonly used by humans.
Always specify this parameter to eliminate reader confusion and to
guarantee predictable behavior. Different implementations produce
different results when a radix is not specified, usually defaulting
the value to 10.
Epilogue:
Object-Oriented JavaScript - Second Edition: The safest thing to do is to always specify the radix. If you omit the radix, your code
will probably still work in 99 percent of cases (because most often
you parse decimals), but every once in a while it might cause you a
bit of hair loss while debugging some edge cases. For example, imagine
you have a form field that accepts calendar days or months and the
user types 06 or 08.
Epilogue II:
ECMAScript 5 removes the octal literal values and avoids the confusion
with parseInt() and unspecified radix.
The Problem is, Your value has been took it in a form of string .. so convert your value into Int using parseInt(accelaration).. then it will work ..
Vfinal = parseInt(Vinitial) + parseInt(acceleration) * parseInt(time)
//use ParseInt
var a=10,b=10;
var sum=parseInt(a+b);
ex:
parseInt(Vinitial + acceleration) * time

Predict the Seed of Javascript's Math.random

Okay, so I'm doing some research on how random numbers are generated with the Math.random method. So far I learned that it starts with a "random" seed, and that seed is plugged into some complex equation to create a random number. If the seed is always the same, will the outcome always be the same?
I heard that the seeds for Math.random are generated through the current time, is that correct? They must use the current time all the way down to the mili-seconds or something, because if you didn't you would get the same outcome.
What exactly is the seed? Is it the time such as "10:45" or the time AND date such as "10:45 11/8/12" or some combination?
How can I find the seed, so I can predict the output?
I want to be able to plug this:
alert(Math.floor((Math.random()*10)+1));
into my url bar, and be able to predict the result. Is that possible?
I looked through the Rhino source code to find out which pseudo-random function they use. Apparently they fall back to the Math.random function defined in the Java standard library.
The documentation for Math.random says:
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
When this method is first called, it creates a single new pseudorandom-number generator, exactly as if by the expression
new java.util.Random
This new pseudorandom-number generator is used thereafter for all calls to this method and is used nowhere else.
This method is properly synchronized to allow correct use by more than one thread. However, if many threads need to generate pseudorandom numbers at a great rate, it may reduce contention for each thread to have its own pseudorandom-number generator.
So I checked the documentation for java.util.Random and found this (for the default constructor):
Creates a new random number generator. Its seed is initialized to a value based on the current time:
public Random() { this(System.currentTimeMillis()); }
Two Random objects created within the same millisecond will have the same sequence of random numbers.
So now we know for sure that the seed is the current time in milliseconds. Also, the documentation for the second constructor says:
Creates a new random number generator using a single long seed:
public Random(long seed) { setSeed(seed); }
Used by method next to hold the state of the pseudorandom number generator.
The documentation for the setSeed method says:
Sets the seed of this random number generator using a single long seed. The general contract of setSeed is that it alters the state of this random number generator object so as to be in exactly the same state as if it had just been created with the argument seed as a seed. The method setSeed is implemented by class Random as follows:
synchronized public void setSeed(long seed) {
this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
haveNextNextGaussian = false;
}
The implementation of setSeed by class Random happens to use only 48 bits of the given seed. In general, however, an overriding method may use all 64 bits of the long argument as a seed value. Note: Although the seed value is an AtomicLong, this method must still be synchronized to ensure correct semantics of haveNextNextGaussian.
The actual method used to generate the random number is nextDouble:
Returns the next pseudorandom, uniformly distributed double value between 0.0 and 1.0 from this random number generator's sequence.
The implementation of the nextDouble function is as follows:
public double nextDouble() {
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
}
Clearly it depends on the next function:
Generates the next pseudorandom number. Subclass should override this, as this is used by all other methods.
The implementation of the next function is as follows:
synchronized protected int next(int bits) {
seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int)(seed >>> (48 - bits));
}
That's the pseudo-random function you are looking for. As it's said in the documentation:
This is a linear congruential pseudorandom number generator, as defined by D. H. Lehmer and described by Donald E. Knuth in The Art of Computer Programming, Volume 2: Seminumerical Algorithms, section 3.2.1.
Note however that this is only the random number generator used by Rhino. Other implementations like Spidermonkey and V8 may have their own pseudo-random number generators.
it's likely that there's more to the seed than the millisecond count, because you can call Math.random() many times in the same millisecond and it will return a different value each time.
for (var i = 0; i < 3; i++) {
console.log(Math.random(), (new Date()).getTime());
};
My output:
0.0617244818713516 1352433709108
0.8024995378218591 1352433709108
0.2409922298975289 1352433709108
If I were implementing it I might make the initial seed based on a millisecond count, and then add 1 each time it's called, so that you wouldn't get the same seed value twice.
Here's a 100% accurate way of predicting the output from Math.random():
Math.random = function () { return .5; };
Now Math.random() will always return .5.
The seed is a numeric value, so my guess is that it would be what you get if you call Date.now() (or new Date().getTime() for older browsers).
However, I'm not sure when that seed is taken, or if the seed is isolated to the current page or common to the entire browser process. Predicting random numbers is supposed to be very hard or impossible, that's the whole point of them being random.
No, you cannot predict the seed, but you can preemtively generate enough numbers in order to accurately brute force a match.
Anyhow, start of by reading the wiki page on RNG's - http://en.wikipedia.org/wiki/Random_number_generation, the look at the practical implementations of PRNG's.

How to generate random SHA1 hash to use as ID in node.js?

I am using this line to generate a sha1 id for node.js:
crypto.createHash('sha1').digest('hex');
The problem is that it's returning the same id every time.
Is it possible to have it generate a random id each time so I can use it as a database document id?
243,583,606,221,817,150,598,111,409x more entropy
I'd recommend using crypto.randomBytes. It's not sha1, but for id purposes, it's quicker, and just as "random".
var id = crypto.randomBytes(20).toString('hex');
//=> f26d60305dae929ef8640a75e70dd78ab809cfe9
The resulting string will be twice as long as the random bytes you generate; each byte encoded to hex is 2 characters. 20 bytes will be 40 characters of hex.
Using 20 bytes, we have 256^20 or 1,461,501,637,330,902,918,203,684,832,716,283,019,655,932,542,976 unique output values. This is identical to SHA1's 160-bit (20-byte) possible outputs.
Knowing this, it's not really meaningful for us to shasum our random bytes. It's like rolling a die twice but only accepting the second roll; no matter what, you have 6 possible outcomes each roll, so the first roll is sufficient.
Why is this better?
To understand why this is better, we first have to understand how hashing functions work. Hashing functions (including SHA1) will always generate the same output if the same input is given.
Say we want to generate IDs but our random input is generated by a coin toss. We have "heads" or "tails"
% echo -n "heads" | shasum
c25dda249cdece9d908cc33adcd16aa05e20290f -
% echo -n "tails" | shasum
71ac9eed6a76a285ae035fe84a251d56ae9485a4 -
If "heads" comes up again, the SHA1 output will be the same as it was the first time
% echo -n "heads" | shasum
c25dda249cdece9d908cc33adcd16aa05e20290f -
Ok, so a coin toss is not a great random ID generator because we only have 2 possible outputs.
If we use a standard 6-sided die, we have 6 possible inputs. Guess how many possible SHA1 outputs? 6!
input => (sha1) => output
1 => 356a192b7913b04c54574d18c28d46e6395428ab
2 => da4b9237bacccdf19c0760cab7aec4a8359010b0
3 => 77de68daecd823babbb58edb1c8e14d7106e83bb
4 => 1b6453892473a467d07372d45eb05abc2031647a
5 => ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
6 => c1dfd96eea8cc2b62785275bca38ac261256e278
It's easy to delude ourselves by thinking just because the output of our function looks very random, that it is very random.
We both agree that a coin toss or a 6-sided die would make a bad random id generator, because our possible SHA1 results (the value we use for the ID) are very few. But what if we use something that has a lot more outputs? Like a timestamp with milliseconds? Or JavaScript's Math.random? Or even a combination of those two?!
Let's compute just how many unique ids we would get ...
The uniqueness of a timestamp with milliseconds
When using (new Date()).valueOf().toString(), you're getting a 13-character number (e.g., 1375369309741). However, since this a sequentially updating number (once per millisecond), the outputs are almost always the same. Let's take a look
for (var i=0; i<10; i++) {
console.log((new Date()).valueOf().toString());
}
console.log("OMG so not random");
// 1375369431838
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431840
// 1375369431840
// OMG so not random
To be fair, for comparison purposes, in a given minute (a generous operation execution time), you will have 60*1000 or 60000 uniques.
The uniqueness of Math.random
Now, when using Math.random, because of the way JavaScript represents 64-bit floating point numbers, you'll get a number with length anywhere between 13 and 24 characters long. A longer result means more digits which means more entropy. First, we need to find out which is the most probable length.
The script below will determine which length is most probable. We do this by generating 1 million random numbers and incrementing a counter based on the .length of each number.
// get distribution
var counts = [], rand, len;
for (var i=0; i<1000000; i++) {
rand = Math.random();
len = String(rand).length;
if (counts[len] === undefined) counts[len] = 0;
counts[len] += 1;
}
// calculate % frequency
var freq = counts.map(function(n) { return n/1000000 *100 });
By dividing each counter by 1 million, we get the probability of the length of number returned from Math.random.
len frequency(%)
------------------
13 0.0004
14 0.0066
15 0.0654
16 0.6768
17 6.6703
18 61.133 <- highest probability
19 28.089 <- second highest probability
20 3.0287
21 0.2989
22 0.0262
23 0.0040
24 0.0004
So, even though it's not entirely true, let's be generous and say you get a 19-character-long random output; 0.1234567890123456789. The first characters will always be 0 and ., so really we're only getting 17 random characters. This leaves us with 10^17 +1 (for possible 0; see notes below) or 100,000,000,000,000,001 uniques.
So how many random inputs can we generate?
Ok, we calculated the number of results for a millisecond timestamp and Math.random
100,000,000,000,000,001 (Math.random)
* 60,000 (timestamp)
-----------------------------
6,000,000,000,000,000,060,000
That's a single 6,000,000,000,000,000,060,000-sided die. Or, to make this number more humanly digestible, this is roughly the same number as
input outputs
------------------------------------------------------------------------------
( 1×) 6,000,000,000,000,000,060,000-sided die 6,000,000,000,000,000,060,000
(28×) 6-sided die 6,140,942,214,464,815,497,21
(72×) 2-sided coins 4,722,366,482,869,645,213,696
Sounds pretty good, right ? Well, let's find out ...
SHA1 produces a 20-byte value, with a possible 256^20 outcomes. So we're really not using SHA1 to it's full potential. Well how much are we using?
node> 6000000000000000060000 / Math.pow(256,20) * 100
A millisecond timestamp and Math.random uses only 4.11e-27 percent of SHA1's 160-bit potential!
generator sha1 potential used
-----------------------------------------------------------------------------
crypto.randomBytes(20) 100%
Date() + Math.random() 0.00000000000000000000000000411%
6-sided die 0.000000000000000000000000000000000000000000000411%
A coin 0.000000000000000000000000000000000000000000000137%
Holy cats, man! Look at all those zeroes. So how much better is crypto.randomBytes(20)? 243,583,606,221,817,150,598,111,409 times better.
Notes about the +1 and frequency of zeroes
If you're wondering about the +1, it's possible for Math.random to return a 0 which means there's 1 more possible unique result we have to account for.
Based on the discussion that happened below, I was curious about the frequency a 0 would come up. Here's a little script, random_zero.js, I made to get some data
#!/usr/bin/env node
var count = 0;
while (Math.random() !== 0) count++;
console.log(count);
Then, I ran it in 4 threads (I have a 4-core processor), appending the output to a file
$ yes | xargs -n 1 -P 4 node random_zero.js >> zeroes.txt
So it turns out that a 0 is not that hard to get. After 100 values were recorded, the average was
1 in 3,164,854,823 randoms is a 0
Cool! More research would be required to know if that number is on-par with a uniform distribution of v8's Math.random implementation
Have a look here: How do I use node.js Crypto to create a HMAC-SHA1 hash?
I'd create a hash of the current timestamp + a random number to ensure hash uniqueness:
var current_date = (new Date()).valueOf().toString();
var random = Math.random().toString();
crypto.createHash('sha1').update(current_date + random).digest('hex');
Do it in the browser, too !
EDIT: this didn't really fit into the flow of my previous answer. I'm leaving it here as a second answer for people that might be looking to do this in the browser.
You can do this client side in modern browsers, if you'd like
// str byteToHex(uint8 byte)
// converts a single byte to a hex string
function byteToHex(byte) {
return ('0' + byte.toString(16)).slice(-2);
}
// str generateId(int len);
// len - must be an even number (default: 40)
function generateId(len = 40) {
var arr = new Uint8Array(len / 2);
window.crypto.getRandomValues(arr);
return Array.from(arr, byteToHex).join("");
}
console.log(generateId())
// "1e6ef8d5c851a3b5c5ad78f96dd086e4a77da800"
console.log(generateId(20))
// "d2180620d8f781178840"
Browser requirements
Browser Minimum Version
--------------------------
Chrome 11.0
Firefox 21.0
IE 11.0
Opera 15.0
Safari 5.1
If Want To Get Unique Identifiers, You should use UUID (Universally Unique Identifier) / GUID (Globally Unique Identifier).
A Hash is Supposed to be Deterministic & Unique & of Fixed Length For Input of any size. So no matter how many times you run the hash function, the output will be the same if you use the same input.
UUIDs Are Unique & Randomly Generated!
There Is A Package called 'uuid' you can install it via npm by
npm install uuid
& In your code import the module by
const { v4:uuidv4} = require('uuid');
// Call The Method uuidv4 or whatever you name it while importing & log it or store it or assign it. The method return a UUID in the form of a string.
console.log(uuidv4());
// Example Output : '59594fc8-6a35-4f50-a966-4d735d8402ea'
Here is the npm link (if you need it) :
https://www.npmjs.com/package/uuid
Using crypto is a good approach cause it's native and stable module,
but there are cases where you can use bcrypt if you want to create a really strong and secure hash. I use it for passwords it has a lot of techniques for hashing, creating salt and comparing passwords.
Technique 1 (generate a salt and hash on separate function calls)
const salt = bcrypt.genSaltSync(saltRounds);
const hash = bcrypt.hashSync(myPlaintextPassword, salt);
Technique 2 (auto-gen a salt and hash):
const hash = bcrypt.hashSync(myPlaintextPassword, saltRounds);
For more examples you can check here: https://www.npmjs.com/package/bcrypt

Categories

Resources