1.3.0 • Public • Published


unpredictable number generation

npm install rndme - or - bower install rndme

Check out a live demo to see what the fuss is about.


Easily gather numbers or text from sound, movement, video, and more.

Cryptography needs un-predictable keys to ensure security. Recent revelations have cast doubt about window.crypto, and everyone knows Math.random() is useless. Existing methods of "entropy gathering" like mouse jiggling or typing are akward for users and hampered by mobile devices. With uniform access to a variety of sources, rndme offers you simple and felxible creation of un-predictable and uniformly-distributed data, if you're into that sort of thing.

Input Sources


Uses getUserMedia() to capture numbers from a microphone. This is the fastest physical source of numbers at over 900 chars per ms sustained. The raw samples are not only shuffled, they are cropped of the most and least signifigant digits, so there's no telling what was briefly "recorded". Use medium volume music or static for a more even distribution of output.


Uses getUserMedia() to capture numbers from a camera. Thousands of pixels are rolled into each character of output. Move the camera around and have some color contrast in the video for maximum entropy. Video is the 2nd fastest source of numbers after sound at around 3 - 80 chars per ms, depending on brightness and movement. Even a dark camera will work, but one shooting the floor or horizon will produce data much faster.


Motion uses the device Motion API to turn physical movements into numbers. It shuffles the samples and chops off bits to ensure privacy in the face of low-resolution sensors and motionless capture. Best entropy is obtained with lots of movement starting and stopping, like gently shaking while tilting. Motion's performance varies per device but ranges from about 2.5 - 5 chars per ms.


Time uses a high-resolution clock and a random workload to gather numbers. Since it uses a clock and rolls many workload timings into each output sample, it's rather slow compared to the others at around 0.60 chars per ms. Time has one main advantage: it works on desktop and mobile alike and doesn't need user permissions. It's great for shorter chunks of data like salts, symmetric encryption keys, and entropy for other number generators.


Crypto uses crypto.getRandomValues and a high-resolution clock derivative to gather numbers. This method is sync under-the-hood and is directly callable. OS-provided numbers are muliplied by a number derived from the date and a high-resolution performance timing API, then cropped in the middle to deliver un-compromised randomness. The crypto source's exact performance rate depends on CPU speed and OS-provided entropy, but expect 100 - 500 chars per ms.


Combo mixes output from one or more sources, like sound and motion, to ensure randomness in the face of broken sensors, or just for plain good measure. It's an easy way to address concerns about one source or the other: use both! All data is gathered at the same time, so you only have to wait the time of the slowest source used. rndme.combo takes a special first argument, a list of source names, but the other parameters are the same except progress, which is not available on combo.

Output Formats

Format Seperator Range Description
hex "" 0-F hex-encoded byte values
bytes "," 0-255 integers that fit into 1 byte
bin "" \u0-\u255 binary string of bytes
int "" 0-9 continuous digits
base64 "" \--z URL-safe chars
base92 "" \t-~ JSON-safe chars
float "," 0-1 16 digit floats
raw "," 0-1 same as int, but no limit


Static methods on the rndme variable can be used async with callbacks or promises.

//   source ( format  limit  callback  progess ) -or- .then(callback)
rndme.sound("bytes", 12345, function(s){alert(s)});
rndme.motion("hex", 1024,function(s){alert(s)}, console.info.bind(console));
rndme.time("float", 256,function(s){alert(s)}, console.info.bind(console));
rndme.video("base92", 1024).then(alert).catch(confirm);
rndme.combo(["sound", "video", "motion"], "hex", 2000).then(alert); // combine 3 sources
rndme.combo("video", "hex", 2000, alert); // combine one source (alt syntax + cb)

Static Utilities


._stamp() - returns 10 random digits, sync, based on the current time. Using Date()s and high-resolution timingings with a chunk of slower code internally, this method should produce different output each time it's called:

// == ["1621049878", "7138172444", "5275617627", "1540339147", "2792212006"]


._spin(arrToShuffle, optNumSwaps) - re-arranges the elements in an array into an unpredictable order bu swapping values. The default is as many swaps as elements, but a 2nd argument can specify a custom number of swaps if desired. Uses Math.random(), so it should not be a primary source of sectrets, but it can help re-arrange secrets to provide a better distribution.

// ~==[5, 2, 8, 9, 6, 3, 1, 7, 4] // note complete re-distribution of element order


._munge - An [].sort() callback that contrary to popular belief, does NOT randomize an array. It does slightly re-arrange the elements, and it does so quickly. It's used by rndme to prevent repeated output in very low-entroy situations like a user having a broken camera and using the video input by altering the look up table of some output builders prior to each execution.

// ~== [2, 1, 8, 3, 7, 4, 5, 6, 9]; // note different order, but not complete re-distribution


._combine(inp1, inp2) - Given two strings or arrays of digits, add them together as numbers and keep the least significant digits. This is used internaly by the combo source, but is exposed for mixing other data/entropy as needed.

// == "802"  (1+7=8, 2+8=0, 3+9=2)

Package Sidebar


npm i rndme

Weekly Downloads






Last publish


  • rndme