Subversion Repositories uuid_mac_utils

Rev

Rev 88 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4. * UUID & MAC Utils
  5. * Copyright 2017 - 2024 Daniel Marschall, ViaThinkSoft
  6. * Version 2024-04-16
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. *     http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20.  
  21. include_once __DIR__.'/includes/uuid_utils.inc.php';
  22.  
  23. const AUTO_NEW_UUIDS = 15;
  24.  
  25. ?><!DOCTYPE html>
  26. <html lang="en">
  27.  
  28. <head>
  29.         <meta charset="iso-8859-1">
  30.         <link rel="stylesheet" type="text/css" href="style.css">
  31.         <title>UUID &amp; MAC Utils by Daniel Marschall</title>
  32.         <meta name=viewport content="width=device-width, initial-scale=1">
  33. </head>
  34.  
  35. <body>
  36.  
  37. <h1>UUID &amp; MAC Utils by Daniel Marschall</h1>
  38.  
  39. <p><a href="https://github.com/danielmarschall/uuid_mac_utils/">View the source code</a></p>
  40.  
  41. <h2>Overview</h2>
  42.  
  43. <ul>
  44.     <li><a href="#gen_uuid">Generate random and/or time-based UUIDs</a><ul>
  45.             <li><a href="#gen_uuidv7"><font color="green">New:</font> Generate Unix Epoch time-based (version 7) UUID</a></li>
  46.             <li><a href="#gen_uuidv6"><font color="green">New:</font> Generate reordered Gregorian time-based (version 6) UUID</a></li>
  47.             <li><a href="#gen_uuidv4">Generate random (version 4) UUID</a></li>
  48.             <li><a href="#gen_uuidv1">Generate Gregorian time-based (version 1) UUID</a></li>
  49.             <li><a href="#gen_uuidv8_sqlserver"><font color="green">New:</font> Generate SQL Server sortable time-based (version 8) UUID</a></li>
  50.         </ul></li>
  51.     <li><a href="#gen_other_uuid">Generate other UUID types</a><ul>
  52.             <li><a href="#gen_uuid_ncs">NCS (variant 0) UUID</a></li>
  53.             <li><a href="#gen_uuidv2">Generate DCE Security (version 2) UUID</a></li>
  54.             <li><a href="#gen_uuidv35">Generate name-based (version 3 / 5 / <font color="green">New: 8</font>) UUID</a></li>
  55.             <li><a href="#gen_uuidv8"><font color="green">New:</font> Generate Custom (version 8) UUID</a></li>
  56.         </ul></li>
  57.     <li><a href="#interpret_uuid">Interpret a UUID</a></li>
  58.     <li><a href="#interpret_mac">Interpret a MAC address (MAC / EUI / ELI / SAI / AAI)</a><ul>
  59.         <li><a href="#gen_aai">Generate an AAI</a></li>
  60.     </ul></li>
  61. </ul>
  62.  
  63. <h2 id="gen_uuid">Generate random and/or time-based UUIDs</h2>
  64.  
  65. <h3 id="gen_uuidv7"><font color="green">New:</font> Generate Unix Epoch time-based (version 7) UUID &#11088;</h3>
  66.  
  67. <p><i>A UUIDv7 measures time in the Unix Epoch with an accuracy
  68. between 1ms and 245ns, depending on how many bits are spent for the timestamp (48-60 bits).
  69. The rest of the UUID (62-74 bits) is filled with random data.
  70. The timestamp is at the front of the UUID, therefore the UUIDs are monotonically increasing,
  71. which is good for using them in database indexes.
  72. Since this UUID version does not contain a MAC address, it is also
  73. recommended due to the improved privacy.</i></p>
  74.  
  75. <script>
  76. function show_uuidv7_info() {
  77.         document.getElementById("uuidv7_info_button").style.display = "none";
  78.         document.getElementById("uuidv7_info").style.display = "block";
  79. }
  80. </script>
  81. <p><a id="uuidv7_info_button" href="javascript:show_uuidv7_info()">Show format</a>
  82. <pre id="uuidv7_info" style="display:none">Variant 1, Version 7 UUID:
  83. - 48 bit <abbr title="Count of 1ms intervals passed since 1 Jan 1970 00:00:00 GMT">Unix Time in milliseconds</abbr>
  84. -  4 bit Version (fix 0x7)
  85. - 12 bit Data
  86. -  2 bit Variant (fix 0b10)
  87. - 62 bit Data
  88.  
  89. Structure of data (74 bits):
  90. - OPTIONAL : Sub-millisecond timestamp fraction (0-12 bits)
  91. - OPTIONAL : Carefully seeded counter
  92. - Random generated bits for any remaining space
  93.  
  94. Time resolution for various sub-millisecond bits:
  95. <?php
  96. for ($num_ms_frac_bits=0; $num_ms_frac_bits<=12; $num_ms_frac_bits++) {
  97.         $resolution_ns = 1000000 / pow(2,$num_ms_frac_bits);
  98.         if ($resolution_ns >= 1000000) $resolution_ns_hf = ($resolution_ns/1000000)." ms";
  99.         else if ($resolution_ns >= 1000) $resolution_ns_hf = ($resolution_ns/1000)." &micro;s";
  100.         else $resolution_ns_hf = "$resolution_ns ns";
  101.         echo "$num_ms_frac_bits bits fraction = $resolution_ns_hf\n";
  102. }
  103. ?>
  104.  
  105. This implementation outputs:
  106. - 12 bits sub-millisecond timestamp (~245ns resolution)
  107. - no counter
  108. - 62 bits random data
  109. </pre></p>
  110.  
  111. <?php
  112. if (AUTO_NEW_UUIDS > 0) { /** @phpstan-ignore-line */
  113.         echo '<p>Here are '.AUTO_NEW_UUIDS.' UUIDs that were created just for you! (Reload the page to get more)</p>';
  114.  
  115.         echo '<pre>';
  116.         for ($i=0; $i<AUTO_NEW_UUIDS; $i++) {
  117.                 $uuid = gen_uuid_v7();
  118.                 echo '<a href="interprete_uuid.php?uuid='.$uuid.'">'.$uuid.'</a><br>';
  119.         }
  120.         echo '</pre>';
  121. }
  122. ?>
  123.  
  124. <form method="GET" action="interprete_uuid.php">
  125.     <input type="hidden" name="version" value="7">
  126.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create and display another UUID">
  127. </form>
  128.  
  129. <h3 id="gen_uuidv6"><font color="green">New:</font> Generate reordered Gregorian time-based (version 6) UUID &#9200;</h3>
  130.  
  131. <p><i>Like UUIDv1, this kind of UUID is made of the MAC address of the generating computer,
  132.         the time, and a clock sequence. However, the components in UUIDv6 are reordered (time is at the beginning),
  133.         so that UUIDs are monotonically increasing, which is good for using them in database indexes.</i></p>
  134.  
  135. <script>
  136. function show_uuidv6_info() {
  137.         document.getElementById("uuidv6_info_button").style.display = "none";
  138.         document.getElementById("uuidv6_info").style.display = "block";
  139. }
  140. </script>
  141. <p><a id="uuidv6_info_button" href="javascript:show_uuidv6_info()">Show format</a>
  142. <pre id="uuidv6_info" style="display:none">Variant 1, Version 6 UUID:
  143. - 48 bit High <abbr title="Count of 100ns intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  144. -  4 bit Version (fix 0x6)
  145. - 12 bit Low <abbr title="Count of 100ns intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  146. -  2 bit Variant (fix 0b10)
  147. -  6 bit Clock Sequence High
  148. -  8 bit Clock Sequence Low
  149. - 48 bit MAC Address</pre></p>
  150.  
  151. <?php
  152. if (AUTO_NEW_UUIDS > 0) { /** @phpstan-ignore-line */
  153.         echo '<p>Here are '.AUTO_NEW_UUIDS.' UUIDs that were created just for you! (Reload the page to get more)</p>';
  154.  
  155.         echo '<pre>';
  156.         for ($i=0; $i<AUTO_NEW_UUIDS; $i++) {
  157.                 $uuid = gen_uuid_v6();
  158.                 echo '<a href="interprete_uuid.php?uuid='.$uuid.'">'.$uuid.'</a><br>';
  159.         }
  160.         echo '</pre>';
  161. }
  162. ?>
  163.  
  164. <form method="GET" action="interprete_uuid.php">
  165.     <input type="hidden" name="version" value="6">
  166.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create and display another UUID">
  167. </form>
  168.  
  169. <h3 id="gen_uuidv4">Generate random (version 4) UUID &#x1F3B2;</h3>
  170.  
  171. <p><i>A UUIDv4 is made of 122 random&nbsp;bits. No other information is encoded in this kind of UUID.</i></p>
  172.  
  173. <script>
  174. function show_uuidv4_info() {
  175.         document.getElementById("uuidv4_info_button").style.display = "none";
  176.         document.getElementById("uuidv4_info").style.display = "block";
  177. }
  178. </script>
  179. <p><a id="uuidv4_info_button" href="javascript:show_uuidv4_info()">Show format</a>
  180. <pre id="uuidv4_info" style="display:none">Variant 1, Version 4 UUID:
  181. - 48 bit Random High
  182. -  4 bit Version (fix 0x4)
  183. - 12 bit Random Mid
  184. -  2 bit Variant (fix 0b10)
  185. - 62 bit Random Low</pre></p>
  186.  
  187. <?php
  188. if (AUTO_NEW_UUIDS > 0) { /** @phpstan-ignore-line */
  189.         echo '<p>Here are '.AUTO_NEW_UUIDS.' UUIDs that were created just for you! (Reload the page to get more)</p>';
  190.  
  191.         echo '<pre>';
  192.         for ($i=0; $i<AUTO_NEW_UUIDS; $i++) {
  193.                 $uuid = gen_uuid_v4();
  194.                 echo '<a href="interprete_uuid.php?uuid='.$uuid.'">'.$uuid.'</a><br>';
  195.         }
  196.         echo '</pre>';
  197. }
  198. ?>
  199.  
  200. <form method="GET" action="interprete_uuid.php">
  201.     <input type="hidden" name="version" value="4">
  202.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create and display another UUID">
  203. </form>
  204.  
  205. <h3 id="gen_uuidv1">Generate Gregorian time-based (version 1) UUID &#9200;</h3>
  206.  
  207. <p><i>A UUIDv1 is made of the MAC address of the generating computer,
  208. the time, and a clock sequence.</i></p>
  209.  
  210. <script>
  211. function show_uuidv1_info() {
  212.         document.getElementById("uuidv1_info_button").style.display = "none";
  213.         document.getElementById("uuidv1_info").style.display = "block";
  214. }
  215. </script>
  216. <p><a id="uuidv1_info_button" href="javascript:show_uuidv1_info()">Show format</a>
  217. <pre id="uuidv1_info" style="display:none">Variant 1, Version 1 UUID:
  218. - 32 bit Low <abbr title="Count of 100ns intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  219. - 16 bit Mid <abbr title="Count of 100ns intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  220. -  4 bit Version (fix 0x1)
  221. - 12 bit High <abbr title="Count of 100ns intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  222. -  2 bit Variant (fix 0b10)
  223. -  6 bit Clock Sequence High
  224. -  8 bit Clock Sequence Low
  225. - 48 bit MAC Address</pre></p>
  226.  
  227. <?php
  228. if (AUTO_NEW_UUIDS > 0) { /** @phpstan-ignore-line */
  229.     echo '<p>Here are '.AUTO_NEW_UUIDS.' UUIDs that were created just for you! (Reload the page to get more)</p>';
  230.  
  231.     echo '<pre>';
  232.     for ($i=0; $i<AUTO_NEW_UUIDS; $i++) {
  233.         $uuid = gen_uuid_v1();
  234.         echo '<a href="interprete_uuid.php?uuid='.$uuid.'">'.$uuid.'</a><br>';
  235.     }
  236.     echo '</pre>';
  237. }
  238. ?>
  239.  
  240. <form method="GET" action="interprete_uuid.php">
  241.     <input type="hidden" name="version" value="1">
  242.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create and display another UUID">
  243. </form>
  244.  
  245. <h3 id="gen_uuidv8_sqlserver">Generate SQL Server sortable time-based (version 8) UUID</h3>
  246.  
  247. <p><i>The sorting of UUIDs in SQL Server is rather confusing and incompatible with UUIDv6 and UUIDv7.<br>
  248. Therefore this method developed by <a href="https://www.hickelsoft.de/">HickelSOFT</a>
  249. generates UUIDs which are sortable by SQL Server.<br>
  250. They have a time resolution of 1 milliseconds combined with 16 bits of random data.</i><br>
  251. <a href="https://gist.github.com/danielmarschall/7fafd270a3bc107d38e8449ce7420c25">C# implementation</a> |
  252. <a href="https://github.com/danielmarschall/uuid_mac_utils/blob/master/includes/uuid_utils.inc.php">PHP implementation</a>
  253. </p>
  254.  
  255. <script>
  256. function show_uuidv8_sqlserver_info() {
  257.         document.getElementById("uuidv8_sqlserver_info_button").style.display = "none";
  258.         document.getElementById("uuidv8_sqlserver_info").style.display = "block";
  259. }
  260. </script>
  261. <p><a id="uuidv8_sqlserver_info_button" href="javascript:show_uuidv8_sqlserver_info()">Show format</a>
  262. <pre id="uuidv8_sqlserver_info" style="display:none">Version 2: Resolution of 1 milliseconds, random part of 16 bits, UTC time, 48 bit random "signature", UUIDv8 conform:
  263. - 16 bit Random data
  264. -  8 bit UTC Milliseconds transformed from 1000ms to 0..255, deviation -2ms..2ms (hex encoded)
  265. -  8 bit UTC Seconds (hex encoded)
  266. - 16 bit UTC Minute of the day (1..1440, hex encoded)
  267. -  4 bit UUID version 8
  268. - 12 bit UTC Day of the year (1..366, hex encoded)
  269. -  2 bit UUID Variant (0b10)
  270. -  2 bit Unused (must be zero)
  271. - 12 bit UTC Year (hex encoded)
  272. - 48 bit Signature 0x5ce32bd83b96
  273.  
  274. Version 1: Resolution of 1 milliseconds, random part of 16 bits, local timezone, 48 zero bits "signature", NOT UUIDv8 conform:
  275. - 16 bit Random data
  276. -  8 bit Generator's local timezone Milliseconds transformed from 1000ms to 0..255, deviation -4ms..0ms (hex encoded)
  277. -  8 bit Generator's local timezone Seconds (BCD encoded)
  278. -  8 bit Generator's local timezone Minute (BCD encoded)
  279. -  8 bit Generator's local timezone Hour (BCD encoded)
  280. -  8 bit Generator's local timezone Day (BCD encoded)
  281. -  8 bit Generator's local timezone Month (BCD encoded)
  282. -  8 bit Generator's local timezone 2-digit year (BCD encoded)
  283. -  8 bit Generator's local timezone 2-digit century (BCD encoded)
  284. - 48 bit Signature 0x000000000000</pre></p>
  285.  
  286. <?php
  287. if (AUTO_NEW_UUIDS > 0) { /** @phpstan-ignore-line */
  288.     echo '<p>Here are '.AUTO_NEW_UUIDS.' UUIDs that were created just for you! (Reload the page to get more)</p>';
  289.  
  290.     echo '<pre>';
  291.     for ($i=0; $i<AUTO_NEW_UUIDS; $i++) {
  292.         $uuid = gen_uuid_v8_sqlserver_sortable();
  293.         echo '<a href="interprete_uuid.php?uuid='.$uuid.'">'.$uuid.'</a><br>';
  294.     }
  295.     echo '</pre>';
  296. }
  297. ?>
  298.  
  299. <form method="GET" action="interprete_uuid.php">
  300.     <input type="hidden" name="version" value="8_sqlserver_v2">
  301.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create and display another UUID (new version)">
  302. </form><br>
  303.  
  304. <form method="GET" action="interprete_uuid.php">
  305.     <input type="hidden" name="version" value="8_sqlserver_v1">
  306.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create and display another UUID (old version)">
  307. </form>
  308.  
  309.  
  310.  
  311. <h2 id="gen_other_uuid">Generate other UUID types</h2>
  312.  
  313. <p><i>The following types of UUIDs are less common and/or require special knowledge. Please only use the following
  314. generators if you know what you are doing.</i></p>
  315.  
  316. <h3 id="gen_uuid_ncs">NCS (variant 0) UUID</h3>
  317.  
  318. <p>The <abbr title="Network Computing System">NCS</abbr> UUIDs are a legacy format
  319. initially designed by Apollo Computer that cannot be generated anymore, because the
  320. amount of available timestamp bits was exhausted on <strong>5 September 2015</strong>.
  321. As an example, here is the last possible NCS UUID (all bits of the timestamp are set to 1) for IP address 127.0.0.1:
  322. <a href="interprete_uuid.php?uuid=ffffffff-ffff-0000-027f-000001000000"><code>ffffffff-ffff-0000-027f-000001000000</code></a>.</p>
  323.  
  324. <script>
  325. function show_uuidnce_info() {
  326.         document.getElementById("uuidnce_info_button").style.display = "none";
  327.         document.getElementById("uuidnce_info").style.display = "block";
  328. }
  329. </script>
  330. <p><a id="uuidnce_info_button" href="javascript:show_uuidnce_info()">Show format</a>
  331. <pre id="uuidnce_info" style="display:none">Variant 0 UUID:
  332. - 32 bit High <abbr title="Count of 4&#xB5;s intervals passed since 1 Jan 1980 00:00:00 GMT">Time</abbr>
  333. - 16 bit Low <abbr title="Count of 4&#xB5;s intervals passed since 1 Jan 1980 00:00:00 GMT">Time</abbr>
  334. - 16 bit Reserved
  335. -  1 bit Variant (fix 0b0)
  336. -  7 bit <abbr title="socket_$unspec (0x0)
  337. socket_$unix (0x1)
  338. socket_$internet (0x2)
  339. socket_$implink (0x3)
  340. socket_$pup (0x4)
  341. socket_$chaos (0x5)
  342. socket_$ns (0x6)
  343. socket_$nbs (0x7)
  344. socket_$ecma (0x8)
  345. socket_$datakit (0x9)
  346. socket_$ccitt (0xA)
  347. socket_$sna (0xB)
  348. socket_$unspec2 (0xC)
  349. socket_$dds (0xD)">Family</abbr>
  350. - 56 bit Node</pre></p>
  351.  
  352. <h3 id="gen_uuidv2">Generate DCE Security (version 2) UUID</h3>
  353.  
  354. <p><i>An UUIDv2 contains information about the creator (person, group, or organization), the generating system (MAC address), and time.
  355. The creator information replaced parts of the time bits, therefore the time resolution is very low.</i></p>
  356.  
  357. <script>
  358. function show_uuidv2_info() {
  359.         document.getElementById("uuidv2_info_button").style.display = "none";
  360.         document.getElementById("uuidv2_info").style.display = "block";
  361. }
  362. </script>
  363. <p><a id="uuidv2_info_button" href="javascript:show_uuidv2_info()">Show format</a>
  364. <pre id="uuidv2_info" style="display:none">Variant 1, Version 2 UUID:
  365. - 32 bit Local Domain Number
  366. - 16 bit Mid <abbr title="Count of 429.4967296s intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  367. -  4 bit Version (fix 0x2)
  368. - 12 bit High <abbr title="Count of 429.4967296s intervals passed since 15 Oct 1582 00:00:00 GMT">Time</abbr>
  369. -  2 bit Variant (fix 0b10)
  370. -  6 bit Clock Sequence
  371. -  8 bit <abbr title="0 = person
  372. 1 = group
  373. 2 = org
  374. 3-255 = site-defined">Local Domain</abbr>
  375. - 48 bit MAC Address</pre></p>
  376.  
  377. <form method="GET" action="interprete_uuid.php">
  378.         <input type="hidden" name="version" value="2">
  379.         <label>Domain (8&nbsp;bits):</label><select name="domain_choose" id="dce_domain_choice" onchange="javascript:dce_domain_choice_choose();">
  380.                 <option value="uid">Person (e.g. POSIX UID)</option>
  381.                 <option value="gid">Group (e.g. POSIX GID)</option>
  382.                 <option value="org">Organization</option>
  383.                 <option value="site">Site-defined</option>
  384.         </select> = Address Family ID: <input type="number" min="0" max="255" name="dce_domain" value="0" id="dce_domain" style="width:50px" pattern="[0-9]+" onchange="javascript:dce_domain_choose();"> (decimal notation)<br>
  385.         <label>Value (32&nbsp;bits):</label><input type="number" min="0" max="4294967295" name="dce_id" value="0" id="dce_id" style="width:200px" pattern="[0-9]+"> (decimal notation)<br>
  386.         <font color="red">Warning</font>: The timestamp has an accuracy of 7:10 minutes,
  387.         therefore the uniqueness of these UUIDs is not guaranteed!<br><br>
  388.         <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create UUIDv2">
  389. </form>
  390. <script>
  391. function dce_domain_choose() {
  392.         var ns = document.getElementById('dce_domain').value;
  393.         if (ns == "0") {
  394.                 document.getElementById('dce_domain_choice').value = "uid";
  395.         } else if (ns == "1") {
  396.                 document.getElementById('dce_domain_choice').value = "gid";
  397.         } else if (ns == "2") {
  398.                 document.getElementById('dce_domain_choice').value = "org";
  399.         } else {
  400.                 document.getElementById('dce_domain_choice').value = "site";
  401.         }
  402. }
  403. function dce_domain_choice_choose() {
  404.         var ns = document.getElementById('dce_domain_choice').value;
  405.         if (ns == "uid") {
  406.                 document.getElementById('dce_domain').value = "0";
  407.         } else if (ns == "gid") {
  408.                 document.getElementById('dce_domain').value = "1";
  409.         } else if (ns == "org") {
  410.                 document.getElementById('dce_domain').value = "2";
  411.         } else if (ns == "site") {
  412.                 document.getElementById('dce_domain').value = "";
  413.         }
  414. }
  415. dce_domain_choose();
  416. </script>
  417.  
  418. <h3 id="gen_uuidv35">Generate name-based (version 3 / 5 / <font color="green">New: 8</font>) UUID</h3>
  419.  
  420. <p><i>An UUIDv3 is made out of a MD5 hash and an UUIDv5 is made out of a SHA1 hash.
  421. RFC 9562 also contains an example for a custom UUIDv8 implementation that
  422. uses modern hash algorithms.</i></p>
  423.  
  424. <script>
  425. function show_uuidv35_info() {
  426.         document.getElementById("uuidv35_info_button").style.display = "none";
  427.         document.getElementById("uuidv35_info").style.display = "block";
  428. }
  429. </script>
  430. <p><a id="uuidv35_info_button" href="javascript:show_uuidv35_info()">Show format</a>
  431. <pre id="uuidv35_info" style="display:none">Variant 1, Version 3/5/8 UUID:
  432. - 48 bit Hash High
  433. -  4 bit Version (fix 0x3, 0x5, or 0x8)
  434. - 12 bit Hash Mid
  435. -  2 bit Variant (fix 0b10)
  436. - 62 bit Hash Low
  437.  
  438.  
  439. <u>As shown in <a href="https://www.ietf.org/rfc/rfc9562.txt">RFC 9562</a> Appendix B.2:</u>
  440. UUIDv8(<i>HashAlgo</i>, <i>NameSpaceUuid</i>, <i>Data</i>) := <abbr title="Adds UUID variant 0b10 and version 8">ConvertRawBytesToUuid_v8</abbr>(<i>HashAlgo</i>( Binary[<i>NameSpaceUuid</i>] || <i>Data</i> )).
  441.  
  442. </pre></p>
  443.  
  444. <style>
  445. label {
  446.         width:120px;
  447.         text-align:left;
  448.         margin-right: 20px;
  449.         display:inline-block;
  450. }
  451. </style>
  452.  
  453. <form method="GET" action="interprete_uuid.php">
  454.         <label>Hash algorithm:</label><select name="version" id="nb_version" onchange="javascript:nb_version_choose();">
  455.                 <?php
  456.  
  457.                 echo "\t\t<option disabled>--- UUIDv3 (defined in RFC 4122/9562) ---</option>\n";
  458.                 echo "\t\t<option value=\"3\">MD5</option>\n";
  459.                 echo "\t\t<option disabled>--- UUIDv5 (defined in RFC 4122/9562) ---</option>\n";
  460.                 echo "\t\t<option value=\"5\" selected>SHA1</option>\n";
  461.                 echo "\t\t<option disabled>--- UUIDv8 (shown in RFC 9562, Appendix B.2) ---</option>\n";
  462.                 $tmp = [];
  463.                 $algos = hash_algos();
  464.                 $algos[] = 'shake128';
  465.                 $algos[] = 'shake256';
  466.                 foreach ($algos as $algo) {
  467.                         if ($algo == 'md5') continue; // use UUIDv3 instead
  468.                         if ($algo == 'sha1') continue; // use UUIDv5 instead
  469.                         $friendlyName = strtoupper($algo);
  470.  
  471.                         if ($algo == 'shake128') $bits = 999;
  472.                         else if ($algo == 'shake256') $bits = 999;
  473.                         else $bits = strlen(hash($algo, '', true)) * 8;
  474.                         if ($bits < 128) $friendlyName .= " (Small hash size! $bits bits)"; // <-- this is not described in Appendix C.2
  475.  
  476.                         $tmp[$friendlyName] = '<option value="8_namebased_'.$algo.'">'.htmlentities($friendlyName).'</option>';
  477.                 }
  478.                 natsort($tmp);
  479.                 foreach ($tmp as $html) {
  480.                         echo "\t\t$html\n";
  481.                 }
  482.  
  483.                 ?>
  484.         </select><br>
  485.         <label>Namespace:</label><select name="namespace_choose" id="nb_nsc" onchange="javascript:nb_ns_choose();">
  486.                 <option value="dns">DNS</option>
  487.                 <option value="url">URL</option>
  488.                 <option value="oid">OID</option>
  489.                 <option value="x500">X.500 DN</option>
  490.                 <option value="r74n">R74n Namespace</option>
  491.                 <!-- <option value="oidplus_ns">OIDplus ns only</option> -->
  492.                 <!-- <option value="oidplus_ns_val">OIDplus ns+val</option> -->
  493.                 <!-- <option value="oidplus_pubkey">OIDplus pubkey</option> -->
  494.                 <option value="other">Other</option>
  495.         </select> = Namespace UUID: <input type="text" name="nb_ns" value="" id="nb_ns" style="width:270px" onchange="javascript:nb_ns_textchange();" pattern="[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}"><br>
  496.         <label>Value:</label><input type="text" name="nb_val" value="" id="nb_val" style="width:300px"><br>
  497.         <font color="red">Warning</font>: These UUIDs do not contain a timestamp,
  498.         therefore the uniqueness of these UUIDs is not guaranteed!<br><br>
  499.         <input type="hidden" name="uuid" value="CREATE"> <input type="submit" id="nb_create_btn" value="Create UUID">
  500. </form>
  501. <script>
  502. function nb_version_choose() {
  503.         var ver = document.getElementById('nb_version').value;
  504.         document.getElementById('nb_create_btn').value = 'Create UUIDv' + ver.substr(0,1);
  505. }
  506. function nb_ns_textchange() {
  507.         var ns = document.getElementById('nb_ns').value.toLowerCase();
  508.         if (ns == "6ba7b810-9dad-11d1-80b4-00c04fd430c8") {
  509.                 if (document.getElementById('nb_nsc').value != "dns") {
  510.                         document.getElementById('nb_nsc').value = "dns";
  511.                         document.getElementById('nb_val').value = "www.example.com";
  512.                 }
  513.         }
  514.         else if (ns == "6ba7b811-9dad-11d1-80b4-00c04fd430c8") {
  515.                 if (document.getElementById('nb_nsc').value != "url") {
  516.                         document.getElementById('nb_nsc').value = "url";
  517.                         document.getElementById('nb_val').value = "http://www.example.com/";
  518.                 }
  519.         }
  520.         else if (ns == "6ba7b812-9dad-11d1-80b4-00c04fd430c8") {
  521.                 if (document.getElementById('nb_nsc').value != "oid") {
  522.                         document.getElementById('nb_nsc').value = "oid";
  523.                         document.getElementById('nb_val').value = "2.999";
  524.                 }
  525.         }
  526.         else if (ns == "6ba7b814-9dad-11d1-80b4-00c04fd430c8") {
  527.                 if (document.getElementById('nb_nsc').value != "x500") {
  528.                         document.getElementById('nb_nsc').value = "x500";
  529.                         document.getElementById('nb_val').value = "UID=jsmith,DC=example,DC=net";
  530.                 }
  531.         }
  532.         else if (ns == "ca069732-780c-11ee-b962-000000000074") { // https://r74n.com/id/uuid
  533.                 if (document.getElementById('nb_nsc').value != "r74n") {
  534.                         document.getElementById('nb_nsc').value = "r74n";
  535.                         document.getElementById('nb_val').value = "ants";
  536.                 }
  537.         }
  538.         else {
  539.                 if (document.getElementById('nb_nsc').value != "other") {
  540.                         document.getElementById('nb_nsc').value = "other";
  541.                         document.getElementById('nb_val').value = "";
  542.                 }
  543.         }
  544. }
  545. function nb_ns_choose() {
  546.         var ns = document.getElementById('nb_nsc').value;
  547.         if (ns == "dns") {
  548.                 document.getElementById('nb_ns').value = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
  549.                 document.getElementById('nb_val').value = "www.example.com";
  550.         }
  551.         else if (ns == "url") {
  552.                 document.getElementById('nb_ns').value = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
  553.                 document.getElementById('nb_val').value = "http://www.example.com/";
  554.         }
  555.         else if (ns == "oid") {
  556.                 document.getElementById('nb_ns').value = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
  557.                 document.getElementById('nb_val').value = "2.999";
  558.         }
  559.         else if (ns == "x500") {
  560.                 document.getElementById('nb_ns').value = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
  561.                 document.getElementById('nb_val').value = "UID=jsmith,DC=example,DC=net";
  562.         }
  563.         else if (ns == "r74n") { // https://r74n.com/id/uuid
  564.                 document.getElementById('nb_ns').value = "ca069732-780c-11ee-b962-000000000074";
  565.                 document.getElementById('nb_val').value = "ants";
  566.         }
  567.         /*
  568.         else if (ns == "oidplus_ns") {
  569.                 document.getElementById('nb_ns').value = "0943e3ce-4b79-11e5-b742-78e3b5fc7f22";
  570.                 document.getElementById('nb_val').value = "ipv4";
  571.         }
  572.         else if (ns == "oidplus_ns_val") {
  573.                 document.getElementById('nb_ns').value = "ad1654e6-7e15-11e4-9ef6-78e3b5fc7f22";
  574.                 document.getElementById('nb_val').value = "ipv4:8.8.8.8";
  575.         }
  576.         else if (ns == "oidplus_ns_pubkey") {
  577.                 document.getElementById('nb_ns').value = "fd16965c-8bab-11ed-8744-3c4a92df8582";
  578.                 document.getElementById('nb_val').value = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqg/PnsC1WX3C1/mUSLuk0DIaDHtEsxBnG0auYJRJ1hBtbUUvItbK0odlKrX2SFo1MJJpu/SSxTzAgqkKZsZe3cCFkgA1svfuH9i94oGLjJ4n0kRJEGlanCmGndJBfIqGDJaQE2BJ8tLxeBrpkd9l0KvJsjhRmqJAb9KYK3KYFsWvT+wyjD3UJ1eHcgLbF/Qb3cwMU/u7Fs7ZpsNMW4phDPlsYsk9XHFpJ1/UCj6G53mYRfOC/ouDdGShlbVLB15s0V95QpnU/7lL8mJ2lE+sTZekGNBA4XbJv2gs21cR4E8zc/z+NyZS7117DYZoJqrAN8sKz6xGoKgQF6wueCK5qQIDAQAB";
  579.         }
  580.         */
  581.         else if (ns == "other") {
  582.                 document.getElementById('nb_ns').value = "";
  583.                 document.getElementById('nb_val').value = "";
  584.         }
  585. }
  586. nb_version_choose();
  587. nb_ns_choose();
  588. </script>
  589.  
  590. <h3 id="gen_uuidv8"><font color="green">New:</font> Generate Custom (version 8) UUID</h3>
  591.  
  592. <p><i>UUIDv8 is made of 122 bits application-specific / custom data. The other 6 bits are used to specify the variant and version of the UUID, to make it RFC-compatible.</i></p>
  593.  
  594. <script>
  595. function show_uuidv8_info() {
  596.         document.getElementById("uuidv8_info_button").style.display = "none";
  597.         document.getElementById("uuidv8_info").style.display = "block";
  598. }
  599. function uuidv8_changedec(block, len) {
  600.         var x = document.getElementById("v8_block"+block+"_dec").value;
  601.         if (x.trim() == "") x = 0;
  602.         x = parseInt(x);
  603.         if (isNaN(x)) {
  604.                 x = "???";
  605.         } else {
  606.                 x = x.toString(16).padStart(len, '0');
  607.                 if ((len > 0) && (x.length > len)) x = "Overflow";
  608.         }
  609.         document.getElementById("v8_block"+block+"_hex").value = x;
  610. }
  611. function uuidv8_changehex(block, len) {
  612.         var x = document.getElementById("v8_block"+block+"_hex").value;
  613.         if (x.trim() == "") x = 0;
  614.         x = parseInt(x, 16);
  615.         if (isNaN(x)) {
  616.                 x = "???";
  617.         } else {
  618.                 x = x.toString().padStart(len, '0');
  619.                 if ((len > 0) && (x.length > len)) x = "Overflow"; // Note: For block 3/4, the overflow actually happens at 12/14 bits, not at 4 nibbles (16 bits)
  620.         }
  621.         document.getElementById("v8_block"+block+"_dec").value = x;
  622. }
  623. </script>
  624. <p><a id="uuidv8_info_button" href="javascript:show_uuidv8_info()">Show format</a>
  625. <pre id="uuidv8_info" style="display:none">Variant 1, Version 8 UUID:
  626. - 48 bit Custom data [Block 1+2]
  627. -  4 bit Version (fix 0x8)
  628. - 12 bit Custom data [Block 3]
  629. -  2 bit Variant (fix 0b10)
  630. - 62 bit Custom data [Block 4+5]</pre></p>
  631.  
  632. <form method="GET" action="interprete_uuid.php">
  633.         <input type="hidden" name="version" value="8">
  634.  
  635.         <label>Block&nbsp;1 (32&nbsp;bits):</label>0x<input type="text" name="block1" value="00000000" maxlength="8" id="v8_block1_hex" onkeyup="uuidv8_changehex(1, 0)" style="width:150px" pattern="[0-9a-fA-F]+"> = Decimal
  636.         <input type="number" name="block1dec" value="0" min="0" maxlength="20" id="v8_block1_dec" onmouseup="uuidv8_changedec(1, 8)" onkeyup="uuidv8_changedec(1, 8)" style="width:150px"><br>
  637.  
  638.         <label>Block&nbsp;2 (16&nbsp;bits):</label>0x<input type="text" name="block2" value="0000" maxlength="4" id="v8_block2_hex" onkeyup="uuidv8_changehex(2, 0)" style="width:150px" pattern="[0-9a-fA-F]+"> = Decimal
  639.         <input type="number" name="block2dec" value="0" min="0" maxlength="20" id="v8_block2_dec" onmouseup="uuidv8_changedec(2, 4)" onkeyup="uuidv8_changedec(2, 4)" style="width:150px"><br>
  640.  
  641.         <label>Block&nbsp;3 (<abbr title="The high 4 bits are occupied by the UUID version = 8">12&nbsp;bits</abbr>):</label>0x<input type="text" name="block3" value="0000" maxlength="4" id="v8_block3_hex" onkeyup="uuidv8_changehex(3, 0)" style="width:150px" pattern="[0-9a-fA-F]+"> = Decimal
  642.         <input type="number" name="block3dec" value="0" min="0" maxlength="20" id="v8_block3_dec" onmouseup="uuidv8_changedec(3, 4)" onkeyup="uuidv8_changedec(3, 4)" style="width:150px"><br>
  643.  
  644.         <label>Block&nbsp;4 (<abbr title="The high 2 bits are occupied by the UUID variant = 0b10">14&nbsp;bits</abbr>):</label>0x<input type="text" name="block4" value="0000" maxlength="4" id="v8_block4_hex" onkeyup="uuidv8_changehex(4, 0)" style="width:150px" pattern="[0-9a-fA-F]+"> = Decimal
  645.         <input type="number" name="block4dec" value="0" min="0" maxlength="20" id="v8_block4_dec" onmouseup="uuidv8_changedec(4, 4)" onkeyup="uuidv8_changedec(4, 4)" style="width:150px"><br>
  646.  
  647.         <label>Block&nbsp;5 (48&nbsp;bits):</label>0x<input type="text" name="block5" value="000000000000" maxlength="12" id="v8_block5_hex" onkeyup="uuidv8_changehex(5, 0)" style="width:150px" pattern="[0-9a-fA-F]+"> = Decimal
  648.         <input type="number" name="block5dec" value="0" min="0" maxlength="20" id="v8_block5_dec" onmouseup="uuidv8_changedec(5, 12)" onkeyup="uuidv8_changedec(5, 12)" style="width:150px"><br>
  649.  
  650.         <font color="red">Warning</font>: These UUIDs do not contain a timestamp,
  651.         therefore the uniqueness of these UUIDs is not guaranteed!<br><br>
  652.         <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Create UUIDv8">
  653. </form>
  654.  
  655. <h2 id="interpret_uuid">Interpret a UUID</h2>
  656.  
  657. <p>You can enter a UUID in the following notations:</p>
  658.  
  659. <ul>
  660.         <li>Classic notation (case insensitive, curly braces optional): <code>9e83839a-5967-11e4-8c1c-78e3b5fc7f22</code></li>
  661.         <li>As OID: <code>2.25.210700883446948645633376489934419689250</code></li>
  662. </ul>
  663.  
  664. <p>The script will output:</p>
  665.  
  666. <ul>
  667.         <li>Notation as UUID and OID</li>
  668.         <li>Version, variant, and additional data (date and time, clock sequence, node id, etc.)</li>
  669. </ul>
  670.  
  671. <p>Please enter a UUID or UUID OID:</p>
  672.  
  673. <form method="GET" action="interprete_uuid.php">
  674.         <input type="text" name="uuid" value="" style="width:300px"> <input type="submit" value="Interprete">
  675. </form>
  676.  
  677. <h2 id="interpret_mac">Interpret a MAC address (<abbr title="Media Access Control">MAC</abbr> /
  678. <abbr title="Extended Unique Identifier">EUI</abbr> /
  679. <abbr title="Extended Local Identifier">ELI</abbr> /
  680. <abbr title="Standard Assigned Identifier">SAI</abbr> /
  681. <abbr title="Administratively Assigned Identifier">AAI</abbr>)</h2>
  682.  
  683. <p>You can enter a UUID in the following notations:</p>
  684.  
  685. <ul>
  686.         <li><code>AA-BB-CC-DD-EE-FF</code></li>
  687.         <li><code>AA:BB:CC:DD:EE:FF</code></li>
  688.         <li><code>AABBCC.DDEEFF</code> (case insensitive)</li>
  689.         <li><code>AA-BB-CC-DD-EE-FF-11-22</code> (EUI-64)</li>
  690.         <li><code>AA:BB:CC:DD:EE:FF-11-22</code> (EUI-64)</li>
  691.         <li><code>fe80::1322:33ff:fe44:5566</code> (IPv6 Link Local / EUI-64)</li>
  692. </ul>
  693.  
  694. <p>The script will output:</p>
  695.  
  696. <ul>
  697.         <li>Information about the I/G and U/L flags.</li>
  698.         <li>Information about the entry in the IEEE registry, if available.</li>
  699.         <li>Information about the registrant, if available.</li>
  700. </ul>
  701.  
  702. <p>Please enter a MAC (EUI, ELI, SAI, AAI), or IPv6-Link-Local address:</p>
  703.  
  704. <form method="GET" action="interprete_mac.php">
  705.         <input type="text" name="mac" value="" style="width:250px"> <input type="submit" value="Interprete">
  706. </form>
  707.  
  708. <h3 id="gen_aai">Generate an <abbr title="Administratively Assigned Identifier">AAI</abbr></h3>
  709.  
  710. <p><i>An Administratively Assigned Identifier (AAI) is a MAC address which can be locally defined
  711. by applications or an administrator. Unlike the EUI, an AAI is NOT worldwide unique.</i></p>
  712.  
  713. <form method="GET" action="interprete_mac.php">
  714.     <input type="hidden" name="aai_gen" value="1">
  715.     <input type="hidden" name="aai_gen_bits" value="48">
  716.     <input type="hidden" name="aai_gen_multicast" value="0">
  717.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Generate AAI-48">
  718. </form>
  719.  
  720. <br>
  721.  
  722. <form method="GET" action="interprete_mac.php">
  723.     <input type="hidden" name="aai_gen" value="1">
  724.     <input type="hidden" name="aai_gen_bits" value="64">
  725.     <input type="hidden" name="aai_gen_multicast" value="0">
  726.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Generate AAI-64">
  727. </form>
  728.  
  729. <p>The following options are rather unusual, but are implemented for the sake of completeness:</p>
  730.  
  731. <form method="GET" action="interprete_mac.php">
  732.     <input type="hidden" name="aai_gen" value="1">
  733.     <input type="hidden" name="aai_gen_bits" value="48">
  734.     <input type="hidden" name="aai_gen_multicast" value="1">
  735.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Generate Multicast AAI-48">
  736. </form>
  737.  
  738. <br>
  739.  
  740. <form method="GET" action="interprete_mac.php">
  741.     <input type="hidden" name="aai_gen" value="1">
  742.     <input type="hidden" name="aai_gen_bits" value="64">
  743.     <input type="hidden" name="aai_gen_multicast" value="1">
  744.     <input type="hidden" name="uuid" value="CREATE"> <input type="submit" value="Generate Multicast AAI-64">
  745. </form>
  746.  
  747. <br><br><br>
  748.  
  749. </body>
  750.  
  751. </html>
  752.