@@ -52,8 +52,115 @@ bool Crypto::get_random_values(JSContext *cx, unsigned argc, JS::Value *vp) {
52
52
return true ;
53
53
}
54
54
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
+
55
161
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};
57
164
58
165
const JSPropertySpec Crypto::properties[] = {JS_PS_END};
59
166
0 commit comments