js-randomness-predictor
Version:
Predict Math.random output in Node, Chrome, and Firefox
141 lines (140 loc) • 11.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _FirefoxRandomnessPredictor_instances, _FirefoxRandomnessPredictor_isInitialized, _FirefoxRandomnessPredictor_mask, _FirefoxRandomnessPredictor_seState0, _FirefoxRandomnessPredictor_seState1, _FirefoxRandomnessPredictor_s0Ref, _FirefoxRandomnessPredictor_s1Ref, _FirefoxRandomnessPredictor_solver, _FirefoxRandomnessPredictor_context, _FirefoxRandomnessPredictor_concreteState0, _FirefoxRandomnessPredictor_concreteState1, _FirefoxRandomnessPredictor_initialize, _FirefoxRandomnessPredictor_xorShift128PlusSymbolic, _FirefoxRandomnessPredictor_xorShift128PlusConcrete, _FirefoxRandomnessPredictor_recoverMantissa, _FirefoxRandomnessPredictor_toDouble;
Object.defineProperty(exports, "__esModule", { value: true });
const z3 = __importStar(require("z3-solver"));
const errors_js_1 = require("../errors.js");
class FirefoxRandomnessPredictor {
constructor(sequence) {
_FirefoxRandomnessPredictor_instances.add(this);
_FirefoxRandomnessPredictor_isInitialized.set(this, false);
_FirefoxRandomnessPredictor_mask.set(this, 0xffffffffffffffffn);
_FirefoxRandomnessPredictor_seState0.set(this, void 0);
_FirefoxRandomnessPredictor_seState1.set(this, void 0);
_FirefoxRandomnessPredictor_s0Ref.set(this, void 0);
_FirefoxRandomnessPredictor_s1Ref.set(this, void 0);
_FirefoxRandomnessPredictor_solver.set(this, void 0);
_FirefoxRandomnessPredictor_context.set(this, void 0);
_FirefoxRandomnessPredictor_concreteState0.set(this, 0n);
_FirefoxRandomnessPredictor_concreteState1.set(this, 0n);
this.sequence = [];
this.sequence = sequence;
}
/**
* Predict next random number.
* @returns {Promise<number>}
*/
async predictNext() {
await __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_instances, "m", _FirefoxRandomnessPredictor_initialize).call(this);
return __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_instances, "m", _FirefoxRandomnessPredictor_toDouble).call(this, __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_instances, "m", _FirefoxRandomnessPredictor_xorShift128PlusConcrete).call(this));
}
}
_FirefoxRandomnessPredictor_isInitialized = new WeakMap(), _FirefoxRandomnessPredictor_mask = new WeakMap(), _FirefoxRandomnessPredictor_seState0 = new WeakMap(), _FirefoxRandomnessPredictor_seState1 = new WeakMap(), _FirefoxRandomnessPredictor_s0Ref = new WeakMap(), _FirefoxRandomnessPredictor_s1Ref = new WeakMap(), _FirefoxRandomnessPredictor_solver = new WeakMap(), _FirefoxRandomnessPredictor_context = new WeakMap(), _FirefoxRandomnessPredictor_concreteState0 = new WeakMap(), _FirefoxRandomnessPredictor_concreteState1 = new WeakMap(), _FirefoxRandomnessPredictor_instances = new WeakSet(), _FirefoxRandomnessPredictor_initialize = async function _FirefoxRandomnessPredictor_initialize() {
if (__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_isInitialized, "f")) {
return true;
}
try {
const { Context } = await z3.init();
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_context, Context("main"), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_solver, new (__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_context, "f").Solver)(), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_seState0, __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_context, "f").BitVec.const("se_state0", 64), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_seState1, __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_context, "f").BitVec.const("se_state1", 64), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_s0Ref, __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState0, "f"), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_s1Ref, __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState1, "f"), "f");
for (let i = 0; i < this.sequence.length; i++) {
__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_instances, "m", _FirefoxRandomnessPredictor_xorShift128PlusSymbolic).call(this);
const mantissa = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_instances, "m", _FirefoxRandomnessPredictor_recoverMantissa).call(this, this.sequence[i]);
const state = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState0, "f").add(__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState1, "f")).and(__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_context, "f").BitVec.val(0x1fffffffffffff, 64));
__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_solver, "f").add(state.eq(__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_context, "f").BitVec.val(mantissa, 64)));
}
const check = await __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_solver, "f").check();
if (check !== "sat") {
return Promise.reject(new errors_js_1.UnsatError());
}
const model = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_solver, "f").model();
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_concreteState0, model.get(__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_s0Ref, "f")).value(), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_concreteState1, model.get(__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_s1Ref, "f")).value(), "f");
// We have to get our concrete state up to the same point as our symbolic state,
// therefore, we discard as many concrete XOR shift calls as we have `this.sequence.length`
// Otherwise, we would return random numbers to the caller that they already have.
// Now, when we return from predictNext() we get the actual next.
for (let i = 0; i < this.sequence.length; i++) {
__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_instances, "m", _FirefoxRandomnessPredictor_xorShift128PlusConcrete).call(this);
}
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_isInitialized, true, "f");
return true;
}
catch (e) {
return Promise.reject(e);
}
}, _FirefoxRandomnessPredictor_xorShift128PlusSymbolic = function _FirefoxRandomnessPredictor_xorShift128PlusSymbolic() {
if (__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState0, "f") === undefined || __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState1, "f") === undefined) {
throw new Error("States are not defined!");
}
let s1 = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState0, "f");
let s0 = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState1, "f");
s1 = s1.xor(s1.shl(23));
s1 = s1.xor(s1.lshr(17));
s1 = s1.xor(s0);
s1 = s1.xor(s0.lshr(26));
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_seState0, __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_seState1, "f"), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_seState1, s1, "f");
}, _FirefoxRandomnessPredictor_xorShift128PlusConcrete = function _FirefoxRandomnessPredictor_xorShift128PlusConcrete() {
let s1 = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_concreteState0, "f") & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
let s0 = __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_concreteState1, "f") & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
s1 ^= (s1 << 23n) & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
s1 ^= (s1 >> 17n) & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
s1 ^= s0 & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
s1 ^= (s0 >> 26n) & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_concreteState0, s0 & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f"), "f");
__classPrivateFieldSet(this, _FirefoxRandomnessPredictor_concreteState1, s1 & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f"), "f");
return (__classPrivateFieldGet(this, _FirefoxRandomnessPredictor_concreteState0, "f") + __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_concreteState1, "f")) & __classPrivateFieldGet(this, _FirefoxRandomnessPredictor_mask, "f");
}, _FirefoxRandomnessPredictor_recoverMantissa = function _FirefoxRandomnessPredictor_recoverMantissa(double) {
return BigInt(Math.floor(double * Math.pow(2, 53)));
}, _FirefoxRandomnessPredictor_toDouble = function _FirefoxRandomnessPredictor_toDouble(n) {
return Number(n & 0x1fffffffffffffn) / Number(1n << 53n);
};
exports.default = FirefoxRandomnessPredictor;