Skip to content

Commit

Permalink
Improve randomness of UUIDs.
Browse files Browse the repository at this point in the history
  • Loading branch information
NeilFraser committed Nov 25, 2015
1 parent a239c72 commit e5dfdf4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
41 changes: 30 additions & 11 deletions core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

9 changes: 6 additions & 3 deletions tests/jsunit/blockly_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit e5dfdf4

Please sign in to comment.