| 'use strict' |
| |
| function oldBrowser () { |
| throw new Error('secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11') |
| } |
| var safeBuffer = require('safe-buffer') |
| var randombytes = require('randombytes') |
| var Buffer = safeBuffer.Buffer |
| var kBufferMaxLength = safeBuffer.kMaxLength |
| var crypto = global.crypto || global.msCrypto |
| var kMaxUint32 = Math.pow(2, 32) - 1 |
| function assertOffset (offset, length) { |
| if (typeof offset !== 'number' || offset !== offset) { // eslint-disable-line no-self-compare |
| throw new TypeError('offset must be a number') |
| } |
| |
| if (offset > kMaxUint32 || offset < 0) { |
| throw new TypeError('offset must be a uint32') |
| } |
| |
| if (offset > kBufferMaxLength || offset > length) { |
| throw new RangeError('offset out of range') |
| } |
| } |
| |
| function assertSize (size, offset, length) { |
| if (typeof size !== 'number' || size !== size) { // eslint-disable-line no-self-compare |
| throw new TypeError('size must be a number') |
| } |
| |
| if (size > kMaxUint32 || size < 0) { |
| throw new TypeError('size must be a uint32') |
| } |
| |
| if (size + offset > length || size > kBufferMaxLength) { |
| throw new RangeError('buffer too small') |
| } |
| } |
| if ((crypto && crypto.getRandomValues) || !process.browser) { |
| exports.randomFill = randomFill |
| exports.randomFillSync = randomFillSync |
| } else { |
| exports.randomFill = oldBrowser |
| exports.randomFillSync = oldBrowser |
| } |
| function randomFill (buf, offset, size, cb) { |
| if (!Buffer.isBuffer(buf) && !(buf instanceof global.Uint8Array)) { |
| throw new TypeError('"buf" argument must be a Buffer or Uint8Array') |
| } |
| |
| if (typeof offset === 'function') { |
| cb = offset |
| offset = 0 |
| size = buf.length |
| } else if (typeof size === 'function') { |
| cb = size |
| size = buf.length - offset |
| } else if (typeof cb !== 'function') { |
| throw new TypeError('"cb" argument must be a function') |
| } |
| assertOffset(offset, buf.length) |
| assertSize(size, offset, buf.length) |
| return actualFill(buf, offset, size, cb) |
| } |
| |
| function actualFill (buf, offset, size, cb) { |
| if (process.browser) { |
| var ourBuf = buf.buffer |
| var uint = new Uint8Array(ourBuf, offset, size) |
| crypto.getRandomValues(uint) |
| if (cb) { |
| process.nextTick(function () { |
| cb(null, buf) |
| }) |
| return |
| } |
| return buf |
| } |
| if (cb) { |
| randombytes(size, function (err, bytes) { |
| if (err) { |
| return cb(err) |
| } |
| bytes.copy(buf, offset) |
| cb(null, buf) |
| }) |
| return |
| } |
| var bytes = randombytes(size) |
| bytes.copy(buf, offset) |
| return buf |
| } |
| function randomFillSync (buf, offset, size) { |
| if (typeof offset === 'undefined') { |
| offset = 0 |
| } |
| if (!Buffer.isBuffer(buf) && !(buf instanceof global.Uint8Array)) { |
| throw new TypeError('"buf" argument must be a Buffer or Uint8Array') |
| } |
| |
| assertOffset(offset, buf.length) |
| |
| if (size === undefined) size = buf.length - offset |
| |
| assertSize(size, offset, buf.length) |
| |
| return actualFill(buf, offset, size) |
| } |