3 ms·
If you need good quality random IDs cheaply, you can do the following: 1. Generate a pool of 2048 bytes or so of entropy at startup using window.crypto.getRand
by jorangreef 11y ago
If you need good quality random IDs cheaply, you can do the following:
1. Generate a pool of 2048 bytes or so of entropy at startup using window.crypto.getRandomValues or crypto.pseudoRandomBytes. To this, append Date.now() and Math.random().toString() just in case your crypto method fails badly. Then call SHA256 on this to get your starting entropy distilled into 32 bytes. If some of the 2048 bytes of entropy are not high quality, it won't matter as much since you compress it into 32 bytes (i.e. it's worse if you just ask for 32 bytes from getRandomValues).
2. Initialize a counter to 0.
3. Each time you need an ID, increment the counter (handle wrap-around if necessary), and take a SHA256 hash of (counter, 32 bytes entropy hash obtained in 1. above, Date.now(), Math.random().toString()). Then truncate and encode this using whatever character set as needed.
This way you don't drain out your cryptographic entropy pool every time you generate an ID. You also don't leak any details as to your system time, startup time, or your current position in Math.random() (which would allow someone to predict the next Math.random() result) since the final ID is hashed.
- tptacek 11y agoSince what you're proposing is pretty close to just running SHA2 in counter mode, you could simplify this by generating 128 bits of random data, using it as an AES key, and just using your crypto library's AES-CTR function to generate a keystream. If you need a predictable stream of uncorrelated bits, this has the benefits of being simple and trivially seedable.
- jorangreef 11y agoThanks, that's an elegant solution. In case the entropy pool is drained, one would still want to get more than 128 bits from urandom and then hash this with SHA2 to get the 128 bit key, right? I had in mind something portable to the browser without requiring AES there, but will try it out on the server.
- tptacek 11y agoIn a practical sense, there is no such thing as draining an entropy pool. The period for AES-CTR is 2^128. The primary reason CSPRNGs rekey themselves periodically is for forward security, so that if your machine gets hacked, an attacker can't snarf the RNG state and predict all future numbers the machine generates.
- Tomte 11y agoForward security is obviously a desirable design feature in a CSPRNG (as a building block that's evaluated and reviewed on its own merits), but I can't help but feel that it's often distracting people from a whole system view. If an attacker has access to your computer on a level where he can inspect the CSPRNG's state, you've probably lost completely and no reseeding will help you.
- tptacek 11y agoI agree, of course.
- tedunangst 11y agoYou also want to stop backtracking. If I can grab the key and counter for your AES stream, I can roll back and generate all the numbers you generated last week too.