Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.

Commit 70aeaa1

Browse files
committed
Merge pull request #81 from runtimejs/tmp-rng
Random API and RNG
2 parents 3b3daa3 + dbd2508 commit 70aeaa1

13 files changed

Lines changed: 657 additions & 0 deletions

File tree

js/.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
deps/

js/core/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ console.log = isolate.log;
1919
var resources = require('./resources');
2020
require('./polyfill');
2121

22+
var random = require('./random');
2223
var keyboard = require('./keyboard');
2324
var ps2 = require('./ps2');
2425
var pci = require('./pci');
2526
var net = require('./net');
2627
var stdio = require('./stdio');
2728

2829
function Runtime() {
30+
this.random = random;
2931
this.keyboard = keyboard;
3032
this.pci = pci;
3133
this.ps2 = ps2;

js/core/random/entropy-source.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
class EntropySource {
18+
constructor(name) {
19+
this._name = name || '';
20+
this.ongetbytes = null;
21+
}
22+
23+
getName() {
24+
return this._name;
25+
}
26+
27+
/**
28+
* Request randomness from this entropy source
29+
*/
30+
getBytes(u8, cb) {
31+
if (!this.ongetbytes) {
32+
throw new Error('entropy source was not initialized');
33+
}
34+
35+
this.ongetbytes(u8, cb);
36+
}
37+
}
38+
39+
module.exports = EntropySource;

js/core/random/index.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2015 runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
var isaac = require('./isaac-wrapper');
17+
var EntropySource = require('./entropy-source');
18+
var sources = require('./sources');
19+
var typeutils = require('typeutils');
20+
var getDefaultSource = sources.getDefaultSource;
21+
require('./js-random-source');
22+
23+
exports.EntropySource = EntropySource;
24+
exports.addEntropySource = sources.addEntropySource;
25+
26+
/**
27+
* Request random bytes from the best available entropy source. This
28+
* function is asynchronous bacause it might take some time to gather
29+
* enough entropy from the source. This might use /dev/random as a backend
30+
* in KVM and might be extremely slow depending on the buffer size and
31+
* the amount of available entropy.
32+
*
33+
* @param {number|Uint8Array} value Number of bytes to request or buffer to fill
34+
* @param {function} cb Callback with the resulting Uint8Array buffer argument
35+
*/
36+
exports.getTrueRandomValues = function(value, cb) {
37+
var u8 = null;
38+
if (typeutils.isNumber(value)) {
39+
u8 = new Uint8Array(value);
40+
}
41+
42+
if (value instanceof Uint8Array) {
43+
u8 = value;
44+
}
45+
46+
if (!u8) {
47+
throw new Error('getTrueRandomValues: argument 0 is not a number or Uint8Array');
48+
}
49+
50+
if (u8.length === 0) {
51+
throw new Error('getTrueRandomValues: buffer length must be greater than 0');
52+
}
53+
54+
if (!typeutils.isFunction(cb)) {
55+
throw new Error('getTrueRandomValues: argument 1 is not a function');
56+
}
57+
58+
var defaultSource = getDefaultSource();
59+
if (!defaultSource) {
60+
throw new Error('getTrueRandomValues: no entropy source available');
61+
}
62+
63+
defaultSource.getBytes(u8, function() {
64+
isaac.seed(u8);
65+
cb(u8);
66+
});
67+
};
68+
69+
/**
70+
* Request random bytes from the CSPRNG seeded with enough entropy.
71+
*
72+
* @param {number|Uint8Array} value Number of bytes to request or buffer to fill
73+
* @return {Uint8Array} Buffer filled with random data
74+
*/
75+
exports.getRandomValues = function(value) {
76+
var u8 = null;
77+
if (typeutils.isNumber(value)) {
78+
u8 = new Uint8Array(value);
79+
}
80+
81+
if (value instanceof Uint8Array) {
82+
u8 = value;
83+
}
84+
85+
if (!u8) {
86+
throw new Error('getRandomValues: argument 0 is not a number or Uint8Array');
87+
}
88+
89+
if (u8.length === 0) {
90+
throw new Error('getRandomValues: buffer length must be greater than 0');
91+
}
92+
93+
for (var i = 0; i < u8.length; i++) {
94+
u8[i] = isaac.getByte();
95+
}
96+
97+
return u8;
98+
};

js/core/random/isaac-wrapper.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2015 runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
var isaac = require('../../deps/isaac/isaac');
18+
19+
// isaac.js returns crazy numbers, both positive and negative.
20+
// This function is called on an isaac.rand() call,
21+
// It gets the number to qualify for all of the following:
22+
// * Positive,
23+
// * Whole number,
24+
// * 0 < n < 256
25+
// This ensures the numbers are similar to the numbers
26+
// generated by VirtioRNG.
27+
function isaacToUint8(n) {
28+
return (n >>> 0) & 0xff;
29+
}
30+
31+
exports.seed = isaac.seed;
32+
exports.getByte = function() {
33+
return isaacToUint8(isaac.rand());
34+
};

js/core/random/js-random-source.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2015 runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
var isaac = require('./isaac-wrapper');
17+
var EntropySource = require('./entropy-source');
18+
var sources = require('./sources');
19+
20+
// Low quality entropy source based on Math.random() seed
21+
// and isaac CSPRNG
22+
var source = new EntropySource('js-random');
23+
source.ongetbytes = function(u8, cb) {
24+
for (var i = 0; i < u8.length; i++) {
25+
u8[i] = isaac.getByte();
26+
}
27+
cb();
28+
};
29+
30+
sources.addEntropySource(source);

js/core/random/sources.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2015 runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
var isaac = require('./isaac-wrapper');
17+
var defaultSource = null;
18+
var availableSources = Object.create(null);
19+
20+
exports.addEntropySource = function(source) {
21+
availableSources[source.getName()] = source;
22+
23+
source.getBytes(new Uint8Array(8), function(u8) {
24+
isaac.seed(u8);
25+
console.log('[random] using entropy source', source.getName());
26+
});
27+
28+
// Set this source as the default one
29+
defaultSource = source;
30+
};
31+
32+
exports.getDefaultSource = function() {
33+
return defaultSource;
34+
};

js/deps/isaac/LICENSE.isaac

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2012 Yves-Marie K. Rinquin
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

0 commit comments

Comments
 (0)