1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/rocketchat_ynh.git synced 2024-09-03 20:16:25 +02:00
rocketchat_ynh/sources/programs/server/packages/random.js
2016-04-29 16:32:48 +02:00

312 lines
34 KiB
JavaScript

(function () {
/* Imports */
var Meteor = Package.meteor.Meteor;
var _ = Package.underscore._;
var ECMAScript = Package.ecmascript.ECMAScript;
var babelHelpers = Package['babel-runtime'].babelHelpers;
var Symbol = Package['ecmascript-runtime'].Symbol;
var Map = Package['ecmascript-runtime'].Map;
var Set = Package['ecmascript-runtime'].Set;
var Promise = Package.promise.Promise;
/* Package-scope variables */
var Random;
(function(){
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// packages/random/random.js //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// We use cryptographically strong PRNGs (crypto.getRandomBytes() on the server, //
// window.crypto.getRandomValues() in the browser) when available. If these //
// PRNGs fail, we fall back to the Alea PRNG, which is not cryptographically //
// strong, and we seed it with various sources such as the date, Math.random, //
// and window size on the client. When using crypto.getRandomValues(), our //
// primitive is hexString(), from which we construct fraction(). When using //
// window.crypto.getRandomValues() or alea, the primitive is fraction and we use //
// that to construct hex string. //
//
if (Meteor.isServer) var nodeCrypto = Npm.require('crypto'); // 10
//
// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript //
// for a full discussion and Alea implementation. //
var Alea = function () { // 15
function Mash() { // 16
var n = 0xefc8249d; // 17
//
var mash = function (data) { // 19
data = data.toString(); // 20
for (var i = 0; i < data.length; i++) { // 21
n += data.charCodeAt(i); // 22
var h = 0.02519603282416938 * n; // 23
n = h >>> 0; // 24
h -= n; // 25
h *= n; // 26
n = h >>> 0; // 27
h -= n; // 28
n += h * 0x100000000; // 2^32 // 29
} //
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 // 31
}; //
//
mash.version = 'Mash 0.9'; // 34
return mash; // 35
} //
//
return (function (args) { // 38
var s0 = 0; // 39
var s1 = 0; // 40
var s2 = 0; // 41
var c = 1; // 42
//
if (args.length == 0) { // 44
args = [+new Date()]; // 45
} //
var mash = Mash(); // 47
s0 = mash(' '); // 48
s1 = mash(' '); // 49
s2 = mash(' '); // 50
//
for (var i = 0; i < args.length; i++) { // 52
s0 -= mash(args[i]); // 53
if (s0 < 0) { // 54
s0 += 1; // 55
} //
s1 -= mash(args[i]); // 57
if (s1 < 0) { // 58
s1 += 1; // 59
} //
s2 -= mash(args[i]); // 61
if (s2 < 0) { // 62
s2 += 1; // 63
} //
} //
mash = null; // 66
//
var random = function () { // 68
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 // 69
s0 = s1; // 70
s1 = s2; // 71
return s2 = t - (c = t | 0); // 72
}; //
random.uint32 = function () { // 74
return random() * 0x100000000; // 2^32 // 75
}; //
random.fract53 = function () { // 77
return random() + (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 // 78
}; //
random.version = 'Alea 0.9'; // 81
random.args = args; // 82
return random; // 83
})(Array.prototype.slice.call(arguments)); //
}; //
//
var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz"; // 88
var BASE64_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-_"; // 89
//
// `type` is one of `RandomGenerator.Type` as defined below. //
// //
// options: //
// - seeds: (required, only for RandomGenerator.Type.ALEA) an array //
// whose items will be `toString`ed and used as the seed to the Alea //
// algorithm //
var RandomGenerator = function (type, options) { // 98
var self = this; // 99
self.type = type; // 100
//
if (!RandomGenerator.Type[type]) { // 102
throw new Error("Unknown random generator type: " + type); // 103
} //
//
if (type === RandomGenerator.Type.ALEA) { // 106
if (!options.seeds) { // 107
throw new Error("No seeds were provided for Alea PRNG"); // 108
} //
self.alea = Alea.apply(null, options.seeds); // 110
} //
}; //
//
// Types of PRNGs supported by the `RandomGenerator` class //
RandomGenerator.Type = { // 115
// Use Node's built-in `crypto.getRandomBytes` (cryptographically //
// secure but not seedable, runs only on the server). Reverts to //
// `crypto.getPseudoRandomBytes` in the extremely uncommon case that //
// there isn't enough entropy yet //
NODE_CRYPTO: "NODE_CRYPTO", // 120
//
// Use non-IE browser's built-in `window.crypto.getRandomValues` //
// (cryptographically secure but not seedable, runs only in the //
// browser). //
BROWSER_CRYPTO: "BROWSER_CRYPTO", // 125
//
// Use the *fast*, seedaable and not cryptographically secure //
// Alea algorithm //
ALEA: "ALEA" // 129
}; //
//
RandomGenerator.prototype.fraction = function () { // 132
var self = this; // 133
if (self.type === RandomGenerator.Type.ALEA) { // 134
return self.alea(); // 135
} else if (self.type === RandomGenerator.Type.NODE_CRYPTO) { //
var numerator = parseInt(self.hexString(8), 16); // 137
return numerator * 2.3283064365386963e-10; // 2^-32 // 138
} else if (self.type === RandomGenerator.Type.BROWSER_CRYPTO) { //
var array = new Uint32Array(1); // 140
window.crypto.getRandomValues(array); // 141
return array[0] * 2.3283064365386963e-10; // 2^-32 // 142
} else { //
throw new Error('Unknown random generator type: ' + self.type); // 144
} //
}; //
//
RandomGenerator.prototype.hexString = function (digits) { // 148
var self = this; // 149
if (self.type === RandomGenerator.Type.NODE_CRYPTO) { // 150
var numBytes = Math.ceil(digits / 2); // 151
var bytes; // 152
// Try to get cryptographically strong randomness. Fall back to //
// non-cryptographically strong if not available. //
try { // 155
bytes = nodeCrypto.randomBytes(numBytes); // 156
} catch (e) { //
// XXX should re-throw any error except insufficient entropy //
bytes = nodeCrypto.pseudoRandomBytes(numBytes); // 159
} //
var result = bytes.toString("hex"); // 161
// If the number of digits is odd, we'll have generated an extra 4 bits //
// of randomness, so we need to trim the last digit. //
return result.substring(0, digits); // 164
} else { //
return this._randomString(digits, "0123456789abcdef"); // 166
} //
}; //
//
RandomGenerator.prototype._randomString = function (charsCount, alphabet) { // 170
var self = this; // 172
var digits = []; // 173
for (var i = 0; i < charsCount; i++) { // 174
digits[i] = self.choice(alphabet); // 175
} //
return digits.join(""); // 177
}; //
//
RandomGenerator.prototype.id = function (charsCount) { // 180
var self = this; // 181
// 17 characters is around 96 bits of entropy, which is the amount of //
// state in the Alea PRNG. //
if (charsCount === undefined) charsCount = 17; // 184
//
return self._randomString(charsCount, UNMISTAKABLE_CHARS); // 187
}; //
//
RandomGenerator.prototype.secret = function (charsCount) { // 190
var self = this; // 191
// Default to 256 bits of entropy, or 43 characters at 6 bits per //
// character. //
if (charsCount === undefined) charsCount = 43; // 194
return self._randomString(charsCount, BASE64_CHARS); // 196
}; //
//
RandomGenerator.prototype.choice = function (arrayOrString) { // 199
var index = Math.floor(this.fraction() * arrayOrString.length); // 200
if (typeof arrayOrString === "string") return arrayOrString.substr(index, 1);else return arrayOrString[index]; // 201
}; //
//
// instantiate RNG. Heuristically collect entropy from various sources when a //
// cryptographic PRNG isn't available. //
//
// client sources //
var height = typeof window !== 'undefined' && window.innerHeight || typeof document !== 'undefined' && document.documentElement && document.documentElement.clientHeight || typeof document !== 'undefined' && document.body && document.body.clientHeight || 1;
//
var width = typeof window !== 'undefined' && window.innerWidth || typeof document !== 'undefined' && document.documentElement && document.documentElement.clientWidth || typeof document !== 'undefined' && document.body && document.body.clientWidth || 1;
//
var agent = typeof navigator !== 'undefined' && navigator.userAgent || ""; // 229
//
function createAleaGeneratorWithGeneratedSeed() { // 231
return new RandomGenerator(RandomGenerator.Type.ALEA, { seeds: [new Date(), height, width, agent, Math.random()] });
}; //
//
if (Meteor.isServer) { // 237
Random = new RandomGenerator(RandomGenerator.Type.NODE_CRYPTO); // 238
} else { //
if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) { // 240
Random = new RandomGenerator(RandomGenerator.Type.BROWSER_CRYPTO); // 242
} else { //
// On IE 10 and below, there's no browser crypto API //
// available. Fall back to Alea //
// //
// XXX looks like at the moment, we use Alea in IE 11 as well, //
// which has `window.msCrypto` instead of `window.crypto`. //
Random = createAleaGeneratorWithGeneratedSeed(); // 249
} //
} //
//
// Create a non-cryptographically secure PRNG with a given seed (using //
// the Alea algorithm) //
Random.createWithSeeds = function () { // 255
for (var _len = arguments.length, seeds = Array(_len), _key = 0; _key < _len; _key++) { //
seeds[_key] = arguments[_key]; // 255
} //
//
if (seeds.length === 0) { // 256
throw new Error("No seeds were provided"); // 257
} //
return new RandomGenerator(RandomGenerator.Type.ALEA, { seeds: seeds }); // 259
}; //
//
// Used like `Random`, but much faster and not cryptographically //
// secure //
Random.insecure = createAleaGeneratorWithGeneratedSeed(); // 264
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}).call(this);
(function(){
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// packages/random/deprecated.js //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Before this package existed, we used to use this Meteor.uuid() //
// implementing the RFC 4122 v4 UUID. It is no longer documented //
// and will go away. //
// XXX COMPAT WITH 0.5.6 //
Meteor.uuid = function () { // 5
var HEX_DIGITS = "0123456789abcdef"; // 6
var s = []; // 7
for (var i = 0; i < 36; i++) { // 8
s[i] = Random.choice(HEX_DIGITS); // 9
} //
s[14] = "4"; // 11
s[19] = HEX_DIGITS.substr(parseInt(s[19], 16) & 0x3 | 0x8, 1); // 12
s[8] = s[13] = s[18] = s[23] = "-"; // 13
//
var uuid = s.join(""); // 15
return uuid; // 16
}; //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}).call(this);
/* Exports */
if (typeof Package === 'undefined') Package = {};
Package.random = {
Random: Random
};
})();
//# sourceMappingURL=random.js.map