diff --git a/lib/crypto-platform.browser.js b/lib/crypto-platform.browser.js
index d6bf688..3edc3f0 100644
--- a/lib/crypto-platform.browser.js
+++ b/lib/crypto-platform.browser.js
@@ -1,6 +1,5 @@
/**
* Browser Bitmessage crypto implementation.
- *
* Documentation:
* Browsers support:
* Blink implementation details:
@@ -34,3 +33,9 @@ exports.ripemd160 = function(buf) {
// so use module.
return Promise.resolve(ripemd160(buf));
};
+
+exports.randomBytes = function(size) {
+ var arr = new Uint8Array(size);
+ window.crypto.getRandomValues(arr);
+ return new Buffer(arr);
+};
diff --git a/lib/crypto-platform.js b/lib/crypto-platform.js
index 47eaf49..81ae9c0 100644
--- a/lib/crypto-platform.js
+++ b/lib/crypto-platform.js
@@ -25,3 +25,12 @@ exports.ripemd160 = function(buf) {
hash.update(buf);
return Promise.resolve(hash.digest());
};
+
+/**
+ * Generate cryptographically strong pseudo-random data.
+ * @param {number} size - Number of bytes
+ * @return {Buffer} Buffer with random data.
+ */
+exports.randomBytes = function(size) {
+ return crypto.randomBytes(size);
+};
diff --git a/lib/crypto.js b/lib/crypto.js
index c77f550..cbda353 100644
--- a/lib/crypto.js
+++ b/lib/crypto.js
@@ -7,6 +7,7 @@
"use strict";
var cryptoPlatform = require("./crypto-platform");
+
Object.keys(cryptoPlatform).forEach(function(key) {
exports[key] = cryptoPlatform[key];
});
diff --git a/test.js b/test.js
index dd25aa2..5ffd7ec 100644
--- a/test.js
+++ b/test.js
@@ -56,6 +56,29 @@ describe("Crypto", function() {
expect(res.toString("hex")).to.equal("5e52fee47e6b070565f74372468cdc699de89107");
});
});
+
+ it("should implement cryptographically secure PRNG", function() {
+ var size = 100;
+ var rnd = bmcrypto.randomBytes(size);
+ expect(Buffer.isBuffer(rnd)).to.be.true;
+ expect(rnd.length).to.equal(size);
+ // Very simple statistical test.
+ var bytes = {};
+ var sum = 0;
+ var value;
+ for (var i = 0; i < size; i++) {
+ value = rnd[i];
+ sum += value;
+ if (!bytes[value]) {
+ bytes[value] = 0;
+ }
+ bytes[value]++;
+ expect(bytes[value]).to.be.below(5);
+ }
+ // Ideal sum = (255 / 2) * size = 12750
+ expect(sum).to.be.above(10000);
+ expect(sum).to.be.below(15000);
+ });
});
describe("Address", function() {