I need to create cryptographically secure pseudorandomness in JavaScript. However, when I googled for PRGs, all I found was very sketchy.
My idea is as follows (in pseudocode):
seed = "0x1a29fd..." // long number I always get passed (impossible to guess but used in a different context as well)
hashedAndSaltedSeed = sha256sum("seed: " + seed)
purpose = "..." // my current function's name (no spaces)
usageIndex = 1; // will increment this each time
randomness = myPrg(hashedAndSaltedSeed, purpose, usageIndex)
function myPrg(hashedAndSaltedSeed, purpose, usageIndex, numberOfBytes) {
if(numberOfBytes > 32) {
fail()
}
input = purpose + " " + usageIndex + " " + hashedAndSaltedSeed
return sha256sum(input).binary2hex().slice(0, 2*numberOfBytes).hex2binary()
}
I only need a small amount of randomness (at most 32 Byte at a time, very few times), so the speed difference won't matter. But is there anything else wrong with this approach?
The randomness I need doesn't need to be distributed perfectly randomly but it needs to be infeasible to guess the resulting randomness when only given purpose
and usageIndex
but not seed
nor hashedAndSaltedSeed
.
Edit: I'm sorry that I forgot to mention an important requirement. I'm sure it was in my question at some point as I wrote it but I seem to have deleted that part accidentally. I need to be able to reproduce the same randomness when given the same seed. That's why I can't just use something that gives me randomness but doesn't let me control the seed.
seed
is secret drawn uniformly at random from $2^{256}$ possibilities, that's fine, but your naming is a little confusing: what is the salt inhashedAndSaltedSeed
? This also, of course, begs the question of whereseed
comes from, but if your present goal is just to have a pseudorandom function family for which it is the caller's responsibility to choose a seed uniformly at random, then that's fine. $\endgroup$hashedAndSaltedSeed
around, no one can do anything with it that it's not intended for. It's not technically a salt because it's constant. Maybe I should find a better name. $\endgroup$purpose="hello world"
andusageIndex="foobar"
, I'll get the same key as if I pass inpurpose="hello"
andusageIndex="world foobar"
even though the inputs are distinct. $\endgroup$