Skip to content

Commit

Permalink
Fix
Browse files Browse the repository at this point in the history
Signed-off-by: Richie Bendall <richiebendall@gmail.com>
  • Loading branch information
Richienb committed Apr 21, 2022
1 parent 2326ee0 commit e92d4e1
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 30 deletions.
27 changes: 9 additions & 18 deletions browser.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
/* eslint-env browser */
import {createStringGenerator, createAsyncStringGenerator} from './core.js';

const toHex = uInt8Array => uInt8Array.map(byte => byte.toString(16).padStart(2, '0')).join('');

const decoder = new TextDecoder('utf8');
const toBase64 = uInt8Array => btoa(decoder.decode(uInt8Array));
const toHex = uInt8Array => [...uInt8Array].map(byte => byte.toString(16).padStart(2, '0')).join('');
const toBase64 = uInt8Array => btoa(String.fromCharCode(...uInt8Array));

// `crypto.getRandomValues` throws an error if too much entropy is requested at once. (https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions)
const maxEntropy = 65_536;

function getRandomValues(byteLength) {
const generatedBytes = [];

while (byteLength > 0) {
const bytesToGenerate = Math.min(byteLength, maxEntropy);
generatedBytes.push(crypto.getRandomValues(new Uint8Array({length: bytesToGenerate})));
byteLength -= bytesToGenerate;
}

const result = new Uint8Array(generatedBytes.reduce((sum, {byteLength}) => sum + byteLength, 0));
let currentIndex = 0;
const generatedBytes = new Uint8Array(byteLength);

for (const bytes of generatedBytes) {
result.set(bytes, currentIndex);
currentIndex += bytes.byteLength;
for (let totalGeneratedBytes = 0; totalGeneratedBytes < byteLength; totalGeneratedBytes += maxEntropy) {
generatedBytes.set(
crypto.getRandomValues(new Uint8Array(Math.min(maxEntropy, byteLength - totalGeneratedBytes))),
totalGeneratedBytes,
);
}

return result;
return generatedBytes;
}

function specialRandomBytes(byteLength, type, length) {
Expand Down
6 changes: 4 additions & 2 deletions core.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const distinguishableCharacters = [...'CDEHKMPRTUWXY012458'];
const asciiPrintableCharacters = [...'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'];
const alphanumericCharacters = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'];

const readUInt16LE = (uInt8Array, offset) => uInt8Array[offset] + (uInt8Array[offset + 1] * (2 ** 8));

const generateForCustomCharacters = (length, characters, randomBytes) => {
// Generating entropy is faster than complex math operations, so we use the simplest way
const characterCount = characters.length;
Expand All @@ -17,7 +19,7 @@ const generateForCustomCharacters = (length, characters, randomBytes) => {
let entropyPosition = 0;

while (entropyPosition < entropyLength && stringLength < length) {
const entropyValue = entropy.readUInt16LE(entropyPosition);
const entropyValue = readUInt16LE(entropy, entropyPosition);
entropyPosition += 2;
if (entropyValue > maxValidSelector) { // Skip values which will ruin distribution when using modular division
continue;
Expand All @@ -44,7 +46,7 @@ const generateForCustomCharactersAsync = async (length, characters, randomBytesA
let entropyPosition = 0;

while (entropyPosition < entropyLength && stringLength < length) {
const entropyValue = entropy.readUInt16LE(entropyPosition);
const entropyValue = readUInt16LE(entropy, entropyPosition);
entropyPosition += 2;
if (entropyValue > maxValidSelector) { // Skip values which will ruin distribution when using modular division
continue;
Expand Down
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {createStringGenerator, createAsyncStringGenerator} from './core.js';

const randomBytesAsync = promisify(crypto.randomBytes);

export default createStringGenerator((byteLength, type, length) => crypto.randomBytes(byteLength).toString(type).slice(0, length), crypto.randomBytes);
export default createStringGenerator((byteLength, type, length) => crypto.randomBytes(byteLength).toString(type).slice(0, length), size => new Uint8Array(crypto.randomBytes(size)));
export const cryptoRandomStringAsync = createAsyncStringGenerator(async (byteLength, type, length) => {
const buffer = await randomBytesAsync(byteLength);
return buffer.toString(type).slice(0, length);
}, randomBytesAsync);
}, async size => new Uint8Array(await randomBytesAsync(size)));
12 changes: 4 additions & 8 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,11 @@ function runTests(test) {
test.run();
}

const nodeTests = suite('Node.js', {
runTests(suite('Node.js', {
cryptoRandomString: nodeCryptoRandomString,
cryptoRandomStringAsync: nodeCryptoRandomStringAsync,
});

const browserTests = suite('Browser', {
}));
runTests(suite('Browser', {
cryptoRandomString: browserCryptoRandomString,
cryptoRandomStringAsync: browserCryptoRandomStringAsync,
});

runTests(nodeTests);
runTests(browserTests);
}));

0 comments on commit e92d4e1

Please sign in to comment.