Skip to content

Commit

Permalink
feat(client,utils) refactor random char generation
Browse files Browse the repository at this point in the history
- Generate actually unique GUIDs
- Use a better random character generator
- Use a better alphabet for join codes which eliminates ambiguity
  • Loading branch information
saghul committed Aug 14, 2024
1 parent ecde249 commit 58bd408
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 42 deletions.
40 changes: 2 additions & 38 deletions spot-client/src/common/utils/cryptography.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,9 @@
/**
* Generates a random 8 character long string.
*
* @returns {string}
*/
export function generate8Characters() {
const buf = new Uint16Array(2);

window.crypto.getRandomValues(buf);

return `${s4(buf[0])}${s4(buf[1])}`;
}

/**
* Generate a likely-to-be-unique guid.
* Generate a GUID.
*
* @private
* @returns {string} The generated string.
*/
export function generateGuid() {
const buf = new Uint16Array(8);

window.crypto.getRandomValues(buf);

return `${s4(buf[0])}${s4(buf[1])}-${s4(buf[2])}-${s4(buf[3])}-${
s4(buf[4])}-${s4(buf[5])}${s4(buf[6])}${s4(buf[7])}`;
}

/**
* Converts the passed in number to a string and ensure it is at least 4
* characters in length, prepending 0's as needed.
*
* @param {number} num - The number to pad and convert to a string.
* @private
* @returns {string} - The number converted to a string.
*/
function s4(num) {
let ret = num.toString(16);

while (ret.length < 4) {
ret = `0${ret}`;
}

return ret;
return window.crypto.randomUUID();
}
66 changes: 62 additions & 4 deletions spot-client/src/common/utils/random.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,70 @@
class RandomPool {

Check failure on line 1 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Missing JSDoc comment
SIZE = 256;

constructor() {

Check failure on line 4 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Missing JSDoc comment
this._rArray = new Uint8Array(this.SIZE);
this._idx = this.SIZE; // Fill the pool on first use.
}

getValue() {

Check failure on line 9 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Missing JSDoc comment
if (this._idx > this.SIZE - 1) {
// Fill the pool.
globalThis.crypto.getRandomValues(this._rArray);

Check failure on line 12 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

'globalThis' is not defined
this._idx = 0;
}

return this._rArray[this._idx++];
}
}

const pool = new RandomPool();

/**
* Choose `num` elements from `seq`, randomly.
*
* @param {string} seq - Sequence of characters, the alphabet.
* @param {number} num - The amount of characters from the alphabet we want.
* @returns {string}
*/
function randomChoice(seq, num) {
const x = seq.length - 1;
const r = new Array(num);

Check failure on line 31 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Multiple spaces found before 'new'

while (num--) {

Check failure on line 33 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Assignment to function parameter 'num'
// Make sure the random value is in our alphabet's range.
const idx = pool.getValue() & x;

Check failure on line 35 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Unexpected use of '&'

r.push(seq[idx]);
}

return r.join('');
}

/**
* This alphabet removes all potential ambiguous symbols, so it's well suited for a code.

Check failure on line 44 in spot-client/src/common/utils/random.js

View workflow job for this annotation

GitHub Actions / Unit-tests

Trailing spaces not allowed
*/
const BASE32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';

/**
* A method to generate a random string, intended to be used to create a random join code.
*
* @param {number} length - The desired length of the random string.
* @returns {string}
*/
export function generateRandomString(length) {
// XXX the method may not always give desired length above 9
return Math.random()
.toString(36)
.slice(2, 2 + length);
return randomChoice(BASE32, length);
}

/**
* This alphabet is similar to BASE32 above, but includes lowercase characters too.
*/
const BASE58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';

/**
* Generates a random 8 character long string.
*
* @returns {string}
*/
export function generate8Characters() {
return randomChoice(BASE58, 8);
}

0 comments on commit 58bd408

Please sign in to comment.