From e5dfdf46589cc833b3a910dffcfb3dec65886f4f Mon Sep 17 00:00:00 2001 From: Neil Fraser Date: Tue, 24 Nov 2015 19:16:01 -0800 Subject: [PATCH] Improve randomness of UUIDs. --- core/utils.js | 41 ++++++++++++++++++++++++++---------- tests/jsunit/blockly_test.js | 9 +++++--- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/core/utils.js b/core/utils.js index 25d00438e..9d19a9fc2 100644 --- a/core/utils.js +++ b/core/utils.js @@ -552,24 +552,43 @@ Blockly.tokenizeInterpolation = function(message) { return tokens; }; -/** - * Legal characters for the unique ID. - * Should be all on a US keyboard. No XML special characters or control codes. - * @private - */ -Blockly.CHARACTER_SOUP_ = '!#$%()*+,-./:;=?@[]^_`{|}~' + - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - /** * Generate a unique ID. This should be globally unique. * 88 characters ^ 20 length ≈ 129 bits (one bit better than a UUID). * @return {string} */ Blockly.genUid = function() { + var length = 20; + var soupLength = Blockly.genUid.soup_.length; var id = []; - for (var i = 0; i < 20; i++) { - id[i] = Blockly.CHARACTER_SOUP_.charAt(Math.random() * - Blockly.CHARACTER_SOUP_.length); + if (Blockly.genUid.crypto_) { + // Cryptographically strong randomness is supported. + var array = new Uint32Array(length); + Blockly.genUid.crypto_.getRandomValues(array); + for (var i = 0; i < length; i++) { + id[i] = Blockly.genUid.soup_.charAt(array[i] % soupLength); + } + } else { + // Fall back to Math.random for IE 10. + for (var i = 0; i < length; i++) { + id[i] = Blockly.genUid.soup_.charAt(Math.random() * soupLength); + } } return id.join(''); }; + +/** + * Determine if window.crypto or global.crypto exists. + * @type {=RandomSource} + * @private + */ +Blockly.genUid.crypto_ = this.crypto; + +/** + * Legal characters for the unique ID. + * Should be all on a US keyboard. No XML special characters or control codes. + * @private + */ +Blockly.genUid.soup_ = '!#$%()*+,-./:;=?@[]^_`{|}~' + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + diff --git a/tests/jsunit/blockly_test.js b/tests/jsunit/blockly_test.js index 57348be99..88f0cebaa 100644 --- a/tests/jsunit/blockly_test.js +++ b/tests/jsunit/blockly_test.js @@ -20,9 +20,12 @@ 'use strict'; function test_genUid() { - var a = Blockly.genUid(); - var b = Blockly.genUid(); - assertFalse('UUID different', a == b); + var uuids = {}; + for (var i = 0; i < 1000; i++) { + var uuid = Blockly.genUid(); + assertFalse('UUID different: ' + uuid, uuid in uuids); + uuids[uuid] = true; + } } function test_addClass() {