| < draft-mealling-uuid-urn-03.txt | draft-mealling-uuid-urn-04.txt > | |||
|---|---|---|---|---|
| Network Working Group P. Leach | Network Working Group P. Leach | |||
| Internet-Draft Microsoft | Internet-Draft Microsoft | |||
| Expires: July 1, 2004 M. Mealling | Expires: June 8, 2005 M. Mealling | |||
| VeriSign, Inc. | VeriSign, Inc. | |||
| R. Salz | R. Salz | |||
| DataPower Technology, Inc. | DataPower Technology, Inc. | |||
| January 2004 | December 8, 2004 | |||
| A UUID URN Namespace | A UUID URN Namespace | |||
| draft-mealling-uuid-urn-03.txt | draft-mealling-uuid-urn-04.txt | |||
| Status of this Memo | Status of this Memo | |||
| This document is an Internet-Draft and is in full conformance with | This document is an Internet-Draft and is subject to all provisions | |||
| all provisions of Section 10 of RFC2026. | of section 3 of RFC 3667. By submitting this Internet-Draft, each | |||
| author represents that any applicable patent or other IPR claims of | ||||
| which he or she is aware have been or will be disclosed, and any of | ||||
| which he or she become aware will be disclosed, in accordance with | ||||
| RFC 3668. | ||||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF), its areas, and its working groups. Note that other | Task Force (IETF), its areas, and its working groups. Note that | |||
| groups may also distribute working documents as Internet-Drafts. | other groups may also distribute working documents as | |||
| Internet-Drafts. | ||||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| The list of current Internet-Drafts can be accessed at http:// | The list of current Internet-Drafts can be accessed at | |||
| www.ietf.org/ietf/1id-abstracts.txt. | http://www.ietf.org/ietf/1id-abstracts.txt. | |||
| The list of Internet-Draft Shadow Directories can be accessed at | The list of Internet-Draft Shadow Directories can be accessed at | |||
| http://www.ietf.org/shadow.html. | http://www.ietf.org/shadow.html. | |||
| This Internet-Draft will expire on July 1, 2004. | This Internet-Draft will expire on June 8, 2005. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (C) The Internet Society (2004). All Rights Reserved. | Copyright (C) The Internet Society (2004). | |||
| Abstract | Abstract | |||
| This specification defines a Uniform Resource Name namespace for | This specification defines a Uniform Resource Name namespace for | |||
| UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | |||
| Unique IDentifier). A UUID is 128 bits long, and can provide a | Unique IDentifier). A UUID is 128 bits long, and can provide a | |||
| guarantee of uniqueness across space and time. UUIDs were originally | guarantee of uniqueness across space and time. UUIDs were originally | |||
| used in the Network Computing System (NCS) [1] and later in the Open | used in the Apollo Network Computing System and later in the Open | |||
| Software Foundation's (OSF) Distributed Computing Environment [2]. | Software Foundation's (OSF) Distributed Computing Environment (DCE), | |||
| and then in Microsoft Windows platforms. | ||||
| This specification is derived from the latter specification with the | This specification is derived from the DCE specification with the | |||
| kind permission of the OSF (now known as The Open Group). Earlier | kind permission of the OSF (now known as The Open Group). Earlier | |||
| versions of this document never left draft stage; this document | versions of this document never left draft stage; this document | |||
| incorporates that information here. | incorporates that information here. | |||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 3 | 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 3. Namespace Registration Template . . . . . . . . . . . . . . 3 | 3. Namespace Registration Template . . . . . . . . . . . . . . . 3 | |||
| 4. Specification . . . . . . . . . . . . . . . . . . . . . . . 5 | 4. Specification . . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 | 4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . . . . 6 | 4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1.2 Layout and byte order . . . . . . . . . . . . . . . . . . . 6 | 4.1.2 Layout and byte order . . . . . . . . . . . . . . . . 7 | |||
| 4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . . . . 7 | 4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . . . . 8 | 4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . . . . 8 | 4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . 9 | |||
| 4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | 4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . . . . 10 | 4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . 10 | |||
| 4.2 Algorithms for creating a time-based UUID . . . . . . . . . 10 | 4.2 Algorithms for creating a time-based UUID . . . . . . . . 10 | |||
| 4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . . . . 10 | 4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . 10 | |||
| 4.2.2 Generation details . . . . . . . . . . . . . . . . . . . . . 12 | 4.2.2 Generation details . . . . . . . . . . . . . . . . . . 12 | |||
| 4.3 Algorithm for creating a name-based UUID . . . . . . . . . . 12 | 4.3 Algorithm for creating a name-based UUID . . . . . . . . . 13 | |||
| 4.4 Algorithms for creating a UUID from truly random or | 4.4 Algorithms for creating a UUID from truly random or | |||
| pseudo-random numbers . . . . . . . . . . . . . . . . . . . 13 | pseudo-random numbers . . . . . . . . . . . . . . . . . . 14 | |||
| 4.5 Node IDs that do not identify the host . . . . . . . . . . . 14 | 4.5 Node IDs that do not identify the host . . . . . . . . . . 14 | |||
| 5. Community Considerations . . . . . . . . . . . . . . . . . . 15 | 5. Community Considerations . . . . . . . . . . . . . . . . . . . 15 | |||
| 6. Security Considerations . . . . . . . . . . . . . . . . . . 15 | 6. Security Considerations . . . . . . . . . . . . . . . . . . . 15 | |||
| 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 15 | 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 15 | |||
| Normative References . . . . . . . . . . . . . . . . . . . . 15 | 8. Normative References . . . . . . . . . . . . . . . . . . . . . 16 | |||
| Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 16 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 16 | |||
| A. Appendix A - Sample Implementation . . . . . . . . . . . . . 16 | A. Appendix A - Sample Implementation . . . . . . . . . . . . . . 17 | |||
| B. Appendix B - Sample output of utest . . . . . . . . . . . . 27 | B. Appendix B - Sample output of utest . . . . . . . . . . . . . 29 | |||
| C. Appendix C - Some name space IDs . . . . . . . . . . . . . . 28 | C. Appendix C - Some name space IDs . . . . . . . . . . . . . . . 29 | |||
| Intellectual Property and Copyright Statements . . . . . . . 29 | Intellectual Property and Copyright Statements . . . . . . . . 31 | |||
| 1. Introduction | 1. Introduction | |||
| This specification defines a Uniform Resource Name namespace for | This specification defines a Uniform Resource Name namespace for | |||
| UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | |||
| Unique IDentifier). A UUID is 128 bits long, and requires no central | Unique IDentifier). A UUID is 128 bits long, and requires no central | |||
| registration process. | registration process. | |||
| The information here is meant to be a concise guide for those wishing | The information here is meant to be a concise guide for those wishing | |||
| to implement services using UUIDs as URNs. Nothing in this document | to implement services using UUIDs as URNs. Nothing in this document | |||
| should be construed to mean that it overrides the DCE standards that | should be construed to mean that it overrides the DCE standards that | |||
| defined UUIDs to begin with. | defined UUIDs to begin with. | |||
| 2. Motivation | There is an ITU-T Recommendation and ISO/IEC Standard [3] that are | |||
| derived from earlier versions of this document. Both sets of | ||||
| specifications have been aligned, and are fully technically | ||||
| compatible. In addition, a global registration function is being | ||||
| provided by the Telecommunications Standardisation Bureau of ITU-T; | ||||
| for details see <http://www.itu.int/ITU-T/asn1/uuid.html>. | ||||
| 2. Motivation | ||||
| One of the main reasons for using UUIDs is that no centralized | One of the main reasons for using UUIDs is that no centralized | |||
| authority is required to administer them (although one format uses | authority is required to administer them (although one format uses | |||
| IEEE 802.1 node identifiers, others do not). As a result, generation | IEEE 802 node identifiers, others do not). As a result, generation | |||
| on demand can be completely automated, and they can be used for a | on demand can be completely automated, and they can be used for a | |||
| wide variety of purposes. The UUID generation algorithm described | wide variety of purposes. The UUID generation algorithm described | |||
| here supports very high allocation rates: 10 million per second per | here supports very high allocation rates: 10 million per second per | |||
| machine if necessary, so that they could even be used as transaction | machine if necessary, so that they could even be used as transaction | |||
| IDs. | IDs. | |||
| UUIDs are of a fixed size (128 bits) which is reasonably small | UUIDs are of a fixed size (128 bits) which is reasonably small | |||
| relative to other alternatives. This lends itself well to sorting, | relative to other alternatives. This lends itself well to sorting, | |||
| ordering, and hashing of all sorts, storing in databases, simple | ordering, and hashing of all sorts, storing in databases, simple | |||
| allocation, and ease of programming in general. | allocation, and ease of programming in general. | |||
| Since UUIDs are unique and persistent, they make excellent Uniform | Since UUIDs are unique and persistent, they make excellent Uniform | |||
| Resource Names. The unique ability to generate a new UUID without a | Resource Names. The unique ability to generate a new UUID without a | |||
| registration process allows for UUIDs to be one of the URNs with the | registration process allows for UUIDs to be one of the URNs with the | |||
| lowest minting cost. | lowest minting cost. | |||
| 3. Namespace Registration Template | 3. Namespace Registration Template | |||
| Namespace ID: UUID | Namespace ID: UUID | |||
| Registration Information: | Registration Information: | |||
| Registration date: 2003-10-01 | Registration date: 2003-10-01 | |||
| Declared registrant of the namespace: | Declared registrant of the namespace: | |||
| JTC 1/SC6 (ASN.1 Rapporteur Group) | JTC 1/SC6 (ASN.1 Rapporteur Group) | |||
| Declaration of syntactic structure: | Declaration of syntactic structure: | |||
| A UUID is an identifier that is unique across both space and time, | A UUID is an identifier that is unique across both space and time, | |||
| with respect to the space of all UUIDs. Since a UUID is a fixed | with respect to the space of all UUIDs. Since a UUID is a fixed | |||
| size and contains a time field, it is possible for values to | size and contains a time field, it is possible for values to | |||
| rollover (around A.D. 3400, depending on the specific algorithm | rollover (around A.D. 3400, depending on the specific algorithm | |||
| used). A UUID can be used for multiple purposes, from tagging | used). A UUID can be used for multiple purposes, from tagging | |||
| objects with an extremely short lifetime, to reliably identifying | objects with an extremely short lifetime, to reliably identifying | |||
| very persistent objects across a network. | very persistent objects across a network. | |||
| The internal representation of a UUID is a specific sequence of | The internal representation of a UUID is a specific sequence of | |||
| bits in memory, as described in Section 4. In order to accurately | bits in memory, as described in Section 4. In order to accurately | |||
| represent a UUID as a URN, it is necessary to convert the bit | represent a UUID as a URN, it is necessary to convert the bit | |||
| sequence to a string representation. | sequence to a string representation. | |||
| Each field is treated as an integer and has its value printed as a | Each field is treated as an integer and has its value printed as a | |||
| zero-filled hexadecimal digit string with the most significant | zero-filled hexadecimal digit string with the most significant | |||
| digit first. The hexadecimal values a through f are output as | digit first. The hexadecimal values a through f are output as | |||
| lower case characters, and are case insensitive on input. | lower case characters, and are case insensitive on input. | |||
| The formal definition of the UUID string representation is | The formal definition of the UUID string representation is | |||
| provided by the following ABNF [6]: | provided by the following ABNF [7]: | |||
| UUID = time_low "-" time_mid "-" | UUID = time-low "-" time-mid "-" | |||
| time_high_and_version "-" | time-high-and-version "-" | |||
| clock_seq_and_reserved | clock-seq-and-reserved | |||
| clock_seq_low "-" node | clock-seq-low "-" node | |||
| time_low = 4hexOctet | time-low = 4hexOctet | |||
| time_mid = 2hexOctet | time-mid = 2hexOctet | |||
| time_high_and_version = 2hexOctet | time-high-and-version = 2hexOctet | |||
| clock_seq_and_reserved = hexOctet | clock-seq-and-reserved = hexOctet | |||
| clock_seq_low = hexOctet | clock-seq-low = hexOctet | |||
| node = 6hexOctet | node = 6hexOctet | |||
| hexOctet = hexDigit hexDigit | hexOctet = hexDigit hexDigit | |||
| hexDigit = | hexDigit = | |||
| "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / | "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / | |||
| "a" / "b" / "c" / "d" / "e" / "f" / | "a" / "b" / "c" / "d" / "e" / "f" / | |||
| "A" / "B" / "C" / "D" / "E" / "F" | "A" / "B" / "C" / "D" / "E" / "F" | |||
| The following is an example of the string representation of a UUID | The following is an example of the string representation of a UUID | |||
| as a URN: | as a URN: | |||
| skipping to change at page 4, line 38 ¶ | skipping to change at page 5, line 4 ¶ | |||
| hexOctet = hexDigit hexDigit | hexOctet = hexDigit hexDigit | |||
| hexDigit = | hexDigit = | |||
| "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / | "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / | |||
| "a" / "b" / "c" / "d" / "e" / "f" / | "a" / "b" / "c" / "d" / "e" / "f" / | |||
| "A" / "B" / "C" / "D" / "E" / "F" | "A" / "B" / "C" / "D" / "E" / "F" | |||
| The following is an example of the string representation of a UUID | The following is an example of the string representation of a UUID | |||
| as a URN: | as a URN: | |||
| urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 | urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 | |||
| Relevant ancillary documentation: | Relevant ancillary documentation: | |||
| [2] | [2] | |||
| Identifier uniqueness considerations: | Identifier uniqueness considerations: | |||
| This document specifies three algorithms to generate UUIDs: the | This document specifies three algorithms to generate UUIDs: the | |||
| first leverages the unique values of 802.1 MAC addresses to | first leverages the unique values of 802 MAC addresses to | |||
| guarantee uniqueness, the second another uses pseudo-random number | guarantee uniqueness, the second another uses pseudo-random number | |||
| generators, and the third uses cryptographic hashing and | generators, and the third uses cryptographic hashing and | |||
| application-provided text strings. As a result, it is possible to | application-provided text strings. As a result, it is possible to | |||
| guarantee that UUIDs generated according to the mechanisms here | guarantee that UUIDs generated according to the mechanisms here | |||
| will be unique from all other UUIDs that have been or will be | will be unique from all other UUIDs that have been or will be | |||
| assigned. | assigned. | |||
| Identifier persistence considerations: | Identifier persistence considerations: | |||
| UUIDs are inherently very difficult to resolve in a global sense. | UUIDs are inherently very difficult to resolve in a global sense. | |||
| This, coupled with the fact that UUIDs are temporally unique | This, coupled with the fact that UUIDs are temporally unique | |||
| within their spatial context, ensures that UUIDs will remain as | within their spatial context, ensures that UUIDs will remain as | |||
| persistent as possible. | persistent as possible. | |||
| Process of identifier assignment: | Process of identifier assignment: | |||
| Generating a UUID does not require that it be a registration | Generating a UUID does not require that it be a registration | |||
| authority be contacted. One algorithm requires a unique value over | authority be contacted. One algorithm requires a unique value | |||
| space for each generator. This value is typically an IEEE 802 MAC | over space for each generator. This value is typically an IEEE | |||
| address, usually already available on network-connected hosts. The | 802 MAC address, usually already available on network-connected | |||
| address can be assigned from an address block obtained from the | hosts. The address can be assigned from an address block obtained | |||
| IEEE registration authority. If no such address is available, or | from the IEEE registration authority. If no such address is | |||
| privacy concerns make its use undesirable, Section 4.5 specifies | available, or privacy concerns make its use undesirable, Section | |||
| two alternatives; another approach is to use version 3 or version | 4.5 specifies two alternatives; another approach is to use version | |||
| 4 UUIDs as defined below. | 3 or version 4 UUIDs as defined below. | |||
| Process for identifier resolution: | Process for identifier resolution: | |||
| Since UUIDs are not globally resolvable, this is not applicable. | Since UUIDs are not globally resolvable, this is not applicable. | |||
| Rules for Lexical Equivalence: | Rules for Lexical Equivalence: | |||
| Consider each field of the UUID to be an unsigned integer as shown | Consider each field of the UUID to be an unsigned integer as shown | |||
| in the table in section Section 4.1.2. Then, to compare a pair of | in the table in section Section 4.1.2. Then, to compare a pair of | |||
| UUIDs, arithmetically compare the corresponding fields from each | UUIDs, arithmetically compare the corresponding fields from each | |||
| UUID in order of significance and according to their data type. | UUID in order of significance and according to their data type. | |||
| Two UUIDs are equal if and only if all the corresponding fields | Two UUIDs are equal if and only if all the corresponding fields | |||
| are equal. | are equal. | |||
| As an implementation note, on many systems equality comparison can | As an implementation note, on many systems equality comparison can | |||
| be performed by doing the appropriate byte-order canonicalization, | be performed by doing the appropriate byte-order canonicalization, | |||
| and then treating the two UUIDs as 128-bit unsigned integers. | and then treating the two UUIDs as 128-bit unsigned integers. | |||
| UUIDs as defined in this document can also be ordered | UUIDs as defined in this document can also be ordered | |||
| lexicographically. For a pair of UUIDs, the first one follows the | lexicographically. For a pair of UUIDs, the first one follows the | |||
| second if the most significant field in which the UUIDs differ is | second if the most significant field in which the UUIDs differ is | |||
| greater for the first UUID. The second precedes the first if the | greater for the first UUID. The second precedes the first if the | |||
| most significant field in which the UUIDs differ is greater for | most significant field in which the UUIDs differ is greater for | |||
| the second UUID. | the second UUID. | |||
| Conformance with URN Syntax: | Conformance with URN Syntax: | |||
| The string representation of a UUID is fully compatible with the | The string representation of a UUID is fully compatible with the | |||
| URN syntax. When converting from an bit-oriented, in-memory | URN syntax. When converting from an bit-oriented, in-memory | |||
| representation of a UUID into a URN, care must be taken to | representation of a UUID into a URN, care must be taken to | |||
| strictly adhere to the byte order issues mentioned in the string | strictly adhere to the byte order issues mentioned in the string | |||
| representation section. | representation section. | |||
| Validation mechanism: | Validation mechanism: | |||
| Apart from determining if the timestamp portion of the UUID is in | Apart from determining if the timestamp portion of the UUID is in | |||
| the future and therefore not yet assignable, there is no mechanism | the future and therefore not yet assignable, there is no mechanism | |||
| for determining if a UUID is 'valid' in any real sense. | for determining if a UUID is 'valid' in any real sense. | |||
| Scope: | Scope: | |||
| UUIDs are global in scope. | UUIDs are global in scope. | |||
| 4. Specification | 4. Specification | |||
| 4.1 Format | ||||
| 4.1 Format | ||||
| In its most general form, all that can be said of the UUID format is | In its most general form, all that can be said of the UUID format is | |||
| that a UUID is 16 octets, and that some bits of the eight octet -- | that a UUID is 16 octets, and that some bits of the eight octet -- | |||
| the variant field specified below -- determine finer structure. | the variant field specified below -- determine finer structure. | |||
| 4.1.1 Variant | 4.1.1 Variant | |||
| The variant field determines the layout of the UUID. That is, the | The variant field determines the layout of the UUID. That is, the | |||
| interpretation of all other bits in the UUID depends on the setting | interpretation of all other bits in the UUID depends on the setting | |||
| of the bits in the variant field. As such, it could more accurately | of the bits in the variant field. As such, it could more accurately | |||
| be called a type field; we retain the original term for | be called a type field; we retain the original term for | |||
| compatibility. The variant field consists of a variable number of the | compatibility. The variant field consists of a variable number of | |||
| most significant bits of the eighth octet of the UUID. | the most significant bits of the eighth octet of the UUID. | |||
| The following table lists the contents of the variant field, where | The following table lists the contents of the variant field, where | |||
| the letter "x" indicates a "don't-care" value. | the letter "x" indicates a "don't-care" value. | |||
| Msb0 Msb1 Msb2 Description | Msb0 Msb1 Msb2 Description | |||
| 0 x x Reserved, NCS backward compatibility. | 0 x x Reserved, NCS backward compatibility. | |||
| 1 0 x The variant specified in this document. | 1 0 x The variant specified in this document. | |||
| 1 1 0 Reserved, Microsoft Corporation backward | 1 1 0 Reserved, Microsoft Corporation backward | |||
| compatibility | compatibility | |||
| 1 1 1 Reserved for future definition. | 1 1 1 Reserved for future definition. | |||
| Interoperability (in any form) with variants other than the one | Interoperability (in any form) with variants other than the one | |||
| defined here is not guaranteed. This is unlikely to be an issue in | defined here is not guaranteed. This is unlikely to be an issue in | |||
| practice. | practice. | |||
| 4.1.2 Layout and byte order | 4.1.2 Layout and byte order | |||
| To minimize confusion about bit assignments within octets, the UUID | To minimize confusion about bit assignments within octets, the UUID | |||
| record definition is defined only in terms of fields that are | record definition is defined only in terms of fields that are | |||
| integral numbers of octets. The fields are presented with the most | integral numbers of octets. The fields are presented with the most | |||
| significant one first. | significant one first. | |||
| Field Data Type Octet Note | Field Data Type Octet Note | |||
| # | # | |||
| time_low unsigned 32 0-3 The low field of the | time_low unsigned 32 0-3 The low field of the | |||
| bit integer timestamp | bit integer timestamp | |||
| time_mid unsigned 16 4-5 The middle field of the | time_mid unsigned 16 4-5 The middle field of the | |||
| bit integer timestamp | bit integer timestamp | |||
| skipping to change at page 7, line 34 ¶ | skipping to change at page 7, line 41 ¶ | |||
| bit integer clock sequence | bit integer clock sequence | |||
| node unsigned 48 10-15 The spatially unique | node unsigned 48 10-15 The spatially unique | |||
| bit integer node identifier | bit integer node identifier | |||
| In the absence of explicit application or presentation protocol | In the absence of explicit application or presentation protocol | |||
| specification to the contrary, a UUID is encoded as a 128-bit object, | specification to the contrary, a UUID is encoded as a 128-bit object, | |||
| as follows: the fields are encoded as 16 octets, with the sizes and | as follows: the fields are encoded as 16 octets, with the sizes and | |||
| order of the fields defined above, and with each field encoded with | order of the fields defined above, and with each field encoded with | |||
| the Most Significant Byte first (this is known as network byte | the Most Significant Byte first (this is known as network byte | |||
| order). Note that the field names, particularly for multiplexed | order). Note that the field names, particularly for multiplexed | |||
| fields, follow historical practice. | fields, follow historical practice. | |||
| 0 1 2 3 | 0 1 2 3 | |||
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
| | time_low | | | time_low | | |||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
| | time_mid | time_hi_and_version | | | time_mid | time_hi_and_version | | |||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
| |clk_seq_hi_res | clk_seq_low | node (0-1) | | |clk_seq_hi_res | clk_seq_low | node (0-1) | | |||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
| | node (2-5) | | | node (2-5) | | |||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |||
| 4.1.3 Version | 4.1.3 Version | |||
| The version number is in the most significant four bits of the time | The version number is in the most significant four bits of the time | |||
| stamp (bits four through seven of the time_hi_and_version field). | stamp (bits four through seven of the time_hi_and_version field). | |||
| The following table lists the currently-defined versions for this | The following table lists the currently-defined versions for this | |||
| UUID variant. | UUID variant. | |||
| Msb0 Msb1 Msb2 Msb3 Version Description | Msb0 Msb1 Msb2 Msb3 Version Description | |||
| 0 0 0 1 1 The time-based version | 0 0 0 1 1 The time-based version | |||
| specified in this document. | specified in this document. | |||
| 0 0 1 0 2 DCE Security version, with | 0 0 1 0 2 DCE Security version, with | |||
| embedded POSIX UIDs. | embedded POSIX UIDs. | |||
| 0 0 1 1 3 The name-based version | 0 0 1 1 3 The name-based version | |||
| specified in this document. | specified in this document | |||
| that uses MD5 hashing. | ||||
| 0 1 0 0 4 The randomly or pseudo- | 0 1 0 0 4 The randomly or pseudo- | |||
| randomly generated version | randomly generated version | |||
| specified in this document. | specified in this document. | |||
| 0 0 1 1 5 The name-based version | ||||
| specified in this document | ||||
| that uses SHA-1 hashing. | ||||
| The version is more accurately a sub-type; again, we retain the term | The version is more accurately a sub-type; again, we retain the term | |||
| for compatibility. | for compatibility. | |||
| 4.1.4 Timestamp | 4.1.4 Timestamp | |||
| The timestamp is a 60-bit value. For UUID version 1, this is | The timestamp is a 60-bit value. For UUID version 1, this is | |||
| represented by Coordinated Universal Time (UTC) as a count of | represented by Coordinated Universal Time (UTC) as a count of | |||
| 100-nanosecond intervals since 00:00:00.00, 15 October 1582 (the date | 100-nanosecond intervals since 00:00:00.00, 15 October 1582 (the date | |||
| of Gregorian reform to the Christian calendar). | of Gregorian reform to the Christian calendar). | |||
| For systems that do not have UTC available, but do have the local | For systems that do not have UTC available, but do have the local | |||
| time, they may use that instead of UTC, as long as they do so | time, they may use that instead of UTC, as long as they do so | |||
| consistently throughout the system. This is not recommended however, | consistently throughout the system. This is not recommended however, | |||
| particularly since all that is needed to generate UTC from local time | particularly since all that is needed to generate UTC from local time | |||
| is a time zone offset. | is a time zone offset. | |||
| For UUID version 3, the timestamp is a 60-bit value constructed from | For UUID version 3 or 5, the timestamp is a 60-bit value constructed | |||
| a name as described in Section 4.3. | from a name as described in Section 4.3. | |||
| For UUID version 4, it is a randomly or pseudo-randomly generated | For UUID version 4, it is a randomly or pseudo-randomly generated | |||
| 60-bit value, as described in Section 4.4. | 60-bit value, as described in Section 4.4. | |||
| 4.1.5 Clock sequence | 4.1.5 Clock sequence | |||
| For UUID version 1, the clock sequence is used to help avoid | For UUID version 1, the clock sequence is used to help avoid | |||
| duplicates that could arise when the clock is set backwards in time | duplicates that could arise when the clock is set backwards in time | |||
| or if the node ID changes. | or if the node ID changes. | |||
| If the clock is set backwards, or even might have been set backwards | If the clock is set backwards, or even might have been set backwards | |||
| (e.g., while the system was powered off), and the UUID generator can | (e.g., while the system was powered off), and the UUID generator can | |||
| not be sure that no UUIDs were generated with timestamps larger than | not be sure that no UUIDs were generated with timestamps larger than | |||
| the value to which the clock was set, then the clock sequence has to | the value to which the clock was set, then the clock sequence has to | |||
| be changed. If the previous value of the clock sequence is known, it | be changed. If the previous value of the clock sequence is known, it | |||
| can be just incremented; otherwise it should be set to a random or | can be just incremented; otherwise it should be set to a random or | |||
| high-quality pseudo random value. | high-quality pseudo random value. | |||
| Similarly, if the node ID changes (e.g. because a network card has | Similarly, if the node ID changes (e.g. because a network card has | |||
| been moved between machines), setting the clock sequence to a random | been moved between machines), setting the clock sequence to a random | |||
| number minimizes the probability of a duplicate due to slight | number minimizes the probability of a duplicate due to slight | |||
| differences in the clock settings of the machines. (If the value of | differences in the clock settings of the machines. (If the value of | |||
| clock sequence associated with the changed node ID were known, then | clock sequence associated with the changed node ID were known, then | |||
| the clock sequence could just be incremented, but that is unlikely.) | the clock sequence could just be incremented, but that is unlikely.) | |||
| The clock sequence MUST be originally (i.e., once in the lifetime of | The clock sequence MUST be originally (i.e., once in the lifetime of | |||
| a system) initialized to a random number to minimize the correlation | a system) initialized to a random number to minimize the correlation | |||
| across systems. This provides maximum protection against node | across systems. This provides maximum protection against node | |||
| identifiers that may move or switch from system to system rapidly. | identifiers that may move or switch from system to system rapidly. | |||
| The initial value MUST NOT be correlated to the node identifier. | The initial value MUST NOT be correlated to the node identifier. | |||
| For UUID version 3, it is a 14-bit value constructed from a name as | For UUID version 3 or 5, it is a 14-bit value constructed from a name | |||
| described in Section 4.3. | as described in Section 4.3. | |||
| For UUID version 4, it is a randomly or pseudo-randomly generated | For UUID version 4, it is a randomly or pseudo-randomly generated | |||
| 14-bit value as described in Section 4.4. | 14-bit value as described in Section 4.4. | |||
| 4.1.6 Node | 4.1.6 Node | |||
| For UUID version 1, the node field consists of an IEEE 802 MAC | For UUID version 1, the node field consists of an IEEE 802 MAC | |||
| address, usually the host address. For systems with multiple IEEE 802 | address, usually the host address. For systems with multiple IEEE | |||
| addresses, any available one can be used. The lowest addressed octet | 802 addresses, any available one can be used. The lowest addressed | |||
| (octet number 10) contains the global/local bit and the unicast/ | octet (octet number 10) contains the global/local bit and the | |||
| multicast bit, and is the first octet of the address transmitted on | unicast/multicast bit, and is the first octet of the address | |||
| an 802.3 LAN. | transmitted on an 802.3 LAN. | |||
| For systems with no IEEE address, a randomly or pseudo-randomly | For systems with no IEEE address, a randomly or pseudo-randomly | |||
| generated value may be used; see Section 4.5. The multicast bit must | generated value may be used; see Section 4.5. The multicast bit must | |||
| be set in such addresses, in order that they will never conflict with | be set in such addresses, in order that they will never conflict with | |||
| addresses obtained from network cards. | addresses obtained from network cards. | |||
| For UUID version 3, the node field is a 48-bit value constructed from | For UUID version 3 or 5, the node field is a 48-bit value constructed | |||
| a name as described in Section 4.3. | from a name as described in Section 4.3. | |||
| For UUID version 4, the node field is a randomly or pseudo-randomly | For UUID version 4, the node field is a randomly or pseudo-randomly | |||
| generated 48-bit value as described in Section 4.4. | generated 48-bit value as described in Section 4.4. | |||
| 4.1.7 Nil UUID | 4.1.7 Nil UUID | |||
| The nil UUID is special form of UUID that is specified to have all | The nil UUID is special form of UUID that is specified to have all | |||
| 128 bits set to zero. | 128 bits set to zero. | |||
| 4.2 Algorithms for creating a time-based UUID | 4.2 Algorithms for creating a time-based UUID | |||
| Various aspects of the algorithm for creating a version 1 UUID are | Various aspects of the algorithm for creating a version 1 UUID are | |||
| discussed in the following sections. | discussed in the following sections. | |||
| 4.2.1 Basic algorithm | 4.2.1 Basic algorithm | |||
| The following algorithm is simple, correct, and inefficient: | The following algorithm is simple, correct, and inefficient: | |||
| o Obtain a system-wide global lock | o Obtain a system-wide global lock | |||
| o From a system-wide shared stable store (e.g., a file), read the | o From a system-wide shared stable store (e.g., a file), read the | |||
| UUID generator state: the values of the time stamp, clock | UUID generator state: the values of the time stamp, clock | |||
| sequence, and node ID used to generate the last UUID. | sequence, and node ID used to generate the last UUID. | |||
| o Get the current time as a 60-bit count of 100-nanosecond intervals | o Get the current time as a 60-bit count of 100-nanosecond intervals | |||
| since 00:00:00.00, 15 October 1582 | since 00:00:00.00, 15 October 1582 | |||
| o Get the current node ID | o Get the current node ID | |||
| o If the state was unavailable (e.g., non-existent or corrupted), or | o If the state was unavailable (e.g., non-existent or corrupted), or | |||
| skipping to change at page 10, line 37 ¶ | skipping to change at page 10, line 48 ¶ | |||
| a random clock sequence value | a random clock sequence value | |||
| o If the state was available, but the saved time stamp is later than | o If the state was available, but the saved time stamp is later than | |||
| the current time stamp, increment the clock sequence value | the current time stamp, increment the clock sequence value | |||
| o Save the state (current time stamp, clock sequence, and node ID) | o Save the state (current time stamp, clock sequence, and node ID) | |||
| back to the stable store | back to the stable store | |||
| o Release the global lock | o Release the global lock | |||
| o Format a UUID from the current time stamp, clock sequence, and | o Format a UUID from the current time stamp, clock sequence, and | |||
| node ID values according to the steps in Section 4.2.2. | node ID values according to the steps in Section 4.2.2. | |||
| If UUIDs do not need to be frequently generated, the above algorithm | If UUIDs do not need to be frequently generated, the above algorithm | |||
| may be perfectly adequate. For higher performance requirements, | may be perfectly adequate. For higher performance requirements, | |||
| however, issues with the basic algorithm include: | however, issues with the basic algorithm include: | |||
| o Reading the state from stable storage each time is inefficient | o Reading the state from stable storage each time is inefficient | |||
| o The resolution of the system clock may not be 100-nanoseconds | o The resolution of the system clock may not be 100-nanoseconds | |||
| o Writing the state to stable storage each time is inefficient | o Writing the state to stable storage each time is inefficient | |||
| o Sharing the state across process boundaries may be inefficient | o Sharing the state across process boundaries may be inefficient | |||
| Each of these issues can be addressed in a modular fashion by local | Each of these issues can be addressed in a modular fashion by local | |||
| improvements in the functions that read and write the state and read | improvements in the functions that read and write the state and read | |||
| the clock. We address each of them in turn in the following sections. | the clock. We address each of them in turn in the following | |||
| sections. | ||||
| 4.2.1.1 Reading stable storage | 4.2.1.1 Reading stable storage | |||
| The state only needs to be read from stable storage once at boot | The state only needs to be read from stable storage once at boot | |||
| time, if it is read into a system-wide shared volatile store (and | time, if it is read into a system-wide shared volatile store (and | |||
| updated whenever the stable store is updated). | updated whenever the stable store is updated). | |||
| If an implementation does not have any stable store available, then | If an implementation does not have any stable store available, then | |||
| it can always say that the values were unavailable. This is the least | it can always say that the values were unavailable. This is the | |||
| desirable implementation, because it will increase the frequency of | least desirable implementation, because it will increase the | |||
| creation of new clock sequence numbers, which increases the | frequency of creation of new clock sequence numbers, which increases | |||
| probability of duplicates. | the probability of duplicates. | |||
| If the node ID can never change (e.g., the net card is inseparable | If the node ID can never change (e.g., the net card is inseparable | |||
| from the system), or if any change also reinitializes the clock | from the system), or if any change also reinitializes the clock | |||
| sequence to a random value, then instead of keeping it in stable | sequence to a random value, then instead of keeping it in stable | |||
| store, the current node ID may be returned. | store, the current node ID may be returned. | |||
| 4.2.1.2 System clock resolution | 4.2.1.2 System clock resolution | |||
| The time stamp is generated from the system time, whose resolution | The time stamp is generated from the system time, whose resolution | |||
| may be less than the resolution of the UUID time stamp. | may be less than the resolution of the UUID time stamp. | |||
| If UUIDs do not need to be frequently generated, the time stamp can | If UUIDs do not need to be frequently generated, the time stamp can | |||
| simply be the system time multiplied by the number of 100-nanosecond | simply be the system time multiplied by the number of 100-nanosecond | |||
| intervals per system time interval. | intervals per system time interval. | |||
| If a system overruns the generator by requesting too many UUIDs | If a system overruns the generator by requesting too many UUIDs | |||
| within a single system time interval, the UUID service MUST either: | within a single system time interval, the UUID service MUST either: | |||
| return an error, or stall the UUID generator until the system clock | return an error, or stall the UUID generator until the system clock | |||
| catches up. | catches up. | |||
| A high resolution time stamp can be simulated by keeping a count of | A high resolution time stamp can be simulated by keeping a count of | |||
| how many UUIDs have been generated with the same value of the system | how many UUIDs have been generated with the same value of the system | |||
| time, and using it to construction the low-order bits of the time | time, and using it to construction the low-order bits of the time | |||
| stamp. The count will range between zero and the number of | stamp. The count will range between zero and the number of | |||
| 100-nanosecond intervals per system time interval. | 100-nanosecond intervals per system time interval. | |||
| Note: if the processors overrun the UUID generation frequently, | Note: if the processors overrun the UUID generation frequently, | |||
| additional node identifiers can be allocated to the system, which | additional node identifiers can be allocated to the system, which | |||
| will permit higher speed allocation by making multiple UUIDs | will permit higher speed allocation by making multiple UUIDs | |||
| potentially available for each time stamp value. | potentially available for each time stamp value. | |||
| 4.2.1.3 Writing stable storage | 4.2.1.3 Writing stable storage | |||
| The state does not always need to be written to stable store every | The state does not always need to be written to stable store every | |||
| time a UUID is generated. The timestamp in the stable store can be | time a UUID is generated. The timestamp in the stable store can be | |||
| periodically set to a value larger than any yet used in a UUID; as | periodically set to a value larger than any yet used in a UUID; as | |||
| long as the generated UUIDs have time stamps less than that value, | long as the generated UUIDs have time stamps less than that value, | |||
| and the clock sequence and node ID remain unchanged, only the shared | and the clock sequence and node ID remain unchanged, only the shared | |||
| volatile copy of the state needs to be updated. Furthermore, if the | volatile copy of the state needs to be updated. Furthermore, if the | |||
| time stamp value in stable store is in the future by less than the | time stamp value in stable store is in the future by less than the | |||
| typical time it takes the system to reboot, a crash will not cause a | typical time it takes the system to reboot, a crash will not cause a | |||
| reinitialization of the clock sequence. | reinitialization of the clock sequence. | |||
| 4.2.1.4 Sharing state across processes | 4.2.1.4 Sharing state across processes | |||
| If it is too expensive to access shared state each time a UUID is | If it is too expensive to access shared state each time a UUID is | |||
| generated, then the system-wide generator can be implemented to | generated, then the system-wide generator can be implemented to | |||
| allocate a block of time stamps each time it is called, and a | allocate a block of time stamps each time it is called, and a | |||
| per-process generator can allocate from that block until it is | per-process generator can allocate from that block until it is | |||
| exhausted. | exhausted. | |||
| 4.2.2 Generation details | 4.2.2 Generation details | |||
| Version 1 UUIDs are generated according to the following algorithm: | Version 1 UUIDs are generated according to the following algorithm: | |||
| o Determine the values for the UTC-based timestamp and clock | o Determine the values for the UTC-based timestamp and clock | |||
| sequence to be used in the UUID, as described in Section 4.2.1. | sequence to be used in the UUID, as described in Section 4.2.1. | |||
| o For the purposes of this algorithm, consider the timestamp to be a | o For the purposes of this algorithm, consider the timestamp to be a | |||
| 60-bit unsigned integer and the clock sequence to be a 14-bit | 60-bit unsigned integer and the clock sequence to be a 14-bit | |||
| unsigned integer. Sequentially number the bits in a field, | unsigned integer. Sequentially number the bits in a field, | |||
| starting with zero for the least significant bit. | starting with zero for the least significant bit. | |||
| o Set the time_low field equal to the least significant 32 bits | o Set the time_low field equal to the least significant 32 bits | |||
| (bits zero through 31) of the time stamp in the same order of | (bits zero through 31) of the time stamp in the same order of | |||
| significance. | significance. | |||
| o Set the time_mid field equal to bits 32 through 47 from the time | o Set the time_mid field equal to bits 32 through 47 from the time | |||
| stamp in the same order of significance. | stamp in the same order of significance. | |||
| o Set the 12 least significant bits (bits zero through 11) of the | o Set the 12 least significant bits (bits zero through 11) of the | |||
| time_hi_and_version field equal to bits 48 through 59 from the | time_hi_and_version field equal to bits 48 through 59 from the | |||
| time stamp in the same order of significance. | time stamp in the same order of significance. | |||
| o Set the four most significant bits (bits 12 through 15) of the | o Set the four most significant bits (bits 12 through 15) of the | |||
| skipping to change at page 12, line 46 ¶ | skipping to change at page 13, line 11 ¶ | |||
| of significance. | of significance. | |||
| o Set the six least significant bits (bits zero through five) of the | o Set the six least significant bits (bits zero through five) of the | |||
| clock_seq_hi_and_reserved field to the six most significant bits | clock_seq_hi_and_reserved field to the six most significant bits | |||
| (bits eight through 13) of the clock sequence in the same order of | (bits eight through 13) of the clock sequence in the same order of | |||
| significance. | significance. | |||
| o Set the two most significant bits (bits six and seven) of the | o Set the two most significant bits (bits six and seven) of the | |||
| clock_seq_hi_and_reserved to zero and one, respectively. | clock_seq_hi_and_reserved to zero and one, respectively. | |||
| o Set the node field to the 48-bit IEEE address in the same order of | o Set the node field to the 48-bit IEEE address in the same order of | |||
| significance as the address. | significance as the address. | |||
| 4.3 Algorithm for creating a name-based UUID | 4.3 Algorithm for creating a name-based UUID | |||
| The version 3 UUID is meant for generating UUIDs from "names" that | The version 3 or 5 UUID is meant for generating UUIDs from "names" | |||
| are drawn from, and unique within, some "name space." The concept of | that are drawn from, and unique within, some "name space." The | |||
| name and name space should be broadly construed, and not limited to | concept of name and name space should be broadly construed, and not | |||
| textual names. For example, some name spaces are the domain name | limited to textual names. For example, some name spaces are the | |||
| system, URLs, ISO Object IDs (OIDs), X.500 Distinguished Names (DNs), | domain name system, URLs, ISO Object IDs (OIDs), X.500 Distinguished | |||
| and reserved words in a programming language. The mechanisms or | Names (DNs), and reserved words in a programming language. The | |||
| conventions for allocating names from, and ensuring their uniqueness | mechanisms or conventions for allocating names from, and ensuring | |||
| within, their name spaces are beyond the scope of this specification. | their uniqueness within, their name spaces are beyond the scope of | |||
| this specification. | ||||
| The requirements for version 3 UUIDs are as follows: | The requirements for these types of UUIDs are as follows: | |||
| o The UUIDs generated at different times from the same name in the | o The UUIDs generated at different times from the same name in the | |||
| same namespace MUST be equal | same namespace MUST be equal | |||
| o The UUIDs generated from two different names in the same namespace | o The UUIDs generated from two different names in the same namespace | |||
| should be different (with very high probability) | should be different (with very high probability) | |||
| o The UUIDs generated from the same name in two different namespaces | o The UUIDs generated from the same name in two different namespaces | |||
| should be different with (very high probability) | should be different with (very high probability) | |||
| o If two UUIDs that were generated from names are equal, then they | o If two UUIDs that were generated from names are equal, then they | |||
| were generated from the same name in the same namespace (with very | were generated from the same name in the same namespace (with very | |||
| high probability). | high probability). | |||
| The algorithm for generating the a UUID from a name and a name space | The algorithm for generating the a UUID from a name and a name space | |||
| are as follows: | are as follows: | |||
| o Allocate a UUID to use as a "name space ID" for all UUIDs | o Allocate a UUID to use as a "name space ID" for all UUIDs | |||
| generated from names in that name space; see Appendix C for some | generated from names in that name space; see Appendix C for some | |||
| pre-defined values | pre-defined values | |||
| o Choose either MD5 [4] or SHA-1 [8] as the hash algorithm; If | ||||
| backward compatibility is not an issue, SHA-1 is preferred | ||||
| o Convert the name to a canonical sequence of octets (as defined by | o Convert the name to a canonical sequence of octets (as defined by | |||
| the standards or conventions of its name space); put the name | the standards or conventions of its name space); put the name | |||
| space ID in network byte order | space ID in network byte order | |||
| o Compute the MD5 [3] hash of the name space ID concatenated with | o Compute the hash of the name space ID concatenated with the name | |||
| the name | ||||
| o Set octets zero through three of the time_low field to octets zero | o Set octets zero through three of the time_low field to octets zero | |||
| through three of the MD5 hash | through three of the hash | |||
| o Set octets zero and one of the time_mid field to octets four and | o Set octets zero and one of the time_mid field to octets four and | |||
| five of the MD5 hash | five of the hash | |||
| o Set octets zero and one of the time_hi_and_version field to octets | o Set octets zero and one of the time_hi_and_version field to octets | |||
| six and seven of the MD5 hash | six and seven of the MD5 hash | |||
| o Set the four most significant bits (bits 12 through 15) of the | o Set the four most significant bits (bits 12 through 15) of the | |||
| time_hi_and_version field to the four-bit version number from | time_hi_and_version field to the appropriate four-bit version | |||
| Section 4.1.3. | number from Section 4.1.3 | |||
| o Set the clock_seq_hi_and_reserved field to octet eight of the MD5 | o Set the clock_seq_hi_and_reserved field to octet eight of the hash | |||
| hash | ||||
| o Set the two most significant bits (bits six and seven) of the | o Set the two most significant bits (bits six and seven) of the | |||
| clock_seq_hi_and_reserved to zero and one, respectively. | clock_seq_hi_and_reserved to zero and one, respectively. | |||
| o Set the clock_seq_low field to octet nine of the MD5 hash | o Set the clock_seq_low field to octet nine of the hash | |||
| o Set octets zero through five of the node field to octets then | o Set octets zero through five of the node field to octets ten | |||
| through fifteen of the MD5 hash | through fifteen of the hash | |||
| o Convert the resulting UUID to local byte order. | o Convert the resulting UUID to local byte order. | |||
| 4.4 Algorithms for creating a UUID from truly random or pseudo-random | 4.4 Algorithms for creating a UUID from truly random or pseudo-random | |||
| numbers | numbers | |||
| The version 4 UUID is meant for generating UUIDs from truly-random or | The version 4 UUID is meant for generating UUIDs from truly-random or | |||
| pseudo-random numbers. | pseudo-random numbers. | |||
| The algorithm is as follows: | The algorithm is as follows: | |||
| o Set the two most significant bits (bits six and seven) of the | o Set the two most significant bits (bits six and seven) of the | |||
| clock_seq_hi_and_reserved to zero and one, respectively. | clock_seq_hi_and_reserved to zero and one, respectively. | |||
| o Set the four most significant bits (bits 12 through 15) of the | o Set the four most significant bits (bits 12 through 15) of the | |||
| time_hi_and_version field to the four-bit version number from | time_hi_and_version field to the four-bit version number from | |||
| Section 4.1.3. | Section 4.1.3. | |||
| o Set all the other bits to randomly (or pseudo-randomly) chosen | o Set all the other bits to randomly (or pseudo-randomly) chosen | |||
| values. | values. | |||
| See Section 4.5 for a discussion on random numbers. | See Section 4.5 for a discussion on random numbers. | |||
| 4.5 Node IDs that do not identify the host | 4.5 Node IDs that do not identify the host | |||
| This section describes how to generate a version 1 UUID if an IEEE | This section describes how to generate a version 1 UUID if an IEEE | |||
| 802 address is not available, or its use is not desired. | 802 address is not available, or its use is not desired. | |||
| One approach is to contact the IEEE and get a separate block of | One approach is to contact the IEEE and get a separate block of | |||
| addresses. At the time of writing, the application could be found at | addresses. At the time of writing, the application could be found at | |||
| [8], and the cost was US$550. | <http://standards.ieee.org/regauth/oui/pilot-ind.html>, and the cost | |||
| was US$550. | ||||
| A better solution is to obtain a 47-bit cryptographic quality random | A better solution is to obtain a 47-bit cryptographic quality random | |||
| number, and use it as the low 47 bits of the node ID, with the least | number, and use it as the low 47 bits of the node ID, with the least | |||
| significant bit of the first octet of the node ID set to one. This | significant bit of the first octet of the node ID set to one. This | |||
| bit is the unicast/multicast bit, which will never be set in IEEE 802 | bit is the unicast/multicast bit, which will never be set in IEEE 802 | |||
| addresses obtained from network cards; hence, there can never be a | addresses obtained from network cards; hence, there can never be a | |||
| conflict between UUIDs generated by machines with and without network | conflict between UUIDs generated by machines with and without network | |||
| cards. (Recall that the IEEE 802 spec talks about transmission order, | cards. (Recall that the IEEE 802 spec talks about transmission | |||
| which is the opposite of the in-memory representation that is | order, which is the opposite of the in-memory representation that is | |||
| discussed in this document.) | discussed in this document.) | |||
| (For compatibility with earlier specifications, note that this | ||||
| document uses the unicast/multicast bit, instead of the arguably more | ||||
| correct local/global bit.) | ||||
| If a system does not have the capability to generate cryptographic | Advice on generating cryptographic-quality random numbers can be | |||
| quality random numbers, then implementation advice can be found in | found in RFC1750 [5]. | |||
| RFC1750 [4]. | ||||
| In addition, items such as the computer's name and the name of the | In addition, items such as the computer's name and the name of the | |||
| operating system, while not strictly speaking random, will help | operating system, while not strictly speaking random, will help | |||
| differentiate the results from those obtained by other systems. | differentiate the results from those obtained by other systems. | |||
| The exact algorithm to generate a node ID using these data is system | The exact algorithm to generate a node ID using these data is system | |||
| specific, because both the data available and the functions to obtain | specific, because both the data available and the functions to obtain | |||
| them are often very system specific. A generic approach, however is | them are often very system specific. A generic approach, however is | |||
| to accumulate as many sources as possible into a buffer, and use a | to accumulate as many sources as possible into a buffer, and use a | |||
| message digest such as MD5 [3] or SHA-1 [7], take an arbitrary six | message digest such as MD5 [4] or SHA-1 [8], take an arbitrary six | |||
| bytes from the hash value, and set the multicast bit as described | bytes from the hash value, and set the multicast bit as described | |||
| above. | above. | |||
| 5. Community Considerations | 5. Community Considerations | |||
| The use of UUIDs is extremely pervasive in computing. They comprise | The use of UUIDs is extremely pervasive in computing. They comprise | |||
| the core identifier infrastructure for many operating systems | the core identifier infrastructure for many operating systems | |||
| (Microsoft Windows) and applications (the Mozilla browser) and in | (Microsoft Windows) and applications (the Mozilla browser) and in | |||
| many cases, become exposed to the web in many non-standard ways. This | many cases, become exposed to the web in many non-standard ways. | |||
| specification attempts to standardize that practice as openly as | This specification attempts to standardize that practice as openly as | |||
| possible and in a way that attempts to benefit the entire Internet. | possible and in a way that attempts to benefit the entire Internet. | |||
| 6. Security Considerations | 6. Security Considerations | |||
| Do not assume that UUIDs are hard to guess; they should not be used | Do not assume that UUIDs are hard to guess; they should not be used | |||
| as security capabilities (identifiers whose mere possession grants | as security capabilities (identifiers whose mere possession grants | |||
| access), for example. | access), for example. A predictable random number source will | |||
| exacerbate the situation. | ||||
| Do not assume that it is easy to determine if a UUID has been | Do not assume that it is easy to determine if a UUID has been | |||
| slightly transposed in order to redirect a reference to another | slightly transposed in order to redirect a reference to another | |||
| object. Humans do not have the ability to easily check the integrity | object. Humans do not have the ability to easily check the integrity | |||
| of a UUID by simply glancing at it. | of a UUID by simply glancing at it. | |||
| 7. Acknowledgments | Distributed applications generating UUIDs at a variety of hosts must | |||
| be willing to rely on the random number source at all hosts. If this | ||||
| is not feasible, the namespace variant should be used. | ||||
| 7. Acknowledgments | ||||
| This document draws heavily on the OSF DCE specification for UUIDs. | This document draws heavily on the OSF DCE specification for UUIDs. | |||
| Ted Ts'o provided helpful comments, especially on the byte ordering | Ted Ts'o provided helpful comments, especially on the byte ordering | |||
| section which we mostly plagiarized from a proposed wording he | section which we mostly plagiarized from a proposed wording he | |||
| supplied (all errors in that section are our responsibility, | supplied (all errors in that section are our responsibility, | |||
| however). | however). | |||
| We are also grateful to the careful reading and bit-twiddling of | We are also grateful to the careful reading and bit-twiddling of | |||
| Ralph S. Engelschall, John Larmouth, and Paul Thorpe. | Ralph S. Engelschall, John Larmouth, and Paul Thorpe. Professor | |||
| Larmouth was also invaluable in achieving coordination with ISO/IEC. | ||||
| Normative References | 8 Normative References | |||
| [1] Zahn, L., Dineen, T. and P. Leach, "Network Computing | [1] Zahn, L., Dineen, T. and P. Leach, "Network Computing | |||
| Architecture", ISBN 0-13-611674-4, January 1990. | Architecture", ISBN 0-13-611674-4, January 1990. | |||
| [2] "DCE: Remote Procedure Call", Open Group CAE Specification C309, | [2] "DCE: Remote Procedure Call", Open Group CAE Specification C309, | |||
| ISBN 1-85912-041-5, August 1994. | ISBN 1-85912-041-5, August 1994. | |||
| [3] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April | [3] ISO/IEC 9834-8:2004 Information Technology, "Procedures for the | |||
| Operation of Registration Authorities - Generation of | ||||
| Universally Unique/Globally Unique Identifiers (UUID/GUID)", | ||||
| ITU-T Rec. X.687, 2004. | ||||
| [4] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April | ||||
| 1992. | 1992. | |||
| [4] Eastlake, D., Crocker, S. and J. Schiller, "Randomness | [5] Eastlake, D., Crocker, S. and J. Schiller, "Randomness | |||
| Recommendations for Security", RFC 1750, December 1994. | Recommendations for Security", RFC 1750, December 1994. | |||
| [5] Moats, R., "URN Syntax", RFC 2141, May 1997. | [6] Moats, R., "URN Syntax", RFC 2141, May 1997. | |||
| [6] Crocker, D. and P. Overell, "Augmented BNF for Syntax | [7] Crocker, D. and P. Overell, "Augmented BNF for Syntax | |||
| Specifications: ABNF", RFC 2234, November 1997. | Specifications: ABNF", RFC 2234, November 1997. | |||
| [7] National Institute of Standards and Technology, "Secure Hash | [8] National Institute of Standards and Technology, "Secure Hash | |||
| Standard", FIPS PUB 180-1, April 1995, <http://www.itl.nist.gov/ | Standard", FIPS PUB 180-1, April 1995, | |||
| fipspubs/fip180-1.htm>. | <http://www.itl.nist.gov/fipspubs/fip180-1.htm>. | |||
| [8] <http://standards.ieee.org/regauth/oui/pilot-ind.html> | ||||
| Authors' Addresses | Authors' Addresses | |||
| Paul J. Leach | Paul J. Leach | |||
| Microsoft | Microsoft | |||
| 1 Microsoft Way | 1 Microsoft Way | |||
| Redmond, WA 98052 | Redmond, WA 98052 | |||
| US | US | |||
| Phone: +1 425-882-8080 | Phone: +1 425-882-8080 | |||
| skipping to change at page 16, line 22 ¶ | skipping to change at page 17, line 4 ¶ | |||
| Authors' Addresses | Authors' Addresses | |||
| Paul J. Leach | Paul J. Leach | |||
| Microsoft | Microsoft | |||
| 1 Microsoft Way | 1 Microsoft Way | |||
| Redmond, WA 98052 | Redmond, WA 98052 | |||
| US | US | |||
| Phone: +1 425-882-8080 | Phone: +1 425-882-8080 | |||
| EMail: paulle@microsoft.com | EMail: paulle@microsoft.com | |||
| Michael Mealling | Michael Mealling | |||
| VeriSign, Inc. | VeriSign, Inc. | |||
| 21345 Ridgetop Circle | 21345 Ridgetop Circle | |||
| Dulles, VA 21345 | Dulles, VA 21345 | |||
| US | US | |||
| Phone: +1 770-717-0732 | Phone: +1 770-717-0732 | |||
| EMail: michael@neonym.net | EMail: michael@neonym.net | |||
| URI: http://www.verisignlabs.com | URI: http://www.verisignlabs.com | |||
| Rich Salz | Rich Salz | |||
| DataPower Technology, Inc. | DataPower Technology, Inc. | |||
| 1 Alewife Center | 1 Alewife Center | |||
| Cambridge, MA 02142 | Cambridge, MA 02142 | |||
| US | US | |||
| Phone: +1 617-864-0455 | Phone: +1 617-864-0455 | |||
| EMail: rsalz@datapower.com | EMail: rsalz@datapower.com | |||
| URI: http://www.datapower.com | URI: http://www.datapower.com | |||
| Appendix A. Appendix A - Sample Implementation | Appendix A. Appendix A - Sample Implementation | |||
| This implementation consists of 5 files: uuid.h, uuid.c, sysdep.h, | This implementation consists of 5 files: uuid.h, uuid.c, sysdep.h, | |||
| sysdep.c and utest.c. The uuid.* files are the system independent | sysdep.c and utest.c. The uuid.* files are the system independent | |||
| implementation of the UUID generation algorithms described above, | implementation of the UUID generation algorithms described above, | |||
| with all the optimizations described above except efficient state | with all the optimizations described above except efficient state | |||
| sharing across processes included. The code has been tested on Linux | sharing across processes included. The code has been tested on Linux | |||
| (Red Hat 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. The | (Red Hat 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. | |||
| code assumes 64-bit integer support, which makes it a lot clearer. | The code assumes 64-bit integer support, which makes it a lot | |||
| clearer. | ||||
| All the following source files should be considered to have the | All the following source files should be considered to have the | |||
| following copyright notice included: | following copyright notice included: | |||
| copyrt.h | copyrt.h | |||
| /* | /* | |||
| ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. | ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. | |||
| ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & | ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & | |||
| ** Digital Equipment Corporation, Maynard, Mass. | ** Digital Equipment Corporation, Maynard, Mass. | |||
| skipping to change at page 17, line 48 ¶ | skipping to change at page 18, line 28 ¶ | |||
| unsigned16 time_mid; | unsigned16 time_mid; | |||
| unsigned16 time_hi_and_version; | unsigned16 time_hi_and_version; | |||
| unsigned8 clock_seq_hi_and_reserved; | unsigned8 clock_seq_hi_and_reserved; | |||
| unsigned8 clock_seq_low; | unsigned8 clock_seq_low; | |||
| byte node[6]; | byte node[6]; | |||
| } uuid_t; | } uuid_t; | |||
| /* uuid_create -- generate a UUID */ | /* uuid_create -- generate a UUID */ | |||
| int uuid_create(uuid_t * uuid); | int uuid_create(uuid_t * uuid); | |||
| /* uuid_create_from_name -- create a UUID using a "name" | /* uuid_create_md5_from_name -- create a version 3 (MD5) UUID using a "name" | |||
| from a "name space" */ | from a "name space" */ | |||
| void uuid_create_from_name( | void uuid_create_md5_from_name( | |||
| uuid_t *uuid, /* resulting UUID */ | ||||
| uuid_t nsid, /* UUID of the namespace */ | ||||
| void *name, /* the name from which to generate a UUID */ | ||||
| int namelen /* the length of the name */ | ||||
| ); | ||||
| /* uuid_create_sha1_from_name -- create a version 5 (SHA-1) UUID using a "name" | ||||
| from a "name space" */ | ||||
| void uuid_create_sha1_from_name( | ||||
| uuid_t *uuid, /* resulting UUID */ | uuid_t *uuid, /* resulting UUID */ | |||
| uuid_t nsid, /* UUID of the namespace */ | uuid_t nsid, /* UUID of the namespace */ | |||
| void *name, /* the name from which to generate a UUID */ | void *name, /* the name from which to generate a UUID */ | |||
| int namelen /* the length of the name */ | int namelen /* the length of the name */ | |||
| ); | ); | |||
| /* uuid_compare -- Compare two UUID's "lexically" and return | /* uuid_compare -- Compare two UUID's "lexically" and return | |||
| -1 u1 is lexically before u2 | -1 u1 is lexically before u2 | |||
| 0 u1 is equal to u2 | 0 u1 is equal to u2 | |||
| 1 u1 is lexically after u2 | 1 u1 is lexically after u2 | |||
| skipping to change at page 18, line 15 ¶ | skipping to change at page 19, line 4 ¶ | |||
| uuid_t nsid, /* UUID of the namespace */ | uuid_t nsid, /* UUID of the namespace */ | |||
| void *name, /* the name from which to generate a UUID */ | void *name, /* the name from which to generate a UUID */ | |||
| int namelen /* the length of the name */ | int namelen /* the length of the name */ | |||
| ); | ); | |||
| /* uuid_compare -- Compare two UUID's "lexically" and return | /* uuid_compare -- Compare two UUID's "lexically" and return | |||
| -1 u1 is lexically before u2 | -1 u1 is lexically before u2 | |||
| 0 u1 is equal to u2 | 0 u1 is equal to u2 | |||
| 1 u1 is lexically after u2 | 1 u1 is lexically after u2 | |||
| Note that lexical ordering is not temporal ordering! | Note that lexical ordering is not temporal ordering! | |||
| */ | */ | |||
| int uuid_compare(uuid_t *u1, uuid_t *u2); | int uuid_compare(uuid_t *u1, uuid_t *u2); | |||
| uuid.c | uuid.c | |||
| #include "copyrt.h" | #include "copyrt.h" | |||
| #include <string.h> | #include <string.h> | |||
| #include <stdio.h> | #include <stdio.h> | |||
| #include <stdlib.h> | #include <stdlib.h> | |||
| #include <time.h> | #include <time.h> | |||
| #include "sysdep.h" | #include "sysdep.h" | |||
| #include "uuid.h" | #include "uuid.h" | |||
| /* various forward declarations */ | /* various forward declarations */ | |||
| static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | |||
| uuid_node_t *node); | uuid_node_t *node); | |||
| static void write_state(unsigned16 clockseq, uuid_time_t timestamp, | static void write_state(unsigned16 clockseq, uuid_time_t timestamp, | |||
| uuid_node_t node); | uuid_node_t node); | |||
| static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq, | static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq, | |||
| uuid_time_t timestamp, uuid_node_t node); | uuid_time_t timestamp, uuid_node_t node); | |||
| static void format_uuid_v3(uuid_t *uuid, unsigned char hash[16]); | static void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16], | |||
| int v); | ||||
| static void get_current_time(uuid_time_t *timestamp); | static void get_current_time(uuid_time_t *timestamp); | |||
| static unsigned16 true_random(void); | static unsigned16 true_random(void); | |||
| /* uuid_create -- generator a UUID */ | /* uuid_create -- generator a UUID */ | |||
| int uuid_create(uuid_t *uuid) | int uuid_create(uuid_t *uuid) | |||
| { | { | |||
| uuid_time_t timestamp, last_time; | uuid_time_t timestamp, last_time; | |||
| unsigned16 clockseq; | unsigned16 clockseq; | |||
| uuid_node_t node; | uuid_node_t node; | |||
| uuid_node_t last_node; | uuid_node_t last_node; | |||
| skipping to change at page 22, line 4 ¶ | skipping to change at page 22, line 42 ¶ | |||
| static unsigned16 true_random(void) | static unsigned16 true_random(void) | |||
| { | { | |||
| static int inited = 0; | static int inited = 0; | |||
| uuid_time_t time_now; | uuid_time_t time_now; | |||
| if (!inited) { | if (!inited) { | |||
| get_system_time(&time_now); | get_system_time(&time_now); | |||
| time_now = time_now / UUIDS_PER_TICK; | time_now = time_now / UUIDS_PER_TICK; | |||
| srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff)); | srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff)); | |||
| inited = 1; | inited = 1; | |||
| } | } | |||
| return rand(); | return rand(); | |||
| } | } | |||
| /* uuid_create_from_name -- create a UUID using a "name" from a "name | /* uuid_create_md5_from_name -- create a version 3 (MD5) UUID using a "name" | |||
| space" */ | from a "name space" */ | |||
| void uuid_create_from_name(uuid_t *uuid, uuid_t nsid, void *name, | void uuid_create_md5_from_name(uuid_t *uuid, uuid_t nsid, void *name, | |||
| int namelen) | int namelen) | |||
| { | { | |||
| MD5_CTX c; | MD5_CTX c; | |||
| unsigned char hash[16]; | unsigned char hash[16]; | |||
| uuid_t net_nsid; | uuid_t net_nsid; | |||
| /* put name space ID in network byte order so it hashes the same | /* put name space ID in network byte order so it hashes the same | |||
| no matter what endian machine we're on */ | no matter what endian machine we're on */ | |||
| net_nsid = nsid; | net_nsid = nsid; | |||
| htonl(net_nsid.time_low); | net_nsid.time_low = htonl(net_nsid.time_low); | |||
| htons(net_nsid.time_mid); | net_nsid.time_mid = htons(net_nsid.time_mid); | |||
| htons(net_nsid.time_hi_and_version); | net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version); | |||
| MD5Init(&c); | MD5Init(&c); | |||
| MD5Update(&c, &net_nsid, sizeof net_nsid); | MD5Update(&c, &net_nsid, sizeof net_nsid); | |||
| MD5Update(&c, name, namelen); | MD5Update(&c, name, namelen); | |||
| MD5Final(hash, &c); | MD5Final(hash, &c); | |||
| /* the hash is in network byte order at this point */ | /* the hash is in network byte order at this point */ | |||
| format_uuid_v3(uuid, hash); | format_uuid_v3or5(uuid, hash, 3); | |||
| } | } | |||
| /* format_uuid_v3 -- make a UUID from a (pseudo)random 128-bit number */ | void uuid_create_sha1_from_name(uuid_t *uuid, uuid_t nsid, void *name, | |||
| void format_uuid_v3(uuid_t *uuid, unsigned char hash[16]) | int namelen) | |||
| { | ||||
| SHA_CTX c; | ||||
| unsigned char hash[16]; | ||||
| uuid_t net_nsid; | ||||
| /* put name space ID in network byte order so it hashes the same | ||||
| no matter what endian machine we're on */ | ||||
| net_nsid = nsid; | ||||
| net_nsid.time_low = htonl(net_nsid.time_low); | ||||
| net_nsid.time_mid = htons(net_nsid.time_mid); | ||||
| net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version); | ||||
| SHA1_Init(&c); | ||||
| SHA1_Update(&c, &net_nsid, sizeof net_nsid); | ||||
| SHA1_Update(&c, name, namelen); | ||||
| SHA1_Final(hash, &c); | ||||
| /* the hash is in network byte order at this point */ | ||||
| format_uuid_v3or5(uuid, hash, 5); | ||||
| } | ||||
| /* format_uuid_v3or5 -- make a UUID from a (pseudo)random 128-bit number */ | ||||
| void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16], int v) | ||||
| { | { | |||
| /* convert UUID to local byte order */ | /* convert UUID to local byte order */ | |||
| memcpy(uuid, hash, sizeof *uuid); | memcpy(uuid, hash, sizeof *uuid); | |||
| ntohl(uuid->time_low); | uuid->time_low = ntohl(uuid->time_low); | |||
| ntohs(uuid->time_mid); | uuid->time_mid = ntohs(uuid->time_mid); | |||
| ntohs(uuid->time_hi_and_version); | uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version); | |||
| /* put in the variant and version bits */ | /* put in the variant and version bits */ | |||
| uuid->time_hi_and_version &= 0x0FFF; | uuid->time_hi_and_version &= 0x0FFF; | |||
| uuid->time_hi_and_version |= (3 << 12); | uuid->time_hi_and_version |= (v << 12); | |||
| uuid->clock_seq_hi_and_reserved &= 0x3F; | uuid->clock_seq_hi_and_reserved &= 0x3F; | |||
| uuid->clock_seq_hi_and_reserved |= 0x80; | uuid->clock_seq_hi_and_reserved |= 0x80; | |||
| } | } | |||
| /* uuid_compare -- Compare two UUID's "lexically" and return */ | /* uuid_compare -- Compare two UUID's "lexically" and return */ | |||
| #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; | #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; | |||
| int uuid_compare(uuid_t *u1, uuid_t *u2) | int uuid_compare(uuid_t *u1, uuid_t *u2) | |||
| { | { | |||
| int i; | int i; | |||
| skipping to change at page 27, line 44 ¶ | skipping to change at page 29, line 8 ¶ | |||
| uuid_create(&u); | uuid_create(&u); | |||
| printf("uuid_create(): "); puid(u); | printf("uuid_create(): "); puid(u); | |||
| f = uuid_compare(&u, &u); | f = uuid_compare(&u, &u); | |||
| printf("uuid_compare(u,u): %d\n", f); /* should be 0 */ | printf("uuid_compare(u,u): %d\n", f); /* should be 0 */ | |||
| f = uuid_compare(&u, &NameSpace_DNS); | f = uuid_compare(&u, &NameSpace_DNS); | |||
| printf("uuid_compare(u, NameSpace_DNS): %d\n", f); /* s.b. 1 */ | printf("uuid_compare(u, NameSpace_DNS): %d\n", f); /* s.b. 1 */ | |||
| f = uuid_compare(&NameSpace_DNS, &u); | f = uuid_compare(&NameSpace_DNS, &u); | |||
| printf("uuid_compare(NameSpace_DNS, u): %d\n", f); /* s.b. -1 */ | printf("uuid_compare(NameSpace_DNS, u): %d\n", f); /* s.b. -1 */ | |||
| uuid_create_from_name(&u, NameSpace_DNS, "www.widgets.com", 15); | uuid_create_md5_from_name(&u, NameSpace_DNS, "www.widgets.com", 15); | |||
| printf("uuid_create_from_name(): "); puid(u); | printf("uuid_create_md5_from_name(): "); puid(u); | |||
| } | } | |||
| Appendix B. Appendix B - Sample output of utest | Appendix B. Appendix B - Sample output of utest | |||
| uuid_create(): 7d444840-9dc0-11d1-b245-5ffdce74fad2 | uuid_create(): 7d444840-9dc0-11d1-b245-5ffdce74fad2 | |||
| uuid_compare(u,u): 0 | uuid_compare(u,u): 0 | |||
| uuid_compare(u, NameSpace_DNS): 1 | uuid_compare(u, NameSpace_DNS): 1 | |||
| uuid_compare(NameSpace_DNS, u): -1 | uuid_compare(NameSpace_DNS, u): -1 | |||
| uuid_create_from_name(): e902893a-9d22-3c7e-a7b8-d6e313b71d9f | uuid_create_md5_from_name(): e902893a-9d22-3c7e-a7b8-d6e313b71d9f | |||
| Appendix C. Appendix C - Some name space IDs | Appendix C. Appendix C - Some name space IDs | |||
| This appendix lists the name space IDs for some potentially | This appendix lists the name space IDs for some potentially | |||
| interesting name spaces, as initialized C structures and in the | interesting name spaces, as initialized C structures and in the | |||
| string representation defined above. | string representation defined above. | |||
| /* Name string is a fully-qualified domain name */ | /* Name string is a fully-qualified domain name */ | |||
| uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | |||
| 0x6ba7b810, | 0x6ba7b810, | |||
| 0x9dad, | 0x9dad, | |||
| 0x11d1, | 0x11d1, | |||
| skipping to change at page 29, line 8 ¶ | skipping to change at page 31, line 8 ¶ | |||
| uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ | uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ | |||
| 0x6ba7b814, | 0x6ba7b814, | |||
| 0x9dad, | 0x9dad, | |||
| 0x11d1, | 0x11d1, | |||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | |||
| }; | }; | |||
| Intellectual Property Statement | Intellectual Property Statement | |||
| The IETF takes no position regarding the validity or scope of any | The IETF takes no position regarding the validity or scope of any | |||
| intellectual property or other rights that might be claimed to | Intellectual Property Rights or other rights that might be claimed to | |||
| pertain to the implementation or use of the technology described in | pertain to the implementation or use of the technology described in | |||
| this document or the extent to which any license under such rights | this document or the extent to which any license under such rights | |||
| might or might not be available; neither does it represent that it | might or might not be available; nor does it represent that it has | |||
| has made any effort to identify any such rights. Information on the | made any independent effort to identify any such rights. Information | |||
| IETF's procedures with respect to rights in standards-track and | on the procedures with respect to rights in RFC documents can be | |||
| standards-related documentation can be found in BCP-11. Copies of | found in BCP 78 and BCP 79. | |||
| claims of rights made available for publication and any assurances of | ||||
| licenses to be made available, or the result of an attempt made to | Copies of IPR disclosures made to the IETF Secretariat and any | |||
| obtain a general license or permission for the use of such | assurances of licenses to be made available, or the result of an | |||
| proprietary rights by implementors or users of this specification can | attempt made to obtain a general license or permission for the use of | |||
| be obtained from the IETF Secretariat. | such proprietary rights by implementers or users of this | |||
| specification can be obtained from the IETF on-line IPR repository at | ||||
| http://www.ietf.org/ipr. | ||||
| The IETF invites any interested party to bring to its attention any | The IETF invites any interested party to bring to its attention any | |||
| copyrights, patents or patent applications, or other proprietary | copyrights, patents or patent applications, or other proprietary | |||
| rights which may cover technology that may be required to practice | rights that may cover technology that may be required to implement | |||
| this standard. Please address the information to the IETF Executive | this standard. Please address the information to the IETF at | |||
| Director. | ietf-ipr@ietf.org. | |||
| Full Copyright Statement | ||||
| Copyright (C) The Internet Society (2004). All Rights Reserved. | Disclaimer of Validity | |||
| This document and translations of it may be copied and furnished to | This document and the information contained herein are provided on an | |||
| others, and derivative works that comment on or otherwise explain it | "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS | |||
| or assist in its implementation may be prepared, copied, published | OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET | |||
| and distributed, in whole or in part, without restriction of any | ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, | |||
| kind, provided that the above copyright notice and this paragraph are | INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE | |||
| included on all such copies and derivative works. However, this | INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED | |||
| document itself may not be modified in any way, such as by removing | WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |||
| the copyright notice or references to the Internet Society or other | ||||
| Internet organizations, except as needed for the purpose of | ||||
| developing Internet standards in which case the procedures for | ||||
| copyrights defined in the Internet Standards process must be | ||||
| followed, or as required to translate it into languages other than | ||||
| English. | ||||
| The limited permissions granted above are perpetual and will not be | Copyright Statement | |||
| revoked by the Internet Society or its successors or assignees. | ||||
| This document and the information contained herein is provided on an | Copyright (C) The Internet Society (2004). This document is subject | |||
| "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING | to the rights, licenses and restrictions contained in BCP 78, and | |||
| TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING | except as set forth therein, the authors retain all their rights. | |||
| BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION | ||||
| HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF | ||||
| MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | ||||
| Acknowledgment | Acknowledgment | |||
| Funding for the RFC Editor function is currently provided by the | Funding for the RFC Editor function is currently provided by the | |||
| Internet Society. | Internet Society. | |||
| <?xml version="1.0"?> | ||||
| <!-- vim: set et sw=2 wm=5 fdm=syntax nofen: --> | ||||
| <!DOCTYPE rfc SYSTEM "rfc2629.dtd"> | ||||
| <?rfc toc="yes"?> | ||||
| <!-- change this to no to create a document with lots of whitespace --> | ||||
| <?rfc compact="yes"?> | ||||
| <rfc ipr="full2026" docName="draft-mealling-uuid-urn-03.txt"> | ||||
| <front> | ||||
| <title abbrev="UUID URN">A UUID URN Namespace</title> | ||||
| <author initials="P." surname="Leach" fullname="Paul J. Leach"> | ||||
| <organization>Microsoft</organization> | ||||
| <address> | ||||
| <postal> | ||||
| <street>1 Microsoft Way</street> | ||||
| <city>Redmond</city> <region>WA</region> <code>98052</code> | ||||
| <country>US</country> | ||||
| </postal> | ||||
| <phone>+1 425-882-8080</phone> | ||||
| <email>paulle@microsoft.com</email> | ||||
| </address> | ||||
| </author> | ||||
| <author initials="M." surname="Mealling" fullname="Michael Mealling"> | ||||
| <organization>VeriSign, Inc.</organization> | ||||
| <address> | ||||
| <postal> | ||||
| <street>21345 Ridgetop Circle</street> | ||||
| <city>Dulles</city> <region>VA</region> <code>21345</code> | ||||
| <country>US</country> | ||||
| </postal> | ||||
| <phone>+1 770-717-0732</phone> | ||||
| <email>michael@neonym.net</email> | ||||
| <uri>http://www.verisignlabs.com</uri> | ||||
| </address> | ||||
| </author> | ||||
| <author initials="R." surname="Salz" fullname="Rich Salz"> | ||||
| <organization>DataPower Technology, Inc.</organization> | ||||
| <address> | ||||
| <postal> | ||||
| <street>1 Alewife Center</street> | ||||
| <city>Cambridge</city> <region>MA</region> <code>02142</code> | ||||
| <country>US</country> | ||||
| </postal> | ||||
| <phone>+1 617-864-0455</phone> | ||||
| <email>rsalz@datapower.com</email> | ||||
| <uri>http://www.datapower.com</uri> | ||||
| </address> | ||||
| </author> | ||||
| <date month="January" year="2004" /> | ||||
| <keyword>URN, UUID</keyword> | ||||
| <abstract> | ||||
| <t>This specification defines a Uniform Resource Name namespace for | ||||
| UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | ||||
| Unique IDentifier). A UUID is 128 bits long, and can provide a | ||||
| guarantee of uniqueness across space and time. UUIDs were originally | ||||
| used in the Network Computing System (NCS) [1] and later in the Open | ||||
| Software Foundation's (OSF) Distributed Computing Environment | ||||
| <xref target="DCE"/>.</t> | ||||
| <t>This specification is derived from the latter specification with the | ||||
| kind permission of the OSF (now known as The Open Group). Earlier | ||||
| versions of this document never left draft stage; this document | ||||
| incorporates that information here.</t> | ||||
| </abstract> | ||||
| </front> | ||||
| <middle> | ||||
| <section anchor="introduction" title="Introduction"> | ||||
| <t>This specification defines a Uniform Resource Name namespace for | ||||
| UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | ||||
| Unique IDentifier). A UUID is 128 bits long, and requires no central | ||||
| registration process.</t> | ||||
| <t>The information here is meant to be a concise guide for those wishing | ||||
| to implement services using UUIDs as URNs. Nothing in this document | ||||
| should be construed to mean that it overrides the DCE standards that | ||||
| defined UUIDs to begin with.</t> | ||||
| </section> | ||||
| <section anchor="motivation" title="Motivation"> | ||||
| <t>One of the main reasons for using UUIDs is that no centralized | ||||
| authority is required to administer them (although one format uses | ||||
| IEEE 802.1 node identifiers, others do not). As a result, generation | ||||
| on demand can be completely automated, and they can be used for a wide | ||||
| variety of purposes. The UUID generation algorithm described here | ||||
| supports very high allocation rates: 10 million per second per machine | ||||
| if necessary, so that they could even be used as transaction IDs.</t> | ||||
| <t>UUIDs are of a fixed size (128 bits) which is reasonably small | ||||
| relative to other alternatives. This lends itself well to sorting, | ||||
| ordering, and hashing of all sorts, storing in databases, simple | ||||
| allocation, and ease of programming in general.</t> | ||||
| <t>Since UUIDs are unique and persistent, they make excellent Uniform | ||||
| Resource Names. The unique ability to generate a new UUID without a | ||||
| registration process allows for UUIDs to be one of the URNs with the | ||||
| lowest minting cost.</t> | ||||
| </section> | ||||
| <section anchor="template" title="Namespace Registration Template"> | ||||
| <t> | ||||
| <list style="hanging"> | ||||
| <t hangText="Namespace ID: ">UUID</t> | ||||
| <t hangText="Registration Information:"><vspace blankLines="0"/> | ||||
| Registration date: 2003-10-01</t> | ||||
| <t hangText="Declared registrant of the namespace:"><vspace blankLines="0"/> | ||||
| JTC 1/SC6 (ASN.1 Rapporteur Group)</t> | ||||
| <t hangText="Declaration of syntactic structure:"><vspace blankLines="0"/> | ||||
| A UUID is an identifier that is unique across both space and time, | ||||
| with respect to the space of all UUIDs. Since a UUID is a fixed | ||||
| size and contains a time field, it is possible for values to | ||||
| rollover (around A.D. 3400, depending on the specific algorithm | ||||
| used). A UUID can be used for multiple purposes, from tagging | ||||
| objects with an extremely short lifetime, to reliably identifying | ||||
| very persistent objects across a network. | ||||
| <vspace blankLines="1"/> | ||||
| The internal representation of a UUID is a specific sequence of | ||||
| bits in memory, as described in <xref target="specification"/>. | ||||
| In order to accurately represent a UUID as a URN, it is necessary | ||||
| to convert the bit sequence to a string representation. | ||||
| <vspace blankLines="1"/> | ||||
| Each field is treated as an integer and has its value printed as a | ||||
| zero-filled hexadecimal digit string with the most significant | ||||
| digit first. The hexadecimal values a through f are | ||||
| output as lower case characters, and are case insensitive on | ||||
| input. | ||||
| <vspace blankLines="1"/> | ||||
| The formal definition of the UUID string representation is | ||||
| provided by the following ABNF <xref | ||||
| target="RFC2234"/>:<figure><artwork><![CDATA[ | ||||
| UUID = time_low "-" time_mid "-" | ||||
| time_high_and_version "-" | ||||
| clock_seq_and_reserved | ||||
| clock_seq_low "-" node | ||||
| time_low = 4hexOctet | ||||
| time_mid = 2hexOctet | ||||
| time_high_and_version = 2hexOctet | ||||
| clock_seq_and_reserved = hexOctet | ||||
| clock_seq_low = hexOctet | ||||
| node = 6hexOctet | ||||
| hexOctet = hexDigit hexDigit | ||||
| hexDigit = | ||||
| "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / | ||||
| "a" / "b" / "c" / "d" / "e" / "f" / | ||||
| "A" / "B" / "C" / "D" / "E" / "F" | ||||
| ]]></artwork></figure> | ||||
| <vspace blankLines="1"/> | ||||
| The following is an example of the string representation of a UUID | ||||
| as a URN:<figure><artwork><![CDATA[ | ||||
| urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| <t hangText="Relevant ancillary documentation:"><vspace blankLines="0"/> | ||||
| <xref target="DCE" /> | ||||
| </t> | ||||
| <t hangText="Identifier uniqueness considerations:"><vspace blankLines="0"/> | ||||
| This document specifies three algorithms to generate UUIDs: the | ||||
| first leverages the unique values of 802.1 MAC addresses to | ||||
| guarantee uniqueness, the second another uses pseudo-random number | ||||
| generators, and the third uses cryptographic hashing and | ||||
| application-provided text strings. As a result, it is possible to | ||||
| guarantee that UUIDs generated according to the mechanisms here | ||||
| will be unique from all other UUIDs that have been or will be | ||||
| assigned.</t> | ||||
| <t hangText="Identifier persistence considerations:"><vspace blankLines="0"/> | ||||
| UUIDs are inherently very difficult to resolve in a global sense. | ||||
| This, coupled with the fact that UUIDs are temporally unique | ||||
| within their spatial context, ensures that UUIDs will remain as | ||||
| persistent as possible.</t> | ||||
| <t hangText="Process of identifier assignment:"><vspace blankLines="0"/> | ||||
| Generating a UUID does not require that it be a registration | ||||
| authority be contacted. One algorithm requires a unique value over | ||||
| space for each generator. This value is typically an IEEE 802 MAC | ||||
| address, usually already available on network-connected hosts. The | ||||
| address can be assigned from an address block obtained from the | ||||
| IEEE registration authority. If no such address is available, or | ||||
| privacy concerns make its use undesirable, | ||||
| <xref target="node-id-no-id"/> specifies two | ||||
| alternatives; another approach is to use version 3 or version 4 | ||||
| UUIDs as defined below.</t> | ||||
| <t hangText="Process for identifier resolution:"><vspace blankLines="0"/> | ||||
| Since UUIDs are not globally resolvable, this is not | ||||
| applicable.</t> | ||||
| <t hangText="Rules for Lexical Equivalence:"><vspace blankLines="0"/> | ||||
| Consider each field of the UUID to be an unsigned integer as | ||||
| shown in the table in section <xref target="uuid-layout"/>. Then, | ||||
| to compare a pair of UUIDs, arithmetically compare the | ||||
| corresponding fields from each UUID in order of significance and | ||||
| according to their data type. Two UUIDs are equal if and only if | ||||
| all the corresponding fields are equal. | ||||
| <vspace blankLines="1"/> | ||||
| As an implementation note, on many systems equality comparison can | ||||
| be performed by doing the appropriate byte-order | ||||
| canonicalization, and then treating the two UUIDs as 128-bit | ||||
| unsigned integers. | ||||
| <vspace blankLines="1"/> | ||||
| UUIDs as defined in this document can also be ordered | ||||
| lexicographically. For a pair of UUIDs, the first one follows the | ||||
| second if the most significant field in which the UUIDs differ is | ||||
| greater for the first UUID. The second precedes the first if the | ||||
| most significant field in which the UUIDs differ is greater for | ||||
| the second UUID.</t> | ||||
| <t hangText="Conformance with URN Syntax:"><vspace blankLines="0"/> | ||||
| The string representation of a UUID is fully compatible with the | ||||
| URN syntax. When converting from an bit-oriented, in-memory | ||||
| representation of a UUID into a URN, care must be taken to | ||||
| strictly adhere to the byte order issues mentioned in the string | ||||
| representation section.</t> | ||||
| <t hangText="Validation mechanism:"><vspace blankLines="0"/> | ||||
| Apart from determining if the timestamp portion of the UUID is in | ||||
| the future and therefore not yet assignable, there is no mechanism | ||||
| for determining if a UUID is 'valid' in any real sense.</t> | ||||
| <t hangText="Scope:"><vspace blankLines="0"/> | ||||
| UUIDs are global in scope.</t> | ||||
| </list> | ||||
| </t> | ||||
| </section> | ||||
| <section anchor="specification" title="Specification"> | ||||
| <section anchor="format" title="Format"> | ||||
| <t>In its most general form, all that can be said of the UUID format is | ||||
| that a UUID is 16 octets, and that some bits of the eight octet -- | ||||
| the variant field specified below -- determine finer | ||||
| structure.</t> | ||||
| <section anchor="variant" title="Variant"> | ||||
| <t>The variant field determines the layout of the UUID. That is, the | ||||
| interpretation of all other bits in the UUID depends on the | ||||
| setting of the bits in the variant field. As such, it could more | ||||
| accurately be called a type field; we retain the original term for | ||||
| compatibility. The variant field consists of a variable number of | ||||
| the most significant bits of the eighth octet of the UUID.</t> | ||||
| <t>The following table lists the contents of the variant field, | ||||
| where the letter "x" indicates a "don't-care" value. | ||||
| <figure><artwork><![CDATA[ | ||||
| Msb0 Msb1 Msb2 Description | ||||
| 0 x x Reserved, NCS backward compatibility. | ||||
| 1 0 x The variant specified in this document. | ||||
| 1 1 0 Reserved, Microsoft Corporation backward | ||||
| compatibility | ||||
| 1 1 1 Reserved for future definition. | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| <t>Interoperability (in any form) with variants other than the one | ||||
| defined here is not guaranteed. This is unlikely to be an issue | ||||
| in practice.</t> | ||||
| </section> | ||||
| <section anchor="uuid-layout" title="Layout and byte order"> | ||||
| <t>To minimize confusion about bit assignments within octets, the | ||||
| UUID record definition is defined only in terms of fields that | ||||
| are integral numbers of octets. The fields are presented with the | ||||
| most significant one first.<figure><artwork><![CDATA[ | ||||
| Field Data Type Octet Note | ||||
| # | ||||
| time_low unsigned 32 0-3 The low field of the | ||||
| bit integer timestamp | ||||
| time_mid unsigned 16 4-5 The middle field of the | ||||
| bit integer timestamp | ||||
| time_hi_and_version unsigned 16 6-7 The high field of the | ||||
| bit integer timestamp multiplexed | ||||
| with the version number | ||||
| clock_seq_hi_and_rese unsigned 8 8 The high field of the | ||||
| rved bit integer clock sequence | ||||
| multiplexed with the | ||||
| variant | ||||
| clock_seq_low unsigned 8 9 The low field of the | ||||
| bit integer clock sequence | ||||
| node unsigned 48 10-15 The spatially unique | ||||
| bit integer node identifier | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| <t>In the absence of explicit application or presentation protocol | ||||
| specification to the contrary, a UUID is encoded as a 128-bit | ||||
| object, as follows: the fields are encoded as 16 octets, with the | ||||
| sizes and order of the fields defined above, and with each field | ||||
| encoded with the Most Significant Byte first (this is known as | ||||
| network byte order). Note that the field names, particularly | ||||
| for multiplexed fields, follow historical | ||||
| practice.<figure><artwork><![CDATA[ | ||||
| 0 1 2 3 | ||||
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| | time_low | | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| | time_mid | time_hi_and_version | | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| |clk_seq_hi_res | clk_seq_low | node (0-1) | | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| | node (2-5) | | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| </section> | ||||
| <section anchor="version" title="Version"> | ||||
| <t>The version number is in the most significant four bits of the | ||||
| time stamp (bits four through seven of the time_hi_and_version | ||||
| field).</t> | ||||
| <t>The following table lists the currently-defined versions for | ||||
| this UUID variant.<figure><artwork><![CDATA[ | ||||
| Msb0 Msb1 Msb2 Msb3 Version Description | ||||
| 0 0 0 1 1 The time-based version | ||||
| specified in this document. | ||||
| 0 0 1 0 2 DCE Security version, with | ||||
| embedded POSIX UIDs. | ||||
| 0 0 1 1 3 The name-based version | ||||
| specified in this document. | ||||
| 0 1 0 0 4 The randomly or pseudo- | ||||
| randomly generated version | ||||
| specified in this document. | ||||
| ]]></artwork></figure> | ||||
| The version is more accurately a sub-type; again, we retain the | ||||
| term for compatibility.</t> | ||||
| </section> | ||||
| <section anchor="timestamp" title="Timestamp"> | ||||
| <t>The timestamp is a 60-bit value. For UUID version 1, this is | ||||
| represented by Coordinated Universal Time (UTC) as a count of | ||||
| 100-nanosecond intervals since 00:00:00.00, 15 October 1582 (the | ||||
| date of Gregorian reform to the Christian calendar).</t> | ||||
| <t>For systems that do not have UTC available, but do have the | ||||
| local time, they may use that instead of UTC, as long as they do | ||||
| so consistently throughout the system. This is not recommended | ||||
| however, particularly since all that is needed to generate UTC | ||||
| from local time is a time zone offset.</t> | ||||
| <t>For UUID version 3, the timestamp is a 60-bit value constructed | ||||
| from a name as described in <xref target="alg-name"/>.</t> | ||||
| <t>For UUID version 4, it is a randomly or pseudo-randomly | ||||
| generated 60-bit value, as described in | ||||
| <xref target="alg-rand"/>.</t> | ||||
| </section> | ||||
| <section anchor="clock-seq" title="Clock sequence"> | ||||
| <t>For UUID version 1, the clock sequence is used to help avoid | ||||
| duplicates that could arise when the clock is set backwards in | ||||
| time or if the node ID changes.</t> | ||||
| <t>If the clock is set backwards, or even might have been set | ||||
| backwards (e.g., while the system was powered off), and the UUID | ||||
| generator can not be sure that no UUIDs were generated with | ||||
| timestamps larger than the value to which the clock was set, | ||||
| then the clock sequence has to be changed. If the previous value | ||||
| of the clock sequence is known, it can be just incremented; | ||||
| otherwise it should be set to a random or high-quality pseudo | ||||
| random value.</t> | ||||
| <t>Similarly, if the node ID changes (e.g. because a network card | ||||
| has been moved between machines), setting the clock sequence to | ||||
| a random number minimizes the probability of a duplicate due to | ||||
| slight differences in the clock settings of the machines. (If | ||||
| the value of clock sequence associated with the changed node ID | ||||
| were known, then the clock sequence could just be incremented, | ||||
| but that is unlikely.)</t> | ||||
| <t>The clock sequence MUST be originally (i.e., once in the | ||||
| lifetime of a system) initialized to a random number to minimize | ||||
| the correlation across systems. This provides maximum protection | ||||
| against node identifiers that may move or switch from system to | ||||
| system rapidly. The initial value MUST NOT be correlated to the | ||||
| node identifier.</t> | ||||
| <t>For UUID version 3, it is a 14-bit value constructed from a | ||||
| name as described in <xref target="alg-name"/>.</t> | ||||
| <t>For UUID version 4, it is a randomly or pseudo-randomly | ||||
| generated 14-bit value as described in | ||||
| <xref target="alg-rand"/>.</t> | ||||
| </section> | ||||
| <section anchor="node" title="Node"> | ||||
| <t>For UUID version 1, the node field consists of an IEEE 802 | ||||
| MAC address, usually the host address. For systems with multiple | ||||
| IEEE 802 addresses, any available one can be used. The lowest | ||||
| addressed octet (octet number 10) contains the global/local bit | ||||
| and the unicast/multicast bit, and is the first octet of the | ||||
| address transmitted on an 802.3 LAN.</t> | ||||
| <t>For systems with no IEEE address, a randomly or pseudo-randomly | ||||
| generated value may be used; see <xref target="node-id-no-id"/>. | ||||
| The multicast bit must be set in such addresses, in order that | ||||
| they will never conflict with addresses obtained from network | ||||
| cards.</t> | ||||
| <t>For UUID version 3, the node field is a 48-bit value constructed | ||||
| from a name as described in <xref target="alg-name"/>.</t> | ||||
| <t>For UUID version 4, the node field is a randomly or | ||||
| pseudo-randomly generated 48-bit value as described in | ||||
| <xref target="alg-rand"/>.</t> | ||||
| </section> | ||||
| <section anchor="nil-uuid" title="Nil UUID"> | ||||
| <t>The nil UUID is special form of UUID that is specified to have | ||||
| all 128 bits set to zero.</t> | ||||
| </section> | ||||
| </section> | ||||
| <section anchor="alg-time" title="Algorithms for creating a time-based UUID"> | ||||
| <t>Various aspects of the algorithm for creating a version 1 UUID are | ||||
| discussed in the following sections.</t> | ||||
| <section anchor="alg-time-basic" title="Basic algorithm"> | ||||
| <t>The following algorithm is simple, correct, and inefficient: | ||||
| <list style="symbols"> | ||||
| <t>Obtain a system-wide global lock</t> | ||||
| <t>From a system-wide shared stable store (e.g., a file), read | ||||
| the UUID generator state: the values of the time stamp, clock | ||||
| sequence, and node ID used to generate the last UUID.</t> | ||||
| <t>Get the current time as a 60-bit count of 100-nanosecond | ||||
| intervals since 00:00:00.00, 15 October 1582</t> | ||||
| <t>Get the current node ID</t> | ||||
| <t>If the state was unavailable (e.g., non-existent or | ||||
| corrupted), or the saved node ID is different than the current | ||||
| node ID, generate a random clock sequence value</t> | ||||
| <t>If the state was available, but the saved time stamp is later | ||||
| than the current time stamp, increment the clock sequence | ||||
| value</t> | ||||
| <t>Save the state (current time stamp, clock sequence, and node | ||||
| ID) back to the stable store</t> | ||||
| <t>Release the global lock</t> | ||||
| <t>Format a UUID from the current time stamp, clock sequence, | ||||
| and node ID values according to the steps in | ||||
| <xref target="alg-time-details"/>.</t> | ||||
| </list> | ||||
| </t> | ||||
| <t>If UUIDs do not need to be frequently generated, the above | ||||
| algorithm may be perfectly adequate. For higher performance | ||||
| requirements, however, issues with the basic algorithm include: | ||||
| <list style="symbols"> | ||||
| <t>Reading the state from stable storage each time is | ||||
| inefficient</t> | ||||
| <t>The resolution of the system clock may not be | ||||
| 100-nanoseconds</t> | ||||
| <t>Writing the state to stable storage each time is | ||||
| inefficient</t> | ||||
| <t>Sharing the state across process boundaries may be | ||||
| inefficient</t> | ||||
| </list> | ||||
| </t> | ||||
| <t>Each of these issues can be addressed in a modular fashion by | ||||
| local improvements in the functions that read and write the state | ||||
| and read the clock. We address each of them in turn in the | ||||
| following sections.</t> | ||||
| <section anchor="read-stable" title="Reading stable storage"> | ||||
| <t>The state only needs to be read from stable storage once at boot | ||||
| time, if it is read into a system-wide shared volatile store (and | ||||
| updated whenever the stable store is updated).</t> | ||||
| <t>If an implementation does not have any stable store available, | ||||
| then it can always say that the values were unavailable. This is | ||||
| the least desirable implementation, because it will increase the | ||||
| frequency of creation of new clock sequence numbers, which | ||||
| increases the probability of duplicates.</t> | ||||
| <t>If the node ID can never change (e.g., the net card is inseparable | ||||
| from the system), or if any change also reinitializes the clock | ||||
| sequence to a random value, then instead of keeping it in stable | ||||
| store, the current node ID may be returned.</t> | ||||
| </section> | ||||
| <section anchor="clock-resolution" title="System clock resolution"> | ||||
| <t>The time stamp is generated from the system time, whose resolution | ||||
| may be less than the resolution of the UUID time stamp.</t> | ||||
| <t>If UUIDs do not need to be frequently generated, the time stamp | ||||
| can simply be the system time multiplied by the number of | ||||
| 100-nanosecond intervals per system time interval.</t> | ||||
| <t>If a system overruns the generator by requesting too many UUIDs | ||||
| within a single system time interval, the UUID service MUST either: | ||||
| return an error, or stall the UUID generator until the system clock | ||||
| catches up.</t> | ||||
| <t>A high resolution time stamp can be simulated by keeping a count | ||||
| of how many UUIDs have been generated with the same value of the | ||||
| system time, and using it to construction the low-order bits of the | ||||
| time stamp. The count will range between zero and the number of | ||||
| 100-nanosecond intervals per system time interval.</t> | ||||
| <t>Note: if the processors overrun the UUID generation frequently, | ||||
| additional node identifiers can be allocated to the system, which | ||||
| will permit higher speed allocation by making multiple UUIDs | ||||
| potentially available for each time stamp value.</t> | ||||
| </section> | ||||
| <section anchor="write-stable" title="Writing stable storage"> | ||||
| <t>The state does not always need to be written to stable store | ||||
| every time a UUID is generated. The timestamp in the stable store | ||||
| can be periodically set to a value larger than any yet used in a | ||||
| UUID; as long as the generated UUIDs have time stamps less than | ||||
| that value, and the clock sequence and node ID remain unchanged, | ||||
| only the shared volatile copy of the state needs to be updated. | ||||
| Furthermore, if the time stamp value in stable store is in the | ||||
| future by less than the typical time it takes the system to | ||||
| reboot, a crash will not cause a reinitialization of the clock | ||||
| sequence.</t> | ||||
| </section> | ||||
| <section anchor="share-state" title="Sharing state across processes"> | ||||
| <t>If it is too expensive to access shared state each time a UUID is | ||||
| generated, then the system-wide generator can be implemented to | ||||
| allocate a block of time stamps each time it is called, and a | ||||
| per-process generator can allocate from that block until it is | ||||
| exhausted.</t> | ||||
| </section> | ||||
| </section> | ||||
| <section anchor="alg-time-details" title="Generation details"> | ||||
| <t>Version 1 UUIDs are generated according to the following | ||||
| algorithm: | ||||
| <list style="symbols"> | ||||
| <t>Determine the values for the UTC-based timestamp and clock | ||||
| sequence to be used in the UUID, as described in | ||||
| <xref target="alg-time-basic"/>.</t> | ||||
| <t>For the purposes of this algorithm, consider the timestamp | ||||
| to be a 60-bit unsigned integer and the clock sequence to be | ||||
| a 14-bit unsigned integer. Sequentially number the bits in a | ||||
| field, starting with zero for the least significant bit.</t> | ||||
| <t>Set the time_low field equal to the least significant 32 | ||||
| bits (bits zero through 31) of the time stamp in the same | ||||
| order of significance.</t> | ||||
| <t>Set the time_mid field equal to bits 32 through 47 from the | ||||
| time stamp in the same order of significance.</t> | ||||
| <t>Set the 12 least significant bits (bits zero through 11) of | ||||
| the time_hi_and_version field equal to bits 48 through 59 | ||||
| from the time stamp in the same order of significance.</t> | ||||
| <t>Set the four most significant bits (bits 12 through 15) of | ||||
| the time_hi_and_version field to the four-bit version number | ||||
| corresponding to the UUID version being created, as shown in | ||||
| the table above.</t> | ||||
| <t>Set the clock_seq_low field to the eight least significant | ||||
| bits (bits zero through seven) of the clock sequence in the | ||||
| same order of significance.</t> | ||||
| <t>Set the six least significant bits (bits zero through five) | ||||
| of the clock_seq_hi_and_reserved field to the six most | ||||
| significant bits (bits eight through 13) of the clock | ||||
| sequence in the same order of significance.</t> | ||||
| <t>Set the two most significant bits (bits six and seven) of | ||||
| the clock_seq_hi_and_reserved to zero and one, | ||||
| respectively.</t> | ||||
| <t>Set the node field to the 48-bit IEEE address in the same | ||||
| order of significance as the address.</t> | ||||
| </list> | ||||
| </t> | ||||
| </section> | ||||
| </section> | ||||
| <section anchor="alg-name" title="Algorithm for creating a name-based UUID"> | ||||
| <t>The version 3 UUID is meant for generating UUIDs from "names" that | ||||
| are drawn from, and unique within, some "name space." The concept | ||||
| of name and name space should be broadly construed, and not limited | ||||
| to textual names. For example, some name spaces are the domain | ||||
| name system, URLs, ISO Object IDs (OIDs), X.500 Distinguished Names | ||||
| (DNs), and reserved words in a programming language. The mechanisms | ||||
| or conventions for allocating names from, and ensuring their | ||||
| uniqueness within, their name spaces are beyond the scope of this | ||||
| specification.</t> | ||||
| <t>The requirements for version 3 UUIDs are as follows: | ||||
| <list style="symbols"> | ||||
| <t>The UUIDs generated at different times from the same name in | ||||
| the same namespace MUST be equal</t> | ||||
| <t>The UUIDs generated from two different names in the same | ||||
| namespace should be different (with very high probability)</t> | ||||
| <t>The UUIDs generated from the same name in two different | ||||
| namespaces should be different with (very high probability)</t> | ||||
| <t>If two UUIDs that were generated from names are equal, then | ||||
| they were generated from the same name in the same namespace | ||||
| (with very high probability).</t> | ||||
| </list> | ||||
| </t> | ||||
| <t>The algorithm for generating the a UUID from a name and a name | ||||
| space are as follows: | ||||
| <list style="symbols"> | ||||
| <t>Allocate a UUID to use as a "name space ID" for all UUIDs | ||||
| generated from names in that name space; see | ||||
| <xref target="appendixC"/> for some pre-defined values</t> | ||||
| <t>Convert the name to a canonical sequence of octets (as defined | ||||
| by the standards or conventions of its name space); put the name | ||||
| space ID in network byte order</t> | ||||
| <t>Compute the <xref target="RFC1321">MD5</xref> hash of the name | ||||
| space ID concatenated with the name</t> | ||||
| <t>Set octets zero through three of the time_low field to octets | ||||
| zero through three of the MD5 hash</t> | ||||
| <t>Set octets zero and one of the time_mid field to octets four | ||||
| and five of the MD5 hash</t> | ||||
| <t>Set octets zero and one of the time_hi_and_version field to | ||||
| octets six and seven of the MD5 hash</t> | ||||
| <t>Set the four most significant bits (bits 12 through 15) of the | ||||
| time_hi_and_version field to the four-bit version number from | ||||
| <xref target="version"/>.</t> | ||||
| <t>Set the clock_seq_hi_and_reserved field to octet eight of the MD5 | ||||
| hash</t> | ||||
| <t>Set the two most significant bits (bits six and seven) of the | ||||
| clock_seq_hi_and_reserved to zero and one, respectively.</t> | ||||
| <t>Set the clock_seq_low field to octet nine of the MD5 hash</t> | ||||
| <t>Set octets zero through five of the node field to octets then | ||||
| through fifteen of the MD5 hash</t> | ||||
| <t>Convert the resulting UUID to local byte order.</t> | ||||
| </list> | ||||
| </t> | ||||
| </section> | ||||
| <section anchor="alg-rand" title="Algorithms for creating a UUID from truly random or pseudo-random numbers"> | ||||
| <t>The version 4 UUID is meant for generating UUIDs from truly-random or | ||||
| pseudo-random numbers.</t> | ||||
| <t>The algorithm is as follows: | ||||
| <list style="symbols"> | ||||
| <t>Set the two most significant bits (bits six and seven) of the | ||||
| clock_seq_hi_and_reserved to zero and one, respectively.</t> | ||||
| <t>Set the four most significant bits (bits 12 through 15) of the | ||||
| time_hi_and_version field to the four-bit version number from | ||||
| <xref target="version"/>.</t> | ||||
| <t>Set all the other bits to randomly (or pseudo-randomly) chosen | ||||
| values.</t> | ||||
| </list> | ||||
| </t> | ||||
| <t>See <xref target="node-id-no-id"/> for a discussion | ||||
| on random numbers.</t> | ||||
| </section> | ||||
| <section anchor="node-id-no-id" title="Node IDs that do not identify the host"> | ||||
| <t>This section describes how to generate a version 1 UUID if an IEEE | ||||
| 802 address is not available, or its use is not desired.</t> | ||||
| <t>One approach is to contact the IEEE and get a separate block of | ||||
| addresses. At the time of writing, the application could | ||||
| be found at | ||||
| <eref target="http://standards.ieee.org/regauth/oui/pilot-ind.html"/>, | ||||
| and the cost was US$550.</t> | ||||
| <t>A better solution is to obtain a 47-bit cryptographic quality | ||||
| random number, and use it as the low 47 bits of the node ID, with the | ||||
| least significant bit of the first octet of the node ID set to one. | ||||
| This bit is the unicast/multicast bit, which will never be set in | ||||
| IEEE 802 addresses obtained from network cards; hence, there can | ||||
| never be a conflict between UUIDs generated by machines with and | ||||
| without network cards. (Recall that the IEEE 802 spec talks | ||||
| about transmission order, which is the opposite of the in-memory | ||||
| representation that is discussed in this document.)</t> | ||||
| <t>If a system does not have the capability to generate cryptographic | ||||
| quality random numbers, then implementation advice can be found in | ||||
| <xref target="RFC1750">RFC1750</xref>. | ||||
| </t> | ||||
| <t>In addition, items such as the computer's name and the name of the | ||||
| operating system, while not strictly speaking random, will help | ||||
| differentiate the results from those obtained by other systems.</t> | ||||
| <t>The exact algorithm to generate a node ID using these data is system | ||||
| specific, because both the data available and the functions to obtain | ||||
| them are often very system specific. A generic approach, however is | ||||
| to accumulate as many sources as possible into a buffer, and use | ||||
| a message digest such as <xref target="RFC1321">MD5</xref> or | ||||
| <xref target="FIPS.180-1.1995">SHA-1</xref>, take an arbitrary six | ||||
| bytes from the hash value, and set the multicast bit as described | ||||
| above.</t> | ||||
| </section> | ||||
| </section> | ||||
| <section anchor="community-considerations" title="Community Considerations"> | ||||
| <t>The use of UUIDs is extremely pervasive in computing. They comprise | ||||
| the core identifier infrastructure for many operating systems | ||||
| (Microsoft Windows) and applications (the Mozilla browser) and in many | ||||
| cases, become exposed to the web in many non-standard ways. This | ||||
| specification attempts to standardize that practice as openly as | ||||
| possible and in a way that attempts to benefit the entire | ||||
| Internet.</t> | ||||
| </section> | ||||
| <section anchor="security-considerations" title="Security Considerations"> | ||||
| <t>Do not assume that UUIDs are hard to guess; they should not be used | ||||
| as security capabilities (identifiers whose mere possession grants | ||||
| access), for example.</t> | ||||
| <t>Do not assume that it is easy to determine if a UUID has been | ||||
| slightly transposed in order to redirect a reference to another | ||||
| object. Humans do not have the ability to easily check the integrity | ||||
| of a UUID by simply glancing at it.</t> | ||||
| </section> | ||||
| <section anchor="acknowledgments" title="Acknowledgments"> | ||||
| <t>This document draws heavily on the OSF DCE specification for UUIDs. | ||||
| Ted Ts'o provided helpful comments, especially on the byte ordering | ||||
| section which we mostly plagiarized from a proposed wording he | ||||
| supplied (all errors in that section are our responsibility, | ||||
| however).</t> | ||||
| <t>We are also grateful to the careful reading and bit-twiddling of | ||||
| Ralph S. Engelschall, John Larmouth, and Paul Thorpe.</t> | ||||
| </section> | ||||
| </middle> | ||||
| <back> | ||||
| <references title="Normative References"> | ||||
| <reference anchor="NCA"> | ||||
| <front> | ||||
| <title abbrev="NCA">Network Computing Architecture</title> | ||||
| <author initials="L." surname="Zahn" fullname="Lisa Zahn"> | ||||
| <organization/> | ||||
| </author> | ||||
| <author initials="T." surname="Dineen" fullname="Terence Dineen"> | ||||
| <organization /> | ||||
| </author> | ||||
| <author initials="P." surname="Leach" fullname="Paul Leach"> | ||||
| <organization/> | ||||
| </author> | ||||
| <date month="January" year="1990"/> | ||||
| </front> | ||||
| <seriesInfo name="ISBN" value="0-13-611674-4"/> | ||||
| </reference> | ||||
| <reference anchor="DCE"> | ||||
| <front> | ||||
| <title>DCE: Remote Procedure Call</title> | ||||
| <author> | ||||
| <organization/> | ||||
| </author> | ||||
| <date month="August" year="1994"/> | ||||
| </front> | ||||
| <seriesInfo name="Open Group CAE Specification" value="C309" /> | ||||
| <seriesInfo name="ISBN" value="1-85912-041-5"/> | ||||
| </reference> | ||||
| <?rfc include="reference.RFC.1321.xml" ?> | ||||
| <?rfc include="reference.RFC.1750.xml" ?> | ||||
| <?rfc include="reference.RFC.2141.xml" ?> | ||||
| <?rfc include="reference.RFC.2234.xml" ?> | ||||
| <?rfc include="reference.FIPS.180-1.1995.xml" ?> | ||||
| </references> | ||||
| <section anchor="appendixA" title="Appendix A - Sample Implementation"> | ||||
| <t>This implementation consists of 5 files: uuid.h, uuid.c, sysdep.h, | ||||
| sysdep.c and utest.c. The uuid.* files are the system independent | ||||
| implementation of the UUID generation algorithms described above, with | ||||
| all the optimizations described above except efficient state sharing | ||||
| across processes included. The code has been tested on Linux (Red Hat | ||||
| 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. The code | ||||
| assumes 64-bit integer support, which makes it a lot clearer.</t> | ||||
| <t>All the following source files should be considered to have the | ||||
| following copyright notice included:<figure><artwork><![CDATA[ | ||||
| copyrt.h | ||||
| /* | ||||
| ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. | ||||
| ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & | ||||
| ** Digital Equipment Corporation, Maynard, Mass. | ||||
| ** Copyright (c) 1998 Microsoft. | ||||
| ** To anyone who acknowledges that this file is provided "AS IS" | ||||
| ** without any express or implied warranty: permission to use, copy, | ||||
| ** modify, and distribute this file for any purpose is hereby | ||||
| ** granted without fee, provided that the above copyright notices and | ||||
| ** this notice appears in all source code copies, and that none of | ||||
| ** the names of Open Software Foundation, Inc., Hewlett-Packard | ||||
| ** Company, or Digital Equipment Corporation be used in advertising | ||||
| ** or publicity pertaining to distribution of the software without | ||||
| ** specific, written prior permission. Neither Open Software | ||||
| ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital | ||||
| ** Equipment Corporation makes any representations about the suitability | ||||
| ** of this software for any purpose. | ||||
| */ | ||||
| uuid.h | ||||
| #include "copyrt.h" | ||||
| #undef uuid_t | ||||
| typedef struct { | ||||
| unsigned32 time_low; | ||||
| unsigned16 time_mid; | ||||
| unsigned16 time_hi_and_version; | ||||
| unsigned8 clock_seq_hi_and_reserved; | ||||
| unsigned8 clock_seq_low; | ||||
| byte node[6]; | ||||
| } uuid_t; | ||||
| /* uuid_create -- generate a UUID */ | ||||
| int uuid_create(uuid_t * uuid); | ||||
| /* uuid_create_from_name -- create a UUID using a "name" | ||||
| from a "name space" */ | ||||
| void uuid_create_from_name( | ||||
| uuid_t *uuid, /* resulting UUID */ | ||||
| uuid_t nsid, /* UUID of the namespace */ | ||||
| void *name, /* the name from which to generate a UUID */ | ||||
| int namelen /* the length of the name */ | ||||
| ); | ||||
| /* uuid_compare -- Compare two UUID's "lexically" and return | ||||
| -1 u1 is lexically before u2 | ||||
| 0 u1 is equal to u2 | ||||
| 1 u1 is lexically after u2 | ||||
| Note that lexical ordering is not temporal ordering! | ||||
| */ | ||||
| int uuid_compare(uuid_t *u1, uuid_t *u2); | ||||
| uuid.c | ||||
| #include "copyrt.h" | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <time.h> | ||||
| #include "sysdep.h" | ||||
| #include "uuid.h" | ||||
| /* various forward declarations */ | ||||
| static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | ||||
| uuid_node_t *node); | ||||
| static void write_state(unsigned16 clockseq, uuid_time_t timestamp, | ||||
| uuid_node_t node); | ||||
| static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq, | ||||
| uuid_time_t timestamp, uuid_node_t node); | ||||
| static void format_uuid_v3(uuid_t *uuid, unsigned char hash[16]); | ||||
| static void get_current_time(uuid_time_t *timestamp); | ||||
| static unsigned16 true_random(void); | ||||
| /* uuid_create -- generator a UUID */ | ||||
| int uuid_create(uuid_t *uuid) | ||||
| { | ||||
| uuid_time_t timestamp, last_time; | ||||
| unsigned16 clockseq; | ||||
| uuid_node_t node; | ||||
| uuid_node_t last_node; | ||||
| int f; | ||||
| /* acquire system-wide lock so we're alone */ | ||||
| LOCK; | ||||
| /* get time, node ID, saved state from non-volatile storage */ | ||||
| get_current_time(×tamp); | ||||
| get_ieee_node_identifier(&node); | ||||
| f = read_state(&clockseq, &last_time, &last_node); | ||||
| /* if no NV state, or if clock went backwards, or node ID changed | ||||
| (e.g., new network card) change clockseq */ | ||||
| if (!f || memcmp(&node, &last_node, sizeof node)) | ||||
| clockseq = true_random(); | ||||
| else if (timestamp < last_time) | ||||
| clockseq++; | ||||
| /* save the state for next time */ | ||||
| write_state(clockseq, timestamp, node); | ||||
| UNLOCK; | ||||
| /* stuff fields into the UUID */ | ||||
| format_uuid_v1(uuid, clockseq, timestamp, node); | ||||
| return 1; | ||||
| } | ||||
| /* format_uuid_v1 -- make a UUID from the timestamp, clockseq, | ||||
| and node ID */ | ||||
| void format_uuid_v1(uuid_t* uuid, unsigned16 clock_seq, | ||||
| uuid_time_t timestamp, uuid_node_t node) | ||||
| { | ||||
| /* Construct a version 1 uuid with the information we've gathered | ||||
| plus a few constants. */ | ||||
| uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF); | ||||
| uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF); | ||||
| uuid->time_hi_and_version = | ||||
| (unsigned short)((timestamp >> 48) & 0x0FFF); | ||||
| uuid->time_hi_and_version |= (1 << 12); | ||||
| uuid->clock_seq_low = clock_seq & 0xFF; | ||||
| uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8; | ||||
| uuid->clock_seq_hi_and_reserved |= 0x80; | ||||
| memcpy(&uuid->node, &node, sizeof uuid->node); | ||||
| } | ||||
| /* data type for UUID generator persistent state */ | ||||
| typedef struct { | ||||
| uuid_time_t ts; /* saved timestamp */ | ||||
| uuid_node_t node; /* saved node ID */ | ||||
| unsigned16 cs; /* saved clock sequence */ | ||||
| } uuid_state; | ||||
| static uuid_state st; | ||||
| /* read_state -- read UUID generator state from non-volatile store */ | ||||
| int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | ||||
| uuid_node_t *node) | ||||
| { | ||||
| static int inited = 0; | ||||
| FILE *fp; | ||||
| /* only need to read state once per boot */ | ||||
| if (!inited) { | ||||
| fp = fopen("state", "rb"); | ||||
| if (fp == NULL) | ||||
| return 0; | ||||
| fread(&st, sizeof st, 1, fp); | ||||
| fclose(fp); | ||||
| inited = 1; | ||||
| } | ||||
| *clockseq = st.cs; | ||||
| *timestamp = st.ts; | ||||
| *node = st.node; | ||||
| return 1; | ||||
| } | ||||
| /* write_state -- save UUID generator state back to non-volatile storage */ | ||||
| void write_state(unsigned16 clockseq, uuid_time_t timestamp, | ||||
| uuid_node_t node) | ||||
| { | ||||
| static int inited = 0; | ||||
| static uuid_time_t next_save; | ||||
| FILE* fp; | ||||
| if (!inited) { | ||||
| next_save = timestamp; | ||||
| inited = 1; | ||||
| } | ||||
| /* always save state to volatile shared state */ | ||||
| st.cs = clockseq; | ||||
| st.ts = timestamp; | ||||
| st.node = node; | ||||
| if (timestamp >= next_save) { | ||||
| fp = fopen("state", "wb"); | ||||
| fwrite(&st, sizeof st, 1, fp); | ||||
| fclose(fp); | ||||
| /* schedule next save for 10 seconds from now */ | ||||
| next_save = timestamp + (10 * 10 * 1000 * 1000); | ||||
| } | ||||
| } | ||||
| /* get-current_time -- get time as 60-bit 100ns ticks since UUID epoch. | ||||
| Compensate for the fact that real clock resolution is | ||||
| less than 100ns. */ | ||||
| void get_current_time(uuid_time_t *timestamp) | ||||
| { | ||||
| static int inited = 0; | ||||
| static uuid_time_t time_last; | ||||
| static unsigned16 uuids_this_tick; | ||||
| uuid_time_t time_now; | ||||
| if (!inited) { | ||||
| get_system_time(&time_now); | ||||
| uuids_this_tick = UUIDS_PER_TICK; | ||||
| inited = 1; | ||||
| } | ||||
| for ( ; ; ) { | ||||
| get_system_time(&time_now); | ||||
| /* if clock reading changed since last UUID generated, */ | ||||
| if (time_last != time_now) { | ||||
| /* reset count of uuids gen'd with this clock reading */ | ||||
| uuids_this_tick = 0; | ||||
| time_last = time_now; | ||||
| break; | ||||
| } | ||||
| if (uuids_this_tick < UUIDS_PER_TICK) { | ||||
| uuids_this_tick++; | ||||
| break; | ||||
| } | ||||
| /* going too fast for our clock; spin */ | ||||
| } | ||||
| /* add the count of uuids to low order bits of the clock reading */ | ||||
| *timestamp = time_now + uuids_this_tick; | ||||
| } | ||||
| /* true_random -- generate a crypto-quality random number. | ||||
| **This sample doesn't do that.** */ | ||||
| static unsigned16 true_random(void) | ||||
| { | ||||
| static int inited = 0; | ||||
| uuid_time_t time_now; | ||||
| if (!inited) { | ||||
| get_system_time(&time_now); | ||||
| time_now = time_now / UUIDS_PER_TICK; | ||||
| srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff)); | ||||
| inited = 1; | ||||
| } | ||||
| return rand(); | ||||
| } | ||||
| /* uuid_create_from_name -- create a UUID using a "name" from a "name | ||||
| space" */ | ||||
| void uuid_create_from_name(uuid_t *uuid, uuid_t nsid, void *name, | ||||
| int namelen) | ||||
| { | ||||
| MD5_CTX c; | ||||
| unsigned char hash[16]; | ||||
| uuid_t net_nsid; | ||||
| /* put name space ID in network byte order so it hashes the same | ||||
| no matter what endian machine we're on */ | ||||
| net_nsid = nsid; | ||||
| htonl(net_nsid.time_low); | ||||
| htons(net_nsid.time_mid); | ||||
| htons(net_nsid.time_hi_and_version); | ||||
| MD5Init(&c); | ||||
| MD5Update(&c, &net_nsid, sizeof net_nsid); | ||||
| MD5Update(&c, name, namelen); | ||||
| MD5Final(hash, &c); | ||||
| /* the hash is in network byte order at this point */ | ||||
| format_uuid_v3(uuid, hash); | ||||
| } | ||||
| /* format_uuid_v3 -- make a UUID from a (pseudo)random 128-bit number */ | ||||
| void format_uuid_v3(uuid_t *uuid, unsigned char hash[16]) | ||||
| { | ||||
| /* convert UUID to local byte order */ | ||||
| memcpy(uuid, hash, sizeof *uuid); | ||||
| ntohl(uuid->time_low); | ||||
| ntohs(uuid->time_mid); | ||||
| ntohs(uuid->time_hi_and_version); | ||||
| /* put in the variant and version bits */ | ||||
| uuid->time_hi_and_version &= 0x0FFF; | ||||
| uuid->time_hi_and_version |= (3 << 12); | ||||
| uuid->clock_seq_hi_and_reserved &= 0x3F; | ||||
| uuid->clock_seq_hi_and_reserved |= 0x80; | ||||
| } | ||||
| /* uuid_compare -- Compare two UUID's "lexically" and return */ | ||||
| #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; | ||||
| int uuid_compare(uuid_t *u1, uuid_t *u2) | ||||
| { | ||||
| int i; | ||||
| CHECK(u1->time_low, u2->time_low); | ||||
| CHECK(u1->time_mid, u2->time_mid); | ||||
| CHECK(u1->time_hi_and_version, u2->time_hi_and_version); | ||||
| CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved); | ||||
| CHECK(u1->clock_seq_low, u2->clock_seq_low) | ||||
| for (i = 0; i < 6; i++) { | ||||
| if (u1->node[i] < u2->node[i]) | ||||
| return -1; | ||||
| if (u1->node[i] > u2->node[i]) | ||||
| return 1; | ||||
| } | ||||
| return 0; | ||||
| } | ||||
| #undef CHECK | ||||
| sysdep.h | ||||
| #include "copyrt.h" | ||||
| /* remove the following define if you aren't running WIN32 */ | ||||
| #define WININC 0 | ||||
| #ifdef WININC | ||||
| #include <windows.h> | ||||
| #else | ||||
| #include <sys/types.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/sysinfo.h> | ||||
| #endif | ||||
| #include "global.h" | ||||
| /* change to point to where MD5 .h's live; RFC 1321 has sample | ||||
| implementation */ | ||||
| #include "md5.h" | ||||
| /* set the following to the number of 100ns ticks of the actual | ||||
| resolution of your system's clock */ | ||||
| #define UUIDS_PER_TICK 1024 | ||||
| /* Set the following to a calls to get and release a global lock */ | ||||
| #define LOCK | ||||
| #define UNLOCK | ||||
| typedef unsigned long unsigned32; | ||||
| typedef unsigned short unsigned16; | ||||
| typedef unsigned char unsigned8; | ||||
| typedef unsigned char byte; | ||||
| /* Set this to what your compiler uses for 64-bit data type */ | ||||
| #ifdef WININC | ||||
| #define unsigned64_t unsigned __int64 | ||||
| #define I64(C) C | ||||
| #else | ||||
| #define unsigned64_t unsigned long long | ||||
| #define I64(C) C##LL | ||||
| #endif | ||||
| typedef unsigned64_t uuid_time_t; | ||||
| typedef struct { | ||||
| char nodeID[6]; | ||||
| } uuid_node_t; | ||||
| void get_ieee_node_identifier(uuid_node_t *node); | ||||
| void get_system_time(uuid_time_t *uuid_time); | ||||
| void get_random_info(char seed[16]); | ||||
| sysdep.c | ||||
| #include "copyrt.h" | ||||
| #include <stdio.h> | ||||
| #include "sysdep.h" | ||||
| /* system dependent call to get IEEE node ID. | ||||
| This sample implementation generates a random node ID. */ | ||||
| void get_ieee_node_identifier(uuid_node_t *node) | ||||
| { | ||||
| static inited = 0; | ||||
| static uuid_node_t saved_node; | ||||
| char seed[16]; | ||||
| FILE *fp; | ||||
| if (!inited) { | ||||
| fp = fopen("nodeid", "rb"); | ||||
| if (fp) { | ||||
| fread(&saved_node, sizeof saved_node, 1, fp); | ||||
| fclose(fp); | ||||
| } | ||||
| else { | ||||
| get_random_info(seed); | ||||
| seed[0] |= 0x01; | ||||
| memcpy(&saved_node, seed, sizeof saved_node); | ||||
| fp = fopen("nodeid", "wb"); | ||||
| if (fp) { | ||||
| fwrite(&saved_node, sizeof saved_node, 1, fp); | ||||
| fclose(fp); | ||||
| } | ||||
| } | ||||
| inited = 1; | ||||
| } | ||||
| *node = saved_node; | ||||
| } | ||||
| /* system dependent call to get the current system time. Returned as | ||||
| 100ns ticks since UUID epoch, but resolution may be less than 100ns. */ | ||||
| #ifdef _WINDOWS_ | ||||
| void get_system_time(uuid_time_t *uuid_time) | ||||
| { | ||||
| ULARGE_INTEGER time; | ||||
| /* NT keeps time in FILETIME format which is 100ns ticks since | ||||
| Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. | ||||
| The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) | ||||
| + 18 years and 5 leap days. */ | ||||
| GetSystemTimeAsFileTime((FILETIME *)&time); | ||||
| time.QuadPart += | ||||
| (unsigned __int64) (1000*1000*10) // seconds | ||||
| * (unsigned __int64) (60 * 60 * 24) // days | ||||
| * (unsigned __int64) (17+30+31+365*18+5); // # of days | ||||
| *uuid_time = time.QuadPart; | ||||
| } | ||||
| /* Sample code, not for use in production; see RFC 1750 */ | ||||
| void get_random_info(char seed[16]) | ||||
| { | ||||
| MD5_CTX c; | ||||
| struct { | ||||
| MEMORYSTATUS m; | ||||
| SYSTEM_INFO s; | ||||
| FILETIME t; | ||||
| LARGE_INTEGER pc; | ||||
| DWORD tc; | ||||
| DWORD l; | ||||
| char hostname[MAX_COMPUTERNAME_LENGTH + 1]; | ||||
| } r; | ||||
| MD5Init(&c); | ||||
| GlobalMemoryStatus(&r.m); | ||||
| GetSystemInfo(&r.s); | ||||
| GetSystemTimeAsFileTime(&r.t); | ||||
| QueryPerformanceCounter(&r.pc); | ||||
| r.tc = GetTickCount(); | ||||
| r.l = MAX_COMPUTERNAME_LENGTH + 1; | ||||
| GetComputerName(r.hostname, &r.l); | ||||
| MD5Update(&c, &r, sizeof r); | ||||
| MD5Final(seed, &c); | ||||
| } | ||||
| #else | ||||
| void get_system_time(uuid_time_t *uuid_time) | ||||
| { | ||||
| struct timeval tp; | ||||
| gettimeofday(&tp, (struct timezone *)0); | ||||
| /* Offset between UUID formatted times and Unix formatted times. | ||||
| UUID UTC base time is October 15, 1582. | ||||
| Unix base time is January 1, 1970.*/ | ||||
| *uuid_time = ((unsigned64)tp.tv_sec * 10000000) | ||||
| + ((unsigned64)tp.tv_usec * 10) | ||||
| + I64(0x01B21DD213814000); | ||||
| } | ||||
| /* Sample code, not for use in production; see RFC 1750 */ | ||||
| void get_random_info(char seed[16]) | ||||
| { | ||||
| MD5_CTX c; | ||||
| struct { | ||||
| struct sysinfo s; | ||||
| struct timeval t; | ||||
| char hostname[257]; | ||||
| } r; | ||||
| MD5Init(&c); | ||||
| sysinfo(&r.s); | ||||
| gettimeofday(&r.t, (struct timezone *)0); | ||||
| gethostname(r.hostname, 256); | ||||
| MD5Update(&c, &r, sizeof r); | ||||
| MD5Final(seed, &c); | ||||
| } | ||||
| #endif | ||||
| utest.c | ||||
| #include "copyrt.h" | ||||
| #include "sysdep.h" | ||||
| #include <stdio.h> | ||||
| #include "uuid.h" | ||||
| uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | ||||
| 0x6ba7b810, | ||||
| 0x9dad, | ||||
| 0x11d1, | ||||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | ||||
| }; | ||||
| /* puid -- print a UUID */ | ||||
| void puid(uuid_t u) | ||||
| { | ||||
| int i; | ||||
| printf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", u.time_low, u.time_mid, | ||||
| u.time_hi_and_version, u.clock_seq_hi_and_reserved, | ||||
| u.clock_seq_low); | ||||
| for (i = 0; i < 6; i++) | ||||
| printf("%2.2x", u.node[i]); | ||||
| printf("\n"); | ||||
| } | ||||
| /* Simple driver for UUID generator */ | ||||
| void main(int argc, char **argv) | ||||
| { | ||||
| uuid_t u; | ||||
| int f; | ||||
| uuid_create(&u); | ||||
| printf("uuid_create(): "); puid(u); | ||||
| f = uuid_compare(&u, &u); | ||||
| printf("uuid_compare(u,u): %d\n", f); /* should be 0 */ | ||||
| f = uuid_compare(&u, &NameSpace_DNS); | ||||
| printf("uuid_compare(u, NameSpace_DNS): %d\n", f); /* s.b. 1 */ | ||||
| f = uuid_compare(&NameSpace_DNS, &u); | ||||
| printf("uuid_compare(NameSpace_DNS, u): %d\n", f); /* s.b. -1 */ | ||||
| uuid_create_from_name(&u, NameSpace_DNS, "www.widgets.com", 15); | ||||
| printf("uuid_create_from_name(): "); puid(u); | ||||
| } | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| </section> | ||||
| <section anchor="appendixB" title="Appendix B - Sample output of utest"> | ||||
| <t><figure><artwork><![CDATA[ | ||||
| uuid_create(): 7d444840-9dc0-11d1-b245-5ffdce74fad2 | ||||
| uuid_compare(u,u): 0 | ||||
| uuid_compare(u, NameSpace_DNS): 1 | ||||
| uuid_compare(NameSpace_DNS, u): -1 | ||||
| uuid_create_from_name(): e902893a-9d22-3c7e-a7b8-d6e313b71d9f | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| </section> | ||||
| <section anchor="appendixC" title="Appendix C - Some name space IDs"> | ||||
| <t>This appendix lists the name space IDs for some potentially | ||||
| interesting name spaces, as initialized C structures and in the string | ||||
| representation defined above. | ||||
| <figure><artwork><![CDATA[ | ||||
| /* Name string is a fully-qualified domain name */ | ||||
| uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | ||||
| 0x6ba7b810, | ||||
| 0x9dad, | ||||
| 0x11d1, | ||||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | ||||
| }; | ||||
| /* Name string is a URL */ | ||||
| uuid_t NameSpace_URL = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */ | ||||
| 0x6ba7b811, | ||||
| 0x9dad, | ||||
| 0x11d1, | ||||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | ||||
| }; | ||||
| /* Name string is an ISO OID */ | ||||
| uuid_t NameSpace_OID = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */ | ||||
| 0x6ba7b812, | ||||
| 0x9dad, | ||||
| 0x11d1, | ||||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | ||||
| }; | ||||
| /* Name string is an X.500 DN (in DER or a text output format) */ | ||||
| uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ | ||||
| 0x6ba7b814, | ||||
| 0x9dad, | ||||
| 0x11d1, | ||||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | ||||
| }; | ||||
| ]]></artwork></figure> | ||||
| </t> | ||||
| </section> | ||||
| </back> | ||||
| </rfc> | ||||
| End of changes. 138 change blocks. | ||||
| 255 lines changed or deleted | 314 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||