Skip to content

Commit 2c32b42

Browse files
Jake ChampionJakeChampion
authored andcommitted
feat: add crypto.randomUUID function
1 parent 6173427 commit 2c32b42

File tree

5 files changed

+144
-1
lines changed

5 files changed

+144
-1
lines changed

c-dependencies/js-compute-runtime/builtins/crypto.cpp

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,115 @@ bool Crypto::get_random_values(JSContext *cx, unsigned argc, JS::Value *vp) {
5252
return true;
5353
}
5454

55+
/*
56+
FROM RFC 4122
57+
The formal definition of the UUID string representation is
58+
provided by the following ABNF [7]:
59+
60+
UUID = time-low "-" time-mid "-"
61+
time-high-and-version "-"
62+
clock-seq-and-reserved
63+
clock-seq-low "-" node
64+
time-low = 4hexOctet
65+
time-mid = 2hexOctet
66+
time-high-and-version = 2hexOctet
67+
clock-seq-and-reserved = hexOctet
68+
clock-seq-low = hexOctet
69+
node = 6hexOctet
70+
hexOctet = hexDigit hexDigit
71+
hexDigit =
72+
"0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
73+
"a" / "b" / "c" / "d" / "e" / "f" /
74+
"A" / "B" / "C" / "D" / "E" / "F"
75+
*/
76+
struct UUID {
77+
uint32_t time_low;
78+
uint16_t time_mid;
79+
uint16_t time_high_and_version;
80+
uint8_t clock_seq_and_reserved;
81+
uint8_t clock_seq_low;
82+
uint8_t node[6];
83+
};
84+
85+
/*
86+
FROM RFC 4122
87+
4.1.3. Version
88+
89+
The version number is in the most significant 4 bits of the time
90+
stamp (bits 4 through 7 of the time_hi_and_version field).
91+
92+
The following table lists the currently-defined versions for this
93+
UUID variant.
94+
95+
Msb0 Msb1 Msb2 Msb3 Version Description
96+
97+
0 0 0 1 1 The time-based version
98+
specified in this document.
99+
100+
0 0 1 0 2 DCE Security version, with
101+
embedded POSIX UIDs.
102+
103+
0 0 1 1 3 The name-based version
104+
specified in this document
105+
that uses MD5 hashing.
106+
107+
0 1 0 0 4 The randomly or pseudo-
108+
randomly generated version
109+
specified in this document.
110+
111+
0 1 0 1 5 The name-based version
112+
specified in this document
113+
that uses SHA-1 hashing.
114+
*/
115+
/*
116+
FROM RFC 4122
117+
The version 4 UUID is meant for generating UUIDs from truly-random or
118+
pseudo-random numbers.
119+
120+
The algorithm is as follows:
121+
122+
Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one,
123+
respectively.
124+
125+
Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the
126+
4-bit version number from Section 4.1.3.
127+
128+
Set all the other bits to randomly (or pseudo-randomly) chosen values.
129+
*/
130+
bool Crypto::random_uuid(JSContext *cx, unsigned argc, JS::Value *vp) {
131+
JS::CallArgs args = CallArgsFromVp(argc, vp);
132+
UUID id;
133+
random_get(reinterpret_cast<int32_t>(&id), sizeof(id));
134+
135+
// Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and
136+
// one, respectively.
137+
id.clock_seq_and_reserved &= 0x3f;
138+
id.clock_seq_and_reserved |= 0x80;
139+
// Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the
140+
// 4-bit version number from Section 4.1.3.
141+
id.time_high_and_version &= 0x0fff;
142+
id.time_high_and_version |= 0x4000;
143+
144+
const char *fmt = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
145+
char buf[80];
146+
std::snprintf(buf, sizeof(buf) - 1, fmt, id.time_low, (uint32_t)id.time_mid,
147+
(uint32_t)id.time_high_and_version, (uint32_t)id.clock_seq_and_reserved,
148+
(uint32_t)id.clock_seq_low, (uint32_t)id.node[0], (uint32_t)id.node[1],
149+
(uint32_t)id.node[2], (uint32_t)id.node[3], (uint32_t)id.node[4],
150+
(uint32_t)id.node[5]);
151+
JS::RootedString str(cx, JS_NewStringCopyN(cx, buf, 36));
152+
153+
if (!str) {
154+
return false;
155+
}
156+
157+
args.rval().setString(str);
158+
return true;
159+
}
160+
55161
const JSFunctionSpec Crypto::methods[] = {
56-
JS_FN("getRandomValues", get_random_values, 1, JSPROP_ENUMERATE), JS_FS_END};
162+
JS_FN("getRandomValues", get_random_values, 1, JSPROP_ENUMERATE),
163+
JS_FN("randomUUID", random_uuid, 0, JSPROP_ENUMERATE), JS_FS_END};
57164

58165
const JSPropertySpec Crypto::properties[] = {JS_PS_END};
59166

c-dependencies/js-compute-runtime/builtins/crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Crypto : public BuiltinNoConstructor<Crypto> {
1414
static const JSPropertySpec properties[];
1515

1616
static bool get_random_values(JSContext *cx, unsigned argc, JS::Value *vp);
17+
static bool random_uuid(JSContext *cx, unsigned argc, JS::Value *vp);
1718
static bool create(JSContext *cx, JS::HandleObject global);
1819
};
1920

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
hide_title: false
3+
hide_table_of_contents: false
4+
pagination_next: null
5+
pagination_prev: null
6+
---
7+
# Crypto.randomUUID()
8+
9+
The **`randomUUID()`** method is used to generate a v4 [UUID](https://developer.mozilla.org/en-US/docs/Glossary/UUID) using a cryptographically secure random number generator.
10+
11+
## Syntax
12+
13+
```js
14+
randomUUID()
15+
```
16+
17+
### Parameters
18+
19+
None.
20+
21+
### Return value
22+
23+
A string containing a randomly generated, 36 character long v4 UUID.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"namespace format": {
3+
"status": "PASS"
4+
},
5+
"version set": {
6+
"status": "PASS"
7+
},
8+
"variant set": {
9+
"status": "PASS"
10+
}
11+
}

tests/wpt-harness/tests.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
"url/urlsearchparams-sort.any.js",
177177
"url/urlsearchparams-stringifier.any.js",
178178
"WebCryptoAPI/getRandomValues.any.js",
179+
"WebCryptoAPI/randomUUID.https.any.js",
179180
"html/webappapis/structured-clone/structured-clone.any.js",
180181
"html/webappapis/timers/clearinterval-from-callback.any.js",
181182
"html/webappapis/timers/cleartimeout-clearinterval.any.js",

0 commit comments

Comments
 (0)