Is Math.random() cryptographically secure? - javascript

How good are algorithms used in Javascript Math.random() in different browsers? Is it okay to use it for generating salts and one-time passwords?
How many bits from one random I can use?

Nope; JavaScript's Math.random() function is not a cryptographically-secure random number generator. You are better off using the JavaScript Crypto Library's Fortuna implementation which is a strong pseudo-random number generator (have a look at src/js/Clipperz/Crypto/PRNG.js), or the Web Crypto API for getRandomValues
Here is a detailed explanation: How trustworthy is javascript's random implementation in various browsers?
Here is how to generate a good crypto grade random number: Secure random numbers in javascript?

It is not secure at all, and in some cases was so predictable you could rebuild internal state of the PRNG, deduct the seed and thus could use it to track people across websites even if they didn't use cookies, hid behind onion routing etc...
2022 edit since this answer still gets upvotes: use Crypto.getRandomValues if you need a cryptographic RNG in JavaScript
http://landing2.trusteer.com/sites/default/files/Temporary_User_Tracking_in_Major_Browsers.pdf a 2008 paper exposing the user tracking possibilities of the browser weak PRNG
http://dl.packetstormsecurity.net/papers/general/Google_Chrome_3.0_Beta_Math.random_vulnerability.pdf a later (2009) Chrome vulnerability, as the problem was already well known

As of March 2013, window.crypto.getRandomValues is an "experimental technology" available since Chrome 11 and Firefox 21 that lets you get cryptographically random values. Also, see getRandomValues from the lastest W3C Web Cryptography API draft.
Description:
If you provide an integer-based TypedArray (i.e. Int8Array,
Uint8Array, Int16Array, Uint16Array, Int32Array, or Uint32Array), the
function is going fill the array with cryptographically random
numbers. The browser is supposed to be using a strong (pseudo) random number generator. The method throws the QuotaExceededError if the requested length is greater than 65536 bytes.
Example:
var array = new Uint32Array(10);
window.crypto.getRandomValues(array);
console.log("Your lucky numbers:");
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
Also, an answer to How random is JavaScript's Math.random? refers to Temporary user tracking in major browsers and Cross-domain information leakage and attacks from 2008 which discusses how the JavaScript Math.random() function leaks information.
Update: For current browser support status, check out the Modern.IE Web Crypto API section, which also links to the Chrome, Firefox, and Safari bug reports.

Because you cannot know the exact implementation of the browser (except for closed user groups like for your business intranet) I would generally consider the RNG weak.
Even if you can identify the browser you don't know if the browser itself or any other browser's agent ID is manipulated. If you can you should generate the number on the server.
Even if you include a good PRNG in your JavaScript your server cannot know whether the request from the client originates from an unmodified script. If the number goes into your database and/or is used as a cryptographic tool it is no good idea to trust the data from the client at all. That is true not only for validity (You do validate all data coming from the client, don't you?) but also for general properties like randomness.

Math.random() is not cryptographically secure. Also Veracode will point this occurrence with
CWE-331 (Insufficient Entropy)
We could make use of SecureRandom to implement similar functionality.
new SecureRandom().nextDouble();

Related

Timestamps for custom output-only AudioWorkletProcessor

I'd like to build a very low-level audio output node using the web audio API's AudioWorkletProcessor. It seems like all of the examples out there implement processors that transform input samples to output samples, but what I'd like to do is produce output only, all based on the timestamp of the samples.
According to MDN, BaseAudioContext.currentTime is not a precise source for this timestamp:
To offer protection against timing attacks and fingerprinting, the precision of audioCtx.currentTime might get rounded depending on browser settings.
In Firefox, the privacy.reduceTimerPrecision preference is enabled by default and defaults to 20us in Firefox 59; in 60 it will be 2ms.
One hacky solution may be to use BaseAudioContext.sampleRate, a running counter, and the size of the output arrays, but that only works if we can assume that every sample is computed without drops and that everything's computed in order, and I'm not sure if those are valid assumptions.
Within a processing frame, is there a reliable way to know the timestamp which correlates to given sample index?
Inside of the AudioWorkletGlobalScope you have access to the currentTime as well as to the currentFrame. They are both available as globals.
https://webaudio.github.io/web-audio-api/#AudioWorkletGlobalScope-attributes
As far as I know they are accurate in any browser which supports the AudioWorklet.

Are simpleflake ids generarated in different languages consistent?

I need to generated unique Ids in distributed manner. Some at server side and another at client side. Server side programming language can be ruby and python while client side is javascript.
I am plannning to use simpleflake libraries for respective languages.
Can I assume that the ids will never collide?
OR they can collide often, due to the implementation details in different packages?
Thanks in advance.
-Amit
Python's Simpleflake and Node.js's simpleflakes are actually derived from same origin (python's implementation). Both generate 64bit IDs And IDs generated by both are compatible with each other.
The simple flake generates id with the formula
flake = (int((time.time() - 946702800) * 1000) << 23) + random.SystemRandom().getrandbits(23)
As pointed out in earlier answer, the probability of collision is really low (It is the probability of clashing 41 bit timestamp in milliseconds and the probability of randomly generated 23 bit integer).
However, it'd be important to know the difference between two implementations mentioned above. The simpleflakes node.js library fixes its epoch at 2000-01-01T00:00:00.000Z whereas python implementation assumes the epoch at 2000-01-01T05:00:00.000Z.
I haven't used Simpleflake itself, but have been using a similar scheme for years, though I use 128 bits instead of 64.
The key ingredient is that most of the bits are random. So even if your libraries choose a slightly different number of bits for the timestamp portion, or a different granularity then the likelihood of collisions is low. Of course, in such cases it lessens the speed improvements in the database.
I imagine that some Simpleflake implementation is "standard" and the other implementations are straight ports---keeping compatibility and characteristics. If not, shame on them for using Simpleflake in their name.

PBKDF2-SHA256 encryption in JavaScript [duplicate]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 10 months ago.
The community reviewed whether to reopen this question 9 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I am writing a login for a forum, and need to hash the password client side in javascript before sending it on to the server. I'm having trouble figuring out which SHA-256 implementation I can actually trust. I was expecting there to be some kind of authoritative script that everyone used, but I'm finding loads of different projects all with their own implementations.
I realize using other people's crypto is always a leap of faith unless you're qualified to review it yourself, and that there is no universal definition of "trustworthy", but this seems like something common and important enough that there ought to be some kind of consensus on what to use. Am I just naive?
Edit since it comes up a lot in the comments: Yes, we do a more stringent hash again on the server side. The client side hashing is not the final result that we save in the database. The client side hashing is because the human client requests it. They have not given a specific reason why, probably they just like overkill.
On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest I found this snippet that uses internal js module:
async function sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));
// convert bytes to hex string
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
Note that crypto.subtle in only available on https or localhost - for example for your local development with python3 -m http.server you need to add this line to your /etc/hosts:
0.0.0.0 localhost
Reboot - and you can open localhost:8000 with working crypto.subtle.
OUTDATED: Many modern browsers now have first-class support for crypto operations. See Vitaly Zdanevich's answer below.
The Stanford JS Crypto Library contains an implementation of SHA-256. While crypto in JS isn't really as well-vetted an endeavor as other implementation platforms, this one is at least partially developed by, and to a certain extent sponsored by, Dan Boneh, who is a well-established and trusted name in cryptography, and means that the project has some oversight by someone who actually knows what he's doing. The project is also supported by the NSF.
It's worth pointing out, however...
... that if you hash the password client-side before submitting it, then the hash is the password, and the original password becomes irrelevant. An attacker needs only to intercept the hash in order to impersonate the user, and if that hash is stored unmodified on the server, then the server is storing the true password (the hash) in plain-text.
So your security is now worse because you decided add your own improvements to what was previously a trusted scheme.
For those interested, this is code for creating SHA-256 hash using sjcl:
import sjcl from 'sjcl'
const myString = 'Hello'
const myBitArray = sjcl.hash.sha256.hash(myString)
const myHash = sjcl.codec.hex.fromBits(myBitArray)
Forge's SHA-256 implementation is fast and reliable.
To run tests on several SHA-256 JavaScript implementations, go to http://brillout.github.io/test-javascript-hash-implementations/.
The results on my machine suggests forge to be the fastest implementation and also considerably faster than the Stanford Javascript Crypto Library (sjcl) mentioned in the accepted answer.
Forge is 256 KB big, but extracting the SHA-256 related code reduces the size to 4.5 KB, see https://github.com/brillout/forge-sha256
No, there's no way to use browser JavaScript to improve password security. I highly recommend you read this article. In your case, the biggest problem is the chicken-egg problem:
What's the "chicken-egg problem" with delivering Javascript cryptography?
If you don't trust the network to deliver a password, or, worse, don't trust the server not to keep user secrets, you can't trust them to deliver security code. The same attacker who was sniffing passwords or reading diaries before you introduce crypto is simply hijacking crypto code after you do.
[...]
Why can't I use TLS/SSL to deliver the Javascript crypto code?
You can. It's harder than it sounds, but you safely transmit Javascript crypto to a browser using SSL. The problem is, having established a secure channel with SSL, you no longer need Javascript cryptography; you have "real" cryptography.
Which leads to this:
The problem with running crypto code in Javascript is that practically any function that the crypto depends on could be overridden silently by any piece of content used to build the hosting page. Crypto security could be undone early in the process (by generating bogus random numbers, or by tampering with constants and parameters used by algorithms), or later (by spiriting key material back to an attacker), or --- in the most likely scenario --- by bypassing the crypto entirely.
There is no reliable way for any piece of Javascript code to verify its execution environment. Javascript crypto code can't ask, "am I really dealing with a random number generator, or with some facsimile of one provided by an attacker?" And it certainly can't assert "nobody is allowed to do anything with this crypto secret except in ways that I, the author, approve of". These are two properties that often are provided in other environments that use crypto, and they're impossible in Javascript.
Basically the problem is this:
Your clients don't trust your servers, so they want to add extra security code.
That security code is delivered by your servers (the ones they don't trust).
Or alternatively,
Your clients don't trust SSL, so they want you use extra security code.
That security code is delivered via SSL.
Note: Also, SHA-256 isn't suitable for this, since it's so easy to brute force unsalted non-iterated passwords. If you decide to do this anyway, look for an implementation of bcrypt, scrypt or PBKDF2.
I found this implementation very easy to use. Also has a generous BSD-style license:
jsSHA: https://github.com/Caligatio/jsSHA
I needed a quick way to get the hex-string representation of a SHA-256 hash. It only took 3 lines:
var sha256 = new jsSHA('SHA-256', 'TEXT');
sha256.update(some_string_variable_to_hash);
var hash = sha256.getHash("HEX");
It is possible to use CryptoJS - https://www.npmjs.com/package/crypto-js
import sha256 from 'crypto-js/sha256'
const hash = sha256('Text')
Besides the Stanford lib that tylerl mentioned. I found jsrsasign very useful (Github repo here:https://github.com/kjur/jsrsasign). I don't know how exactly trustworthy it is, but i've used its API of SHA256, Base64, RSA, x509 etc. and it works pretty well. In fact, it includes the Stanford lib as well.
If all you want to do is SHA256, jsrsasign might be a overkill. But if you have other needs in the related area, I feel it's a good fit.
js-sha256 is an npm package you can use, and unlike the popular crypto.subtle which only works on secure connections(localhost/https) it can work regardless. Of course having a secure connection is still the best. I was using crypto.subtle and it always worked because I run my webapp using localhost and it failed the instant I tried it on a server. I had to switch to the js-sha256 npm package as a temporary solution until a secure connection can be configured.
ethers.js has a SHA256 (https://docs.ethers.io/v5/api/utils/hashing/)
const { ethers } = require('ethers');
ethers.utils.sha256(ethers.utils.toUtf8Bytes('txt'));

Random function in Javascript considered insecure. Does it really matter?

I am writing some code that shall run in a browser, which uses Javascript random function(s) for key generation.
Now reading in several forums that this is considered to be not secure, due to bad random number generation.
Now, what if I only create one key pair per browser/computer. So, having a distributed scenario where there is actually no sequence of random numbers per browser. Will this fundamentally change the problematic situation? Thanks for your thoughts.
Yes it matters. If an attacker generates random numbers at the same time as a genuine user, they can predict what is generated and retrieve they key. Even if the clocks aren't fully synchronised, an attacker could generate a range around the UNIX timestamp when the key was known to have been generated and then try each one in turn.
Solution: Use window.crypto to generate a secure random number using the crypto library.
The Crypto interface represents basic cryptography features available
in the current context. It allows access to a cryptographically strong
random number generator and to cryptographic primitives.
Random numbers are generated in Javascript by the amount of milliseconds since 1st of January 1970(UNIX Timestamp). Then Javascript just takes the first few values and that is your random number. i.e.
Math.floor((Math.random() * 10) + 1);
Makes a random number between 1 and 10.

JavaScript FileSystem API as Chess Alpha Beta data storage

I'm starting to write a Chess program in JavaScript and possibly some Node.JS if I find the need to involve the server in the Chess AI logic, which is still plausible at least in my possibly ignorant opinion. My question is simple enough: Is the client-side FileSystem API for JavaScript a reasonable way to cache off minimax results for future reference, or is the resulting data just way too much to store in any one place? My idea was that it could be used as a way to allow the AI to adapt to the user and "learn" by being able to access previous decisions rather than manually re-determining them every time. Is this a reasonable plan or am I underestimating the memory usage this would need? If your answer is that this is plausible, some tips on the most efficient method for storing the data in this manner would be nice too.
I have written Chess Engines before in C++, but no Javascript.
What you describe is usually solved by a transposition table. You calculate a hash key that identifies the position and store additional data with it.
See:
https://www.chessprogramming.org/Transposition_Table
https://www.chessprogramming.org/Zobrist_Hashing
Web storage provides per origin:
2.5 MB for Google Chrome
5 MB for Mozilla Firefox
10 MB for Internet Explorer
Each entry usually holds:
Zobrist Hash Key: 8 byte
Best Move: 2 byte
Depth: 1 byte
Score: 2 byte
Type of score (exact, upper bound, lower bound): 1 byte
= 16 byte
So e.g. Google Chrome can hold 160k entries. Usually for a chess position analysis you use over 1 GB of memory for the transposition table. Anyway, for a javascript engine I think the 2.5 MB is a good compromise.
To make sure that the javascript engine uses the optimal storage I advise you to convert the data to some sort of binary representation. Then I would index the localStorage by Zobrist Hash Key and store all the other information associated with it.

Categories

Resources