Skip to content

Commit d7cdac0

Browse files
committed
fix(#48): Math.random() impl for randomId()
1 parent 96b2f2a commit d7cdac0

File tree

5 files changed

+65
-48
lines changed

5 files changed

+65
-48
lines changed

.changeset/smooth-maps-attack.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sv443-network/userutils": minor
3+
---
4+
5+
Made `randomId()` default to using Math.random() and added the parameter `enhancedEntropy` to revert back to the much slower but also much more entropic implementation

README-summary.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ or view the documentation of previous major releases:
3939
- [`clamp()`](https://github.com/Sv443-Network/UserUtils#clamp) - constrain a number between a min and max value
4040
- [`mapRange()`](https://github.com/Sv443-Network/UserUtils#maprange) - map a number from one range to the same spot in another range
4141
- [`randRange()`](https://github.com/Sv443-Network/UserUtils#randrange) - generate a random number between a min and max boundary
42-
- [`randomId()`](https://github.com/Sv443-Network/UserUtils#randomid) - generate a random ID of a given length and radix
4342
- **Misc:**
4443
- [`DataStore`](https://github.com/Sv443-Network/UserUtils#datastore) - class that manages a hybrid sync & async persistent JSON database, including data migration
4544
- [`DataStoreSerializer`](https://github.com/Sv443-Network/UserUtils#datastoreserializer) - class for importing & exporting data of multiple DataStore instances, including compression, checksumming and running migrations
@@ -51,6 +50,7 @@ or view the documentation of previous major releases:
5150
- [`compress()`](https://github.com/Sv443-Network/UserUtils#compress) - compress a string with Gzip or Deflate
5251
- [`decompress()`](https://github.com/Sv443-Network/UserUtils#decompress) - decompress a previously compressed string
5352
- [`computeHash()`](https://github.com/Sv443-Network/UserUtils#computehash) - compute the hash / checksum of a string or ArrayBuffer
53+
- [`randomId()`](https://github.com/Sv443-Network/UserUtils#randomid) - generate a random ID of a given length and radix
5454
- **Arrays:**
5555
- [`randomItem()`](https://github.com/Sv443-Network/UserUtils#randomitem) - returns a random item from an array
5656
- [`randomItemIndex()`](https://github.com/Sv443-Network/UserUtils#randomitemindex) - returns a tuple of a random item and its index from an array

README.md

+34-31
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ View the documentation of previous major releases:
4141
- [`clamp()`](#clamp) - constrain a number between a min and max value
4242
- [`mapRange()`](#maprange) - map a number from one range to the same spot in another range
4343
- [`randRange()`](#randrange) - generate a random number between a min and max boundary
44-
- [`randomId()`](#randomid) - generate a random ID of a given length and radix
4544
- [**Misc:**](#misc)
4645
- [`DataStore`](#datastore) - class that manages a hybrid sync & async persistent JSON database, including data migration
4746
- [`DataStoreSerializer`](#datastoreserializer) - class for importing & exporting data of multiple DataStore instances, including compression, checksumming and running migrations
@@ -53,6 +52,7 @@ View the documentation of previous major releases:
5352
- [`compress()`](#compress) - compress a string with Gzip or Deflate
5453
- [`decompress()`](#decompress) - decompress a previously compressed string
5554
- [`computeHash()`](#computehash) - compute the hash / checksum of a string or ArrayBuffer
55+
- [`randomId()`](#randomid) - generate a random ID of a given length and radix
5656
- [**Arrays:**](#arrays)
5757
- [`randomItem()`](#randomitem) - returns a random item from an array
5858
- [`randomItemIndex()`](#randomitemindex) - returns a tuple of a random item and its index from an array
@@ -928,36 +928,6 @@ randRange(10); // 7
928928

929929
</details>
930930

931-
<br>
932-
933-
### randomId()
934-
Usage:
935-
```ts
936-
randomId(length?: number, radix?: number): string
937-
```
938-
939-
Generates a cryptographically strong random ID of a given length and [radix (base).](https://en.wikipedia.org/wiki/Radix)
940-
Uses the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for generating the random numbers.
941-
⚠️ This is not intended for generating encryption keys, only for generating IDs with a decent amount of entropy!
942-
943-
The default length is 16 and the default radix is 16 (hexadecimal).
944-
You may change the radix to get digits from different numerical systems.
945-
Use 2 for binary, 8 for octal, 10 for decimal, 16 for hexadecimal and 36 for alphanumeric.
946-
947-
<details><summary><b>Example - click to view</b></summary>
948-
949-
```ts
950-
import { randomId } from "@sv443-network/userutils";
951-
952-
randomId(); // "1bda419a73629d4f" (length 16, radix 16)
953-
randomId(10); // "f86cd354a4" (length 10, radix 16)
954-
randomId(10, 2); // "1010001101" (length 10, radix 2)
955-
randomId(10, 10); // "0183428506" (length 10, radix 10)
956-
randomId(10, 36); // "z46jfpa37r" (length 10, radix 36)
957-
```
958-
959-
</details>
960-
961931
<br><br>
962932

963933
<!-- #SECTION Misc -->
@@ -1526,6 +1496,39 @@ run();
15261496
```
15271497
</details>
15281498

1499+
<br>
1500+
1501+
### randomId()
1502+
Usage:
1503+
```ts
1504+
randomId(length?: number, radix?: number, enhancedEntropy?: boolean): string
1505+
```
1506+
1507+
Generates a random ID of a given length and [radix (base).](https://en.wikipedia.org/wiki/Radix)
1508+
1509+
The default length is 16 and the default radix is 16 (hexadecimal).
1510+
You may change the radix to get digits from different numerical systems.
1511+
Use 2 for binary, 8 for octal, 10 for decimal, 16 for hexadecimal and 36 for alphanumeric.
1512+
1513+
If `enhancedEntropy` is set to true (false by default), the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) is used for generating the random numbers.
1514+
Note that this takes MUCH longer, but the generated IDs will have a higher entropy.
1515+
1516+
⚠️ Not suitable for generating anything related to cryptography! Use [SubtleCrypto's `generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that instead.
1517+
1518+
<details><summary><b>Example - click to view</b></summary>
1519+
1520+
```ts
1521+
import { randomId } from "@sv443-network/userutils";
1522+
1523+
randomId(); // "1bda419a73629d4f" (length 16, radix 16)
1524+
randomId(10); // "f86cd354a4" (length 10, radix 16)
1525+
randomId(10, 2); // "1010001101" (length 10, radix 2)
1526+
randomId(10, 10); // "0183428506" (length 10, radix 10)
1527+
randomId(10, 36); // "z46jfpa37r" (length 10, radix 36)
1528+
```
1529+
1530+
</details>
1531+
15291532
<br><br>
15301533

15311534
<!-- #SECTION Arrays -->

lib/math.ts

-16
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,3 @@ export function randRange(...args: number[]): number {
4444

4545
return Math.floor(Math.random() * (max - min + 1)) + min;
4646
}
47-
48-
/**
49-
* Generates a random ID with the specified length and radix (16 characters and hexadecimal by default)
50-
* Uses [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for better cryptographic randomness
51-
* ⚠️ Not suitable for generating encryption keys! Use [`crypto.subtle.generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that.
52-
* @param length The length of the ID to generate (defaults to 16)
53-
* @param radix The [radix](https://en.wikipedia.org/wiki/Radix) of each digit (defaults to 16 which is hexadecimal. Use 2 for binary, 10 for decimal, 36 for alphanumeric, etc.)
54-
*/
55-
export function randomId(length = 16, radix = 16): string {
56-
const arr = new Uint8Array(length);
57-
crypto.getRandomValues(arr);
58-
return Array.from(
59-
arr,
60-
(v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1),
61-
).join("");
62-
}

lib/misc.ts

+25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getUnsafeWindow } from "./dom.js";
2+
import { mapRange } from "./math.js";
23
import type { Stringifiable } from "./types.js";
34

45
/**
@@ -158,3 +159,27 @@ export async function computeHash(input: string | ArrayBuffer, algorithm = "SHA-
158159

159160
return hashHex;
160161
}
162+
163+
/**
164+
* Generates a random ID with the specified length and radix (16 characters and hexadecimal by default)
165+
*
166+
* ⚠️ Not suitable for generating anything related to cryptography! Use [SubtleCrypto's `generateKey()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey) for that instead.
167+
* @param length The length of the ID to generate (defaults to 16)
168+
* @param radix The [radix](https://en.wikipedia.org/wiki/Radix) of each digit (defaults to 16 which is hexadecimal. Use 2 for binary, 10 for decimal, 36 for alphanumeric, etc.)
169+
* @param enhancedEntropy If set to true, uses [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) for better cryptographic randomness (this also makes it take MUCH longer to generate)
170+
*/
171+
export function randomId(length = 16, radix = 16, enhancedEntropy = false): string {
172+
if(enhancedEntropy) {
173+
const arr = new Uint8Array(length);
174+
crypto.getRandomValues(arr);
175+
return Array.from(
176+
arr,
177+
(v) => mapRange(v, 0, 255, 0, radix).toString(radix).substring(0, 1),
178+
).join("");
179+
}
180+
181+
return Array.from(
182+
{ length },
183+
() => Math.floor(Math.random() * radix).toString(radix),
184+
).join("");
185+
}

0 commit comments

Comments
 (0)