Skip to content

Commit 1cdf057

Browse files
committed
zero copy large buffer random bytes
1 parent 5e89305 commit 1cdf057

File tree

2 files changed

+57
-17
lines changed

2 files changed

+57
-17
lines changed

browser.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
'use strict'
22

3+
// limit of Crypto.getRandomValues()
4+
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
5+
var MAX_BYTES = 65536
6+
7+
// Node supports requesting up to this number of bytes
8+
// https://github.com/nodejs/node/blob/master/lib/internal/crypto/random.js#L48
9+
var MAX_UINT32 = 4294967295
10+
311
function oldBrowser () {
412
throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11')
513
}
@@ -15,14 +23,21 @@ if (crypto && crypto.getRandomValues) {
1523

1624
function randomBytes (size, cb) {
1725
// phantomjs needs to throw
18-
if (size > 65536) throw new Error('requested too many random bytes')
26+
if (size > MAX_UINT32) throw new Error('requested too many random bytes')
1927
// in case browserify isn't using the Uint8Array version
2028
var bytes = Buffer.allocUnsafe(size)
2129

2230
// This will not work in older browsers.
2331
// See https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
2432
if (size > 0) { // getRandomValues fails on IE if size == 0
25-
crypto.getRandomValues(bytes)
33+
if (size > MAX_BYTES) {
34+
for (var generated = 0; generated < size; generated += MAX_BYTES) {
35+
var nextChunk = generated + MAX_BYTES > size ? size - generated : MAX_BYTES
36+
crypto.getRandomValues(bytes.slice(generated, generated + nextChunk))
37+
}
38+
} else {
39+
crypto.getRandomValues(bytes)
40+
}
2641
}
2742

2843
if (typeof cb === 'function') {

test.js

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
var test = require('tape')
22
var randomBytes = require('./')
3+
var MAX_BYTES = 65536
4+
var MAX_UINT32 = 4294967295
35

46
test('sync', function (t) {
5-
t.plan(4)
7+
t.plan(9)
68
t.equals(randomBytes(0).length, 0, 'len: ' + 0)
79
t.equals(randomBytes(3).length, 3, 'len: ' + 3)
810
t.equals(randomBytes(30).length, 30, 'len: ' + 30)
911
t.equals(randomBytes(300).length, 300, 'len: ' + 300)
12+
t.equals(randomBytes(17 + MAX_BYTES).length, 17 + MAX_BYTES, 'len: ' + 17 + MAX_BYTES)
13+
t.equals(randomBytes(MAX_BYTES * 100).length, MAX_BYTES * 100, 'len: ' + MAX_BYTES * 100)
14+
t.throws(function () {
15+
randomBytes(MAX_UINT32 + 1)
16+
})
17+
t.throws(function () {
18+
t.equals(randomBytes(-1))
19+
})
20+
t.throws(function () {
21+
t.equals(randomBytes('hello'))
22+
})
1023
})
1124

1225
test('async', function (t) {
13-
t.plan(4)
26+
t.plan(9)
1427

1528
randomBytes(0, function (err, resp) {
1629
if (err) throw err
@@ -35,22 +48,34 @@ test('async', function (t) {
3548

3649
t.equals(resp.length, 300, 'len: ' + 300)
3750
})
38-
})
3951

40-
if (process.browser) {
41-
test('requesting to much throws', function (t) {
42-
t.plan(1)
43-
t.throws(function () {
44-
randomBytes(65537)
52+
randomBytes(17 + MAX_BYTES, function (err, resp) {
53+
if (err) throw err
54+
55+
t.equals(resp.length, 17 + MAX_BYTES, 'len: ' + 17 + MAX_BYTES)
56+
})
57+
58+
randomBytes(MAX_BYTES * 100, function (err, resp) {
59+
if (err) throw err
60+
61+
t.equals(resp.length, MAX_BYTES * 100, 'len: ' + MAX_BYTES * 100)
62+
})
63+
64+
t.throws(function () {
65+
randomBytes(MAX_UINT32 + 1, function () {
66+
t.ok(false, 'should not get here')
4567
})
4668
})
4769

48-
test('requesting to much throws async', function (t) {
49-
t.plan(1)
50-
t.throws(function () {
51-
randomBytes(65537, function () {
52-
t.ok(false, 'should not get here')
53-
})
70+
t.throws(function () {
71+
randomBytes(-1, function () {
72+
t.ok(false, 'should not get here')
5473
})
5574
})
56-
}
75+
76+
t.throws(function () {
77+
randomBytes('hello', function () {
78+
t.ok(false, 'should not get here')
79+
})
80+
})
81+
})

0 commit comments

Comments
 (0)