-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(client,utils) refactor random char generation
- Generate actually unique GUIDs - Use a better random character generator - Use a better alphabet for join codes which eliminates ambiguity
- Loading branch information
Showing
2 changed files
with
64 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,70 @@ | ||
class RandomPool { | ||
SIZE = 256; | ||
|
||
constructor() { | ||
this._rArray = new Uint8Array(this.SIZE); | ||
this._idx = this.SIZE; // Fill the pool on first use. | ||
} | ||
|
||
getValue() { | ||
if (this._idx > this.SIZE - 1) { | ||
// Fill the pool. | ||
globalThis.crypto.getRandomValues(this._rArray); | ||
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); | ||
|
||
while (num--) { | ||
// Make sure the random value is in our alphabet's range. | ||
const idx = pool.getValue() & x; | ||
|
||
r.push(seq[idx]); | ||
} | ||
|
||
return r.join(''); | ||
} | ||
|
||
/** | ||
* This alphabet removes all potential ambiguous symbols, so it's well suited for a code. | ||
*/ | ||
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); | ||
} |