I've read
the article from Unciphered about it, multiple times, and still fail to understand it
It basically says that wallets generated by BitcoinJs front end library from 2011 to 2015 are vulnerable because of the poor randomness generation. Especially those generated between May 4, 2011 to March 2012
But it's really vague on explaining what the actual exploit is. It could be just summarized as:
it used Math.random() for randomness before March 2014, and it is a bad functionLet's look at the initial commit from
March 4, 2011 :
eckey.js is used for generating the private key, while
rng.js and
prng4.js in the jsbn folder are used for harvesting randomness.
rng.jsIf
rng_pool is not already initialized, it is filled with random values from
Math.random()while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
t = Math.floor(65536 * Math.random());
rng_pool[rng_pptr++] = t >>> 8;
rng_pool[rng_pptr++] = t & 255;
}
Math.random() according to
the article has the cycle of 2^60 values before they repeat. The article also mentions that it
fails modern benchmark tests, but I'm not sure about them
Is
Math.random() the whole weakness of the story? What is the weakness actually about?
Later, the time in milliseconds is seeded to the pool
function rng_seed_time() {
rng_seed_int(new Date().getTime());
}
And later for
SecureRandom.prototype.nextBytes = rng_get_bytes;
we initialize the state, and pass the pool as the key into the RC4 cipher
rng_state = prng_newstate();
rng_state.init(rng_pool);
from
prng4.jsprng4.jswhich creates a 256 values array
and fills it with the loop
for(i = 0; i < 256; ++i) {
j = (j + this.S[i] + key[i % key.length]) & 255;
t = this.S[i];
this.S[i] = this.S[j];
this.S[j] = t;
}
eckey.jseckey.js uses
SecureRandom() and creates our private key
var rng = new SecureRandom();
....
this.priv = ECDSA.getBigRandom(n);
But again, this tells us next to nothing about the actual vulnerability and what attacks might be used. Unciphered's article suggests that if we have GUID or IV (I guess that's a public key?), then we can do the work with just 2^32 to 2^64 values (2^48 most commonly)
Also, not sure about the clicks being added in the entropy pool, apart from:
<body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
comment.
In what way, other things are added into entropy pool apart from the initial timestamp seed?
Edit July 23, 2024:Sorry, I forgot that
ecdsa.js also has its own context
ecdsa.jsBasically,
getBigRandom() method is realized in this file with
rng = new SecureRandom();Bitcoin.ECDSA = (function () {
var ecparams = getSECCurveByName("secp256k1");
var rng = new SecureRandom();
....
var ECDSA = {
getBigRandom: function (limit) {
return new BigInteger(limit.bitLength(), rng)
.mod(limit.subtract(BigInteger.ONE))
.add(BigInteger.ONE)
;
},
.