Related
I'm using this BigInteger.js for some calculations:
let myBigInt = bigInt(20).pow(200) // gets 160693804425899027554196209234116260252220299378279283530137600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
I'd like to apply the logarithm to the big integer but in the docs I could not find any matching function. How can I implement a log(baseN, valueX) function for the BigInteger.js library?
Note: let myLogarithm = myBigInt.log(baseN) is not a valid implementation.
Note: After a lot of try&error I did found a working solution my own and I will post it here because I'm pretty sure there are a few more people then me that also gots faced with the same issue right there. So I hope, I could help :)
Have a look at wikipedia, as I did because theres a very nice article about baseConversion.
Below you can find a function for Math.log(base, value) that is able to calculate the log(base) from a value.
Math.log = (function() {
var log = Math.log;
return function(base, n) {
return log(n)/(base ? log(base) : 1);
};
})();
To calculate the logarithmToBaseN for bigInt-values just use this line of code:
let logarithmToBaseN = (myBigInt.toString().length * Math.log(baseN, 10) + Math.log(baseN, parseFloat("0." + myBigInt))) - 1);
Edit: This soltuion is a tiny workaround bacause parseFloat("0." + myBigInt) converts a big value like 100000 to a really small one like 0.100000,... what causes that it will be in integer precision.
According to #Jonas W's comment: The solution is very accurate for lower bases like (5, 10, ...) combined with low values like 10, 1000, 100000 - but for really big values like bigInt(20).pow(200) is it not.
Note: Using parseFloat (IEEE 754 double precision floating-point) means, you have a maximum of 52 bits of precision, which is a bit more than 15 decimal places. After that - the accuracy will be killed.
Note: For really big values bigInt(20).pow(200) combined with really big Bases like 100*(and more) it seems to be pretty accurate again.
Greetings, jonas.
How do I generate cryptographically secure random numbers in javascript?
There's been discussion at WHATWG on adding this to the window.crypto object. You can read the discussion and check out the proposed API and webkit bug (22049).
Just tested the following code in Chrome to get a random byte:
(function(){
var buf = new Uint8Array(1);
window.crypto.getRandomValues(buf);
alert(buf[0]);
})();
In order, I think your best bets are:
window.crypto.getRandomValues or window.msCrypto.getRandomValues
The sjcl library's randomWords function (http://crypto.stanford.edu/sjcl/)
The isaac library's random number generator (which is seeded by Math.random, so not really cryptographically secure) (https://github.com/rubycon/isaac.js)
window.crypto.getRandomValues has been implemented in Chrome for a while now, and relatively recently in Firefox as well. Unfortunately, Internet Explorer 10 and before do not implement the function. IE 11 has window.msCrypto, which accomplishes the same thing. sjcl has a great random number generator seeded from mouse movements, but there's always a chance that either the mouse won't have moved sufficiently to seed the generator, or that the user is on a mobile device where there is no mouse movement whatsoever. Thus, I recommend having a fallback case where you can still get a non-secure random number if there is no choice. Here's how I've handled this:
function GetRandomWords (wordCount) {
var randomWords;
// First we're going to try to use a built-in CSPRNG
if (window.crypto && window.crypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.crypto.getRandomValues(randomWords);
}
// Because of course IE calls it msCrypto instead of being standard
else if (window.msCrypto && window.msCrypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.msCrypto.getRandomValues(randomWords);
}
// So, no built-in functionality - bummer. If the user has wiggled the mouse enough,
// sjcl might help us out here
else if (sjcl.random.isReady()) {
randomWords = sjcl.random.randomWords(wordCount);
}
// Last resort - we'll use isaac.js to get a random number. It's seeded from Math.random(),
// so this isn't ideal, but it'll still greatly increase the space of guesses a hacker would
// have to make to crack the password.
else {
randomWords = [];
for (var i = 0; i < wordCount; i++) {
randomWords.push(isaac.rand());
}
}
return randomWords;
};
You'll need to include sjcl.js and isaac.js for that implementation, and be sure to start the sjcl entropy collector as soon as your page is loaded:
sjcl.random.startCollectors();
sjcl is dual-licensed BSD and GPL, while isaac.js is MIT, so it's perfectly safe to use either of those in any project. As mentioned in another answer, clipperz is another option, however for whatever bizarre reason, it is licensed under the AGPL. I have yet to see anyone who seems to understand what implications that has for a JavaScript library, but I'd universally avoid it.
One way to improve the code I've posted might be to store the state of the isaac random number generator in localStorage, so it isn't reseeded every time the page is loaded. Isaac will generate a random sequence, but for cryptography purposes, the seed is all-important. Seeding with Math.random is bad, but at least a little less bad if it isn't necessarily on every page load.
You can for instance use mouse movement as seed for random numbers, read out time and mouse position whenever the onmousemove event happens, feed that data to a whitening function and you will have some first class random at hand. Though do make sure that user has moved the mouse sufficiently before you use the data.
Edit: I have myself played a bit with the concept by making a password generator, I wouldn't guarantee that my whitening function is flawless, but being constantly reseeded I'm pretty sure that it's plenty for the job: ebusiness.hopto.org/generator.htm
Edit2: It now sort of works with smartphones, but only by disabling touch functionality while the entropy is gathered. Android won't work properly any other way.
Use window.crypto.getRandomValues, like this:
var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);
This is supported in all modern browsers and uses the operating system's random generator (e.g. /dev/urandom). If you need IE11 compatibility, you have to use their prefixed implementation viavar crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..) though.
Note that the window.crypto API can also generate keys outright, which may be the better option.
Crypto-strong
to get cryptographic strong number from range [0, 1) (similar to Math.random()) use crypto:
let random = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;
console.log( random() );
You might want to try
http://sourceforge.net/projects/clipperzlib/
It has an implementation of Fortuna which is a cryptographically secure random number generator. (Take a look at src/js/Clipperz/Crypto/PRNG.js). It appears to use the mouse as a source of randomness as well.
First of all, you need a source of entropy. For example, movement of the mouse, password, or any other. But all of these sources are very far from random, and guarantee you 20 bits of entropy, rarely more. The next step that you need to take is to use the mechanism like "Password-Based KDF" it will make computationally difficult to distinguish data from random.
Many years ago, you had to implement your own random number generator and seed it with entropy collected by mouse movement and timing information. This was the Phlogiston Era of JavaScript cryptography. These days we have window.crypto to work with.
If you need a random integer, random-number-csprng is a great choice. It securely generates a series of random bytes and then converts it into an unbiased random integer.
const randomInt = require("random-number-csprng");
(async function() {
let random = randomInt(10, 30);
console.log(`Your random number: ${random}`);
})();
If you need a random floating point number, you'll need to do a little more work. Generally, though, secure randomness is an integer problem, not a floating point problem.
I know i'm late to the party, but if you don't want to deal with the math of getting a cryptographically secure random value, i recommend using rando.js. it's a super small 2kb library that'll give you a decimal, pick something from an array, or whatever else you want- all cryptographically secure.
It's on npm too.
Here's a sample I copied from the GitHub, but it does more than this if you want to go there and read about it more.
console.log(rando()); //a floating-point number between 0 and 1 (could be exactly 0, but never exactly 1)
console.log(rando(5)); //an integer between 0 and 5 (could be 0 or 5)
console.log(rando(5, 10)); //a random integer between 5 and 10 (could be 5 or 10)
console.log(rando(5, "float")); //a floating-point number between 0 and 5 (could be exactly 0, but never exactly 5)
console.log(rando(5, 10, "float")); //a floating-point number between 5 and 10 (could be exactly 5, but never exactly 10)
console.log(rando(true, false)); //either true or false
console.log(rando(["a", "b"])); //{index:..., value:...} object representing a value of the provided array OR false if array is empty
console.log(rando({a: 1, b: 2})); //{key:..., value:...} object representing a property of the provided object OR false if object has no properties
console.log(rando("Gee willikers!")); //a character from the provided string OR false if the string is empty. Reoccurring characters will naturally form a more likely return value
console.log(rando(null)); //ANY invalid arguments return false
<script src="https://randojs.com/2.0.0.js"></script>
If you need large amounts, here's what I would do:
// Max value of random number length
const randLen = 16384
var randomId = randLen
var randomArray = new Uint32Array(randLen)
function random32() {
if (randomId === randLen) {
randomId = 0
return crypto.getRandomValues(randomArray)[randomId++] * 2.3283064365386963e-10
}
return randomArray[randomId++] * 2.3283064365386963e-10
}
function random64() {
if (randomId === randLen || randomId === randLen - 1) {
randomId = 0
crypto.getRandomValues(randomArray)
}
return randomArray[randomId++] * 2.3283064365386963e-10 + randomArray[randomId++] * 5.421010862427522e-20
}
console.log(random32())
console.log(random64())
I know that exponentiation is O(log n) or worse for most cases, but I'm getting lost trying to understand of how numbers are represented themselves. Take JavaScript, for example, because it has several native number formats:
100000 === 1E5 && 100000 === 0303240
>>> true
Internally, don't they all end up being stored and manipulated as binary values stored in memory? If so, is the machine able to store the decimal and scientific-notation representations as fast as it does the octal?
And thus, would you expect +("1E" + n) to be faster than Math.pow(10, n)?
Mostly this question is about how 1E(n) works, but in trying to think about the answer myself I became more curious about how the number is parsed and stored in the first place. I would appreciate any explanation you can offer.
I don't think string manipulation could be faster, because at least concatenation creates a new object (memory allocation, more job for GC), Math.pow usually comes to single machine instruction.
Moreover, some modern JS VMs do hotspot optimisation, producing machine code from javascript. There is chance of it for Math.pow, but nearly impossible for the string magic.
If you 100% sure that Math.pow works slow in your application (I just cannot believe in it), you could use array lookup, it should work fastest possible: [1,10,100,1000,10000,...][n]. Array will be relatively small and complexity is O(1).
but I'm getting lost trying to understand of how numbers are represented themselves. Take JavaScript, for example, because it has several native number formats:
Internally, don't they all end up being stored and manipulated as binary values stored in memory?
Yep In javascript, there is only one number type a 64bit float type therefore
1 === 1.0
http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference
If so, is the machine able to store the decimal and scientific-notation representations as fast as it does the octal?
Yes again because there is only one type. (Maybe there is a minute difference but it should be negligible)
However, for this specific case there is a limit on the numbers that can be represented ~ 1e300, therefore the runtime is O(~300) = O(1) all other numbers are represented as +/- Infinity.
And thus, would you expect +("1E" + n) to be faster than Math.pow(10, n)?
Not quite! 1E100 is faster than Math.pow(10,n)
However +("1E"+n) is slower than Math.pow(10,n);
Not because of string and memory allocation, but because the JS interpreter has to parse the string and convert it into a number, and that is slower than the native Math.pow(num,num) operation.
jsperf test
I ran a jsperf on the options.
var sum = 0;
for (var i = 1; i < 20; ++i){
sum += +("1E" + i);
}
is slow because of string concatenation.
var sum = 0;
for (var i = 0; i < 20; ++i){
Math.pow(10, i);
}
is therefore faster, since it operates on numbers only.
var sum = 0;
sum += 1e0;
sum += 1e1;
...
sum += 1e19;
is fastest, but only likely since 1ex for a constant are precomputed values.
To get the best peformance, you might want to precompute the answers for yourself.
Math.pow doesn't distinguish between numbers so it is just as slow for every number, provided that the interpreter doesn't optimize for integers. It is likely to allocate just a few floats to run. I am ignoring parsing time.
"1E"+n will allocate 2~3 string objects which might have quite a substantial memory overhead, destroy intermediates, and reparse it as a number. Unlikely to be faster than pow. I am again ignoring the parse time.
Is this correct? using - http://en.wikipedia.org/wiki/Binomial_probability
Looks like values are from .0000000000000000 to .9999999999999999
Probability of happening twice = p^2 = (1/9999999999999999)^2 = 1.0 e-32
I think I am missing something here?
Also, how does being a pseudo random number generator change this calculation?
Thank You.
In an ideal world Math.random() would be absolutely random, with one output being completely independent from another, which (assuming p=the probability of any given number being produced) results in a probably of p^2 for any value being repeated immediately after another (as others have already said).
In practice people want Math.random to be fast which means pseudo-random number generators are used by the engines. There are many different kinds of PRNG but the most basic is a linear congruential generator, which is basically a function along the lines of:
s(n + 1) = some_prime * s(n) + some_value mod some_other_prime
If such a generator is used then you won't see a value repeated until you've called random() some_other_prime times. You're guaranteed of that.
Relatively recently however it's become apparent that this kind of behaviour (coupled with seeding the PRNGs with the current time) could be used for some forms tracking have led to browsers doing a number of things that mean you can't assume anything about subsequent random() calls.
I think the probability of getting two numbers in a row is 1 divided by the range of the generator, assuming that it has a good distribution.
The reason for this is that the first number can be anything, and the second number needs to just be that number again, which means we don't care about the first number at all. The probability of getting the same number twice in a row is the same as the probability of getting any particular number once.
Getting some particular number twice in a row, e.g. two 0.5s in a row, would be p^2; however, if you just care about any number twice in a row, it's just p.
If the numbers were truly random, you'd expect them, indeed, to appear with probability 1/p, so twice that would be 1/p^2.
The value for p is not exactly the one you have though, because the numbers are being represented internally as binary. Figure out how many bits of mantissa the numbers have in javascript and use that for your combinatoric count.
The "pseudorandom" part is more interesting, because the properties of pseudorandom number generators vary. Knuth does some lovely work with that in Seminumerical Algorithms, but basically most usual PN generators have at least some spectral distributiuon. Cryptograp0hic PN generators are generally stronger.
Update: The amount of time shouldn't be significant. Whether it's a millisecond or a year, as long as you don't update the state The probabilities will stay the same.
The probability that you would get 2 given numbers is (1/p)^2, but the probability that you get 2 of same numbers (any) is 1/p. That is because the first number can be anything, and the second just needs to match that.
You can kind of find out, just let it run a few days :)
var last = 0.1;
var count = 0 | 0;
function rand(){
++count;
var num = Math.random();
if(num === last){
console.log('count: '+count+' num: '+num);
}
last = num;
}
while(true) rand();
How do I generate cryptographically secure random numbers in javascript?
There's been discussion at WHATWG on adding this to the window.crypto object. You can read the discussion and check out the proposed API and webkit bug (22049).
Just tested the following code in Chrome to get a random byte:
(function(){
var buf = new Uint8Array(1);
window.crypto.getRandomValues(buf);
alert(buf[0]);
})();
In order, I think your best bets are:
window.crypto.getRandomValues or window.msCrypto.getRandomValues
The sjcl library's randomWords function (http://crypto.stanford.edu/sjcl/)
The isaac library's random number generator (which is seeded by Math.random, so not really cryptographically secure) (https://github.com/rubycon/isaac.js)
window.crypto.getRandomValues has been implemented in Chrome for a while now, and relatively recently in Firefox as well. Unfortunately, Internet Explorer 10 and before do not implement the function. IE 11 has window.msCrypto, which accomplishes the same thing. sjcl has a great random number generator seeded from mouse movements, but there's always a chance that either the mouse won't have moved sufficiently to seed the generator, or that the user is on a mobile device where there is no mouse movement whatsoever. Thus, I recommend having a fallback case where you can still get a non-secure random number if there is no choice. Here's how I've handled this:
function GetRandomWords (wordCount) {
var randomWords;
// First we're going to try to use a built-in CSPRNG
if (window.crypto && window.crypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.crypto.getRandomValues(randomWords);
}
// Because of course IE calls it msCrypto instead of being standard
else if (window.msCrypto && window.msCrypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.msCrypto.getRandomValues(randomWords);
}
// So, no built-in functionality - bummer. If the user has wiggled the mouse enough,
// sjcl might help us out here
else if (sjcl.random.isReady()) {
randomWords = sjcl.random.randomWords(wordCount);
}
// Last resort - we'll use isaac.js to get a random number. It's seeded from Math.random(),
// so this isn't ideal, but it'll still greatly increase the space of guesses a hacker would
// have to make to crack the password.
else {
randomWords = [];
for (var i = 0; i < wordCount; i++) {
randomWords.push(isaac.rand());
}
}
return randomWords;
};
You'll need to include sjcl.js and isaac.js for that implementation, and be sure to start the sjcl entropy collector as soon as your page is loaded:
sjcl.random.startCollectors();
sjcl is dual-licensed BSD and GPL, while isaac.js is MIT, so it's perfectly safe to use either of those in any project. As mentioned in another answer, clipperz is another option, however for whatever bizarre reason, it is licensed under the AGPL. I have yet to see anyone who seems to understand what implications that has for a JavaScript library, but I'd universally avoid it.
One way to improve the code I've posted might be to store the state of the isaac random number generator in localStorage, so it isn't reseeded every time the page is loaded. Isaac will generate a random sequence, but for cryptography purposes, the seed is all-important. Seeding with Math.random is bad, but at least a little less bad if it isn't necessarily on every page load.
You can for instance use mouse movement as seed for random numbers, read out time and mouse position whenever the onmousemove event happens, feed that data to a whitening function and you will have some first class random at hand. Though do make sure that user has moved the mouse sufficiently before you use the data.
Edit: I have myself played a bit with the concept by making a password generator, I wouldn't guarantee that my whitening function is flawless, but being constantly reseeded I'm pretty sure that it's plenty for the job: ebusiness.hopto.org/generator.htm
Edit2: It now sort of works with smartphones, but only by disabling touch functionality while the entropy is gathered. Android won't work properly any other way.
Use window.crypto.getRandomValues, like this:
var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);
This is supported in all modern browsers and uses the operating system's random generator (e.g. /dev/urandom). If you need IE11 compatibility, you have to use their prefixed implementation viavar crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..) though.
Note that the window.crypto API can also generate keys outright, which may be the better option.
Crypto-strong
to get cryptographic strong number from range [0, 1) (similar to Math.random()) use crypto:
let random = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;
console.log( random() );
You might want to try
http://sourceforge.net/projects/clipperzlib/
It has an implementation of Fortuna which is a cryptographically secure random number generator. (Take a look at src/js/Clipperz/Crypto/PRNG.js). It appears to use the mouse as a source of randomness as well.
First of all, you need a source of entropy. For example, movement of the mouse, password, or any other. But all of these sources are very far from random, and guarantee you 20 bits of entropy, rarely more. The next step that you need to take is to use the mechanism like "Password-Based KDF" it will make computationally difficult to distinguish data from random.
Many years ago, you had to implement your own random number generator and seed it with entropy collected by mouse movement and timing information. This was the Phlogiston Era of JavaScript cryptography. These days we have window.crypto to work with.
If you need a random integer, random-number-csprng is a great choice. It securely generates a series of random bytes and then converts it into an unbiased random integer.
const randomInt = require("random-number-csprng");
(async function() {
let random = randomInt(10, 30);
console.log(`Your random number: ${random}`);
})();
If you need a random floating point number, you'll need to do a little more work. Generally, though, secure randomness is an integer problem, not a floating point problem.
I know i'm late to the party, but if you don't want to deal with the math of getting a cryptographically secure random value, i recommend using rando.js. it's a super small 2kb library that'll give you a decimal, pick something from an array, or whatever else you want- all cryptographically secure.
It's on npm too.
Here's a sample I copied from the GitHub, but it does more than this if you want to go there and read about it more.
console.log(rando()); //a floating-point number between 0 and 1 (could be exactly 0, but never exactly 1)
console.log(rando(5)); //an integer between 0 and 5 (could be 0 or 5)
console.log(rando(5, 10)); //a random integer between 5 and 10 (could be 5 or 10)
console.log(rando(5, "float")); //a floating-point number between 0 and 5 (could be exactly 0, but never exactly 5)
console.log(rando(5, 10, "float")); //a floating-point number between 5 and 10 (could be exactly 5, but never exactly 10)
console.log(rando(true, false)); //either true or false
console.log(rando(["a", "b"])); //{index:..., value:...} object representing a value of the provided array OR false if array is empty
console.log(rando({a: 1, b: 2})); //{key:..., value:...} object representing a property of the provided object OR false if object has no properties
console.log(rando("Gee willikers!")); //a character from the provided string OR false if the string is empty. Reoccurring characters will naturally form a more likely return value
console.log(rando(null)); //ANY invalid arguments return false
<script src="https://randojs.com/2.0.0.js"></script>
If you need large amounts, here's what I would do:
// Max value of random number length
const randLen = 16384
var randomId = randLen
var randomArray = new Uint32Array(randLen)
function random32() {
if (randomId === randLen) {
randomId = 0
return crypto.getRandomValues(randomArray)[randomId++] * 2.3283064365386963e-10
}
return randomArray[randomId++] * 2.3283064365386963e-10
}
function random64() {
if (randomId === randLen || randomId === randLen - 1) {
randomId = 0
crypto.getRandomValues(randomArray)
}
return randomArray[randomId++] * 2.3283064365386963e-10 + randomArray[randomId++] * 5.421010862427522e-20
}
console.log(random32())
console.log(random64())