| < draft-mealling-uuid-urn-00.txt | draft-mealling-uuid-urn-01.txt > | |||
|---|---|---|---|---|
| Network Working Group M. Mealling | Network Working Group P. Leach | |||
| Internet-Draft VeriSign, Inc. | Internet-Draft Microsoft | |||
| Expires: April 1, 2003 P. Leach | Expires: April 2, 2004 M. Mealling | |||
| Microsoft | VeriSign, Inc. | |||
| R. Salz | R. Salz | |||
| Datapower Technology, Inc. | DataPower Technology, Inc. | |||
| October 2002 | October 3, 2003 | |||
| A UUID URN Namespace | A UUID URN Namespace | |||
| draft-mealling-uuid-urn-00.txt | draft-mealling-uuid-urn-01.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 in full conformance with | |||
| all provisions of Section 10 of RFC2026. | all provisions of Section 10 of RFC2026. | |||
| 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 | Task Force (IETF), its areas, and its working groups. Note that other | |||
| other groups may also distribute working documents as Internet- | groups may also distribute working documents as Internet-Drafts. | |||
| 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 http:// | |||
| www.ietf.org/ietf/1id-abstracts.txt. | 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 April 1, 2003. | This Internet-Draft will expire on April 2, 2004. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (C) The Internet Society (2002). All Rights Reserved. | Copyright (C) The Internet Society (2003). All Rights Reserved. | |||
| 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 | UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | |||
| (Globally Unique IDentifier). A UUID is 128 bits long, and if | Unique IDentifier). A UUID is 128 bits long, and can provide a | |||
| generated according to the one of the mechanisms in this document, is | guarantee of uniqueness across space and time. UUIDs were originally | |||
| either guaranteed to be different from all other UUIDs/GUIDs | used in the Network Computing System (NCS) [1] and later in the Open | |||
| generated until 3400 A.D. or extremely likely to be different | Software Foundation's (OSF) Distributed Computing Environment [2]. | |||
| (depending on the mechanism chosen). UUIDs were originally used in | ||||
| the Network Computing System (NCS) [1] and later in the Open Software | ||||
| Foundation's (OSF) Distributed Computing Environment [2]. | ||||
| This specification is derived from the latter specification with the | This specification is derived from the latter specification with the | |||
| kind permission of the OSF. The original version of this document | kind permission of the OSF (now known as The Open Group). Earlier | |||
| was written by Paul Leach and Rich Salz but was unpublished for | versions of this document never left draft stage; this document | |||
| several years. This is an updated version incorporated as part of | incorporates that information here. | |||
| the URN registration document. | ||||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 4 | 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
| 3. Namespace Registration Template . . . . . . . . . . . . . . 4 | 3. Namespace Registration Template . . . . . . . . . . . . . . 3 | |||
| 4. Specification . . . . . . . . . . . . . . . . . . . . . . . 7 | 4. Specification . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 | 4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . . . . 7 | 4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1.2 UUID Layout . . . . . . . . . . . . . . . . . . . . . . . . 8 | 4.1.2 Layout and byte order . . . . . . . . . . . . . . . . . . . 6 | |||
| 4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | 4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . . . . 10 | 4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . . . . 10 | 4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 | 4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . . . . 11 | 4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . . . . 10 | |||
| 4.2 Algorithms for creating a time-based UUID . . . . . . . . . 12 | 4.2 Algorithms for creating a time-based UUID . . . . . . . . . 10 | |||
| 4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . . . . 12 | 4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . . . . 10 | |||
| 4.2.2 Reading stable storage . . . . . . . . . . . . . . . . . . . 13 | 4.2.2 Generation details . . . . . . . . . . . . . . . . . . . . . 12 | |||
| 4.2.3 System clock resolution . . . . . . . . . . . . . . . . . . 13 | 4.3 Algorithm for creating a name-based UUID . . . . . . . . . . 13 | |||
| 4.2.4 Writing stable storage . . . . . . . . . . . . . . . . . . . 14 | 4.4 Algorithms for creating a UUID from truly random or | |||
| 4.2.5 Sharing state across processes . . . . . . . . . . . . . . . 14 | pseudo-random numbers . . . . . . . . . . . . . . . . . . . 14 | |||
| 4.2.6 UUID Generation details . . . . . . . . . . . . . . . . . . 14 | 4.5 Node IDs that do not identify the host . . . . . . . . . . . 15 | |||
| 4.3 Algorithm for creating a name-based UUID . . . . . . . . . . 15 | 5. Community Considerations . . . . . . . . . . . . . . . . . . 16 | |||
| 5. Algorithms for creating a UUID from truly random or | 6. Security Considerations . . . . . . . . . . . . . . . . . . 17 | |||
| pseudo-random numbers . . . . . . . . . . . . . . . . . . . 16 | 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 17 | |||
| 6. Byte order of UUIDs . . . . . . . . . . . . . . . . . . . . 17 | Normative References . . . . . . . . . . . . . . . . . . . . 17 | |||
| 7. Node IDs when no IEEE 802 network card is available . . . . 17 | Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 18 | |||
| 8. Obtaining IEEE 802 addresses . . . . . . . . . . . . . . . . 19 | A. Appendix A - Sample Implementation . . . . . . . . . . . . . 18 | |||
| 9. Community Considerations . . . . . . . . . . . . . . . . . . 19 | B. Appendix B - Sample output of utest . . . . . . . . . . . . 29 | |||
| 10. Security Considerations . . . . . . . . . . . . . . . . . . 20 | C. Appendix C - Some name space IDs . . . . . . . . . . . . . . 29 | |||
| 11. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 20 | Intellectual Property and Copyright Statements . . . . . . . 31 | |||
| Normative References . . . . . . . . . . . . . . . . . . . . 20 | ||||
| Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 21 | ||||
| A. Appendix A - UUID Sample Implementation . . . . . . . . . . 21 | ||||
| B. Appendix B - Sample output of utest . . . . . . . . . . . . 33 | ||||
| C. Appendix C - Some name space IDs . . . . . . . . . . . . . . 33 | ||||
| Full Copyright Statement . . . . . . . . . . . . . . . . . . 35 | ||||
| 1. Introduction | 1. Introduction | |||
| This specification defines a Uniform Resource Name (URN) [4] | This specification defines a Uniform Resource Name namespace for | |||
| namespace for UUIDs (Universally Unique IDentifiers), also known as | UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally | |||
| GUIDs (Globally Unique IDentifiers). A UUID is 128 bits long, and if | Unique IDentifier). A UUID is 128 bits long, and requires no central | |||
| generated according to the one of the mechanisms in this document, is | registration process. | |||
| either guaranteed to be different from all other UUIDs/GUIDs | ||||
| generated until 3400 A.D. or extremely likely to be different | ||||
| (depending on the mechanism chosen). | ||||
| It is extremely important to note that most of the text in this | The information here is meant to be a concise guide for those wishing | |||
| document originated with Paul Leach and Rich Salz. It has been | to implement services using UUIDs as URNs. Nothing in this document | |||
| modified in order to be compliant with URN namespace registration | should be construed to mean that it supersedes the DCE standards that | |||
| procedures. Nothing in this document should be construed to mean | defined UUIDs to begin with. | |||
| that it supercedes the DCE standards that defined UUIDs to begin | ||||
| with. The information here is simply meant as a concise guide for | ||||
| those wishing to implement services using UUIDs as URNs. | ||||
| 2. Motivation | 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 (beyond the one that | authority is required to administer them (although one format uses | |||
| allocates IEEE 802.1 node identifiers). As a result, generation on | IEEE 802.1 node identifiers, others do not). As a result, generation | |||
| demand can be completely automated, and they can be used for a wide | on demand can be completely automated, and they can be used for a | |||
| variety of purposes. The UUID generation algorithm described here | wide variety of purposes. The UUID generation algorithm described | |||
| supports very high allocation rates: 10 million per second per | here supports very high allocation rates: 10 million per second per | |||
| machine if you need it, so that they could even be used as | machine if necessary, so that they could even be used as transaction | |||
| transaction IDs. | IDs. | |||
| UUIDs are fixed-size (128-bits) which is reasonably small relative to | UUIDs are of a fixed size (128-bits) which is reasonably small | |||
| other alternatives. This fixed, relatively small size lends itself | relative to other alternatives. This lends itself well to sorting, | |||
| well to sorting, ordering, and hashing of all sorts, storing in | ordering, and hashing of all sorts, storing in databases, simple | |||
| databases, simple allocation, and ease of programming in general. | allocation, and ease of programming in general. | |||
| Since UUIDs are unique and persistent given correct time settings, | Since UUIDs are unique and persistent, they make excellent Uniform | |||
| they make excellent Uniform Resource Names. The unique ability to | Resource Names. The unique ability to generate a new UUID without a | |||
| generate new UUIDs without a registration process allows for UUIDs to | registration process allows for UUIDs to be one of the URNs with the | |||
| be one the URN 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: 2002-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. To be precise, the UUID | with respect to the space of all UUIDs. Since a UUID is a fixed | |||
| consists of a finite bit space. Thus the time value used for | size and contains a time field, it is possible for values to | |||
| constructing a UUID is limited and will roll over in the future | rollover (around A.D. 3400, depending on the specific algorithm | |||
| (approximately at A.D. 3400, based on the specified algorithm). | used). A UUID can be used for multiple purposes, from tagging | |||
| A UUID can be used for multiple purposes, from tagging objects | objects with an extremely short lifetime, to reliably identifying | |||
| with an extremely short lifetime, to reliably identifying very | very persistent objects across a network. | |||
| persistent objects across a network. | ||||
| The internal representation of a UUID is a specfic sequence of | The internal representation of a UUID is a specific sequence of | |||
| bits in memory. In order to accurately represent a UUID as a URN | bits in memory, as described in Section 4. In order to accurately | |||
| it is necessary to convert the bit sequence to a string | represent a UUID as a URN, it is necessary to convert the bit | |||
| representation. The exact sequence and meaning of this bit | sequence to a string representation. | |||
| sequence is covered in Section 4 | ||||
| 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 to f inclusive are output | digit first. The hexadecimal values a through f are output as | |||
| as lower case characters, and are case insensitive on input. The | lower case characters, and are case insensitive on input. | |||
| sequence is the same as the UUID constructed type. | ||||
| The formal definition of the UUID string representation is | The formal definition of the UUID string representation is | |||
| provided by the following extended BNF: | provided by the following extended BNF: | |||
| 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 = 4*<hexOctet> | time_low = 4*<hexOctet> | |||
| time_mid = 2*<hexOctet> | time_mid = 2*<hexOctet> | |||
| time_high_and_version = 2*<hexOctet> | time_high_and_version = 2*<hexOctet> | |||
| clock_seq_and_reserved = <hexOctet> | clock_seq_and_reserved = <hexOctet> | |||
| clock_seq_low = <hexOctet> | clock_seq_low = <hexOctet> | |||
| node = 6*<hexOctet | node = 6*<hexOctet | |||
| 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: | |||
| Due to the combination of spacial and temporal components and the | This document specifies three algorithms to generate UUIDs: the | |||
| fact that spatial uniqueness is maintained via 802.1 MAC | first leverages the unique values of 802.1 MAC addresses to | |||
| addresses, all UUIDs that are generated according to the standards | guarantee uniqueness, the second another uses pseudo-random number | |||
| and techniques mentioned in this document are unique from all | generators, and the third uses cryptographic hashing and | |||
| other UUIDs that have been or will be assigned. | 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. | ||||
| 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: | |||
| The generation of UUIDs does not require that a registration | Generating a UUID does not require that it be a registration | |||
| authority be contacted for each identifier. Instead, it requires | authority be contacted. One algorithm requires a unique value over | |||
| a unique value over space for each UUID generator. This spatially | space for each generator. This value is typically an IEEE 802 | |||
| unique value is specified as an IEEE 802 address, which is usually | address, usually already available on network-connected hosts. The | |||
| already available to network-connected systems. This 48-bit | address can be assigned from an address block obtained from the | |||
| address can be assigned based on an address block obtained through | IEEE registration authority. If no such address is available, or | |||
| the IEEE registration authority. This section of the UUID | privacy concerns make its use undesirable, Section 4.5 specifies | |||
| specification assumes the availability of an IEEE 802 address to a | two alternatives; another approach is to use version 3 or version | |||
| system desiring to generate a UUID, but if one is not available | 4 UUIDs as defined below. | |||
| Section 7 specifies a way to generate a probabilistically unique | ||||
| one that can not conflict with any properly assigned IEEE 802 | ||||
| address. | ||||
| Process for identifier resolution: | Process for identifier resolution: | |||
| Due to UUIDs not being globally resolvable, this value is not | Since UUIDs are not globally resolvable, this is not applicable. | |||
| 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 3.1. Then, to compare a pair of UUIDs, | in the table in section Section 4.1.2. Then, to compare a pair of | |||
| arithmetically compare the corresponding fields from each UUID in | UUIDs, arithmetically compare the corresponding fields from each | |||
| order of significance and according to their data type. Two UUIDs | UUID in order of significance and according to their data type. | |||
| are equal if and only if all the corresponding fields are equal. | Two UUIDs are equal if and only if all the corresponding fields | |||
| are equal. | ||||
| Note: as a practical matter, on many systems comparison of two | As an implementation note, on many systems equality comparison can | |||
| UUIDs for equality can be performed simply by comparing the 128 | be performed by doing the appropriate byte-order canonicalization, | |||
| bits of their in-memory representation considered as a 128 bit | and then treating the two UUIDs as 128-bit unsigned integers. | |||
| unsigned integer. Here, it is presumed that by the time the in- | ||||
| memory representation is obtained the appropriate byte-order | ||||
| canonicalizations have been carried out. | ||||
| Two UUIDs allocated according to the same variant can also be | UUIDs as defined in this document can also be ordered | |||
| ordered lexicographically. For the UUID variant herein defined, | lexicographically. For a pair of UUIDs, the first one follows the | |||
| the first of two UUIDs follows the second if the most significant | second if the most significant field in which the UUIDs differ is | |||
| field in which the UUIDs differ is greater for the first UUID. | greater for the first UUID. The second precedes the first if the | |||
| The first of a pair of UUIDs precedes the second if the most | most significant field in which the UUIDs differ is greater for | |||
| significant field in which the UUIDs differ is greater for the | the second UUID. | |||
| second UUID. | ||||
| Conformance with URN Syntax: | Conformance with URN Syntax: | |||
| The string representation of a UUID produces a string that is | The string representation of a UUID is fully compatible with the | |||
| fully compatible with the URN syntax. When converting from an | URN syntax. When converting from an bit-oriented, in-memory | |||
| bit-oriented, in-memory representation of a UUID into a URN, care | representation of a UUID into a URN, care must be taken to | |||
| must be taken to strictly adhere to the byte order issues | strictly adhere to the byte order issues mentioned in the string | |||
| mentioned in the string representation section. | representation section. | |||
| Validation mechanism: | Validation mechanism: | |||
| Appart 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 thus no yet assignable, there is no mechanism for | the future and therefore not yet assignable, there is no mechanism | |||
| 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 octet 8 of the UUID | that a UUID is 16 octets, and that some bits of the eight octet -- | |||
| called the variant field (specified in the next section) determine | the variant field specified below -- determine finer structure. | |||
| 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. The variant field consists of a | of the bits in the variant field. As such, it could more accurately | |||
| variable number of the msbs of octet 8 of the UUID. | 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. | ||||
| The following table lists the contents of the variant field. | The following table lists the contents of the variant field, where | |||
| the letter "x" indicates a "don't-care" value. | ||||
| Msb0 Msb1 Msb2 Description | Msb0 Msb1 Msb2 Description | |||
| 0 - - Reserved, NCS backward compatibility. | 0 x x Reserved, NCS backward compatibility. | |||
| 1 0 - 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. | |||
| Other UUID variants may not interoperate with the UUID variant | Interoperability (in any form) with variants other than the one | |||
| specified in this document, where interoperability is defined as the | defined here is not guaranteed. This is unlikely to be an issue in | |||
| applicability of operations such as string conversion and lexical | practice. | |||
| ordering across different systems. However, UUIDs allocated | ||||
| according to the stricture of different variants, though they may | ||||
| define different interpretations of the bits outside the variant | ||||
| field, will not result in duplicate UUID allocation, because of the | ||||
| differing values of the variant field itself. | ||||
| The remaining fields described below (version, timestamp, etc.) are | 4.1.2 Layout and byte order | |||
| defined only for the UUID variant noted above. | 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. | ||||
| 4.1.2 UUID Layout | Field Data Type Octet Note | |||
| # | ||||
| The following table gives the format of a UUID for the variant | time_low unsigned 32 0-3 The low field of the | |||
| specified herein. The UUID consists of a record of 16 octets. To | bit integer timestamp | |||
| 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 in order of significance | ||||
| for comparison purposes, with "time_low" the most significant, and | ||||
| "node" the least significant. | ||||
| Field Data Type Octet Note | time_mid unsigned 16 4-5 The middle field of the | |||
| # | bit integer timestamp | |||
| time_low unsigned 32 0-3 The low field of the | time_hi_and_version unsigned 16 6-7 The high field of the | |||
| bit integer timestamp. | bit integer timestamp multiplexed | |||
| with the version number | ||||
| time_mid unsigned 16 4-5 The middle field of the | clock_seq_hi_and_rese unsigned 8 8 The high field of the | |||
| bit integer timestamp. | rved bit integer clock sequence | |||
| multiplexed with the | ||||
| variant | ||||
| time_hi_and_version unsigned 16 6-7 The high field of the | clock_seq_low unsigned 8 9 The low field of the | |||
| bit integer timestamp multiplexed | bit integer clock sequence | |||
| with the version number. | ||||
| clock_seq_hi_and_rese unsigned 8 8 The high field of the | node unsigned 48 10-15 The spatially unique | |||
| rved bit integer clock sequence | bit integer node identifier | |||
| multiplexed with the | ||||
| variant. | ||||
| clock_seq_low unsigned 8 9 The low field of the | In the absence of explicit application or presentation protocol | |||
| bit integer clock sequence. | 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). | ||||
| node unsigned 48 10-15 The spatially unique | 0 1 2 3 | |||
| bit integer node identifier. | 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) | | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| 4.1.3 Version | 4.1.3 Version | |||
| The version number is in the most significant 4 bits of the time | The version number is in the most significant four bits of the time | |||
| stamp (time_hi_and_version). | stamp (time_hi_and_version). | |||
| The following table lists currently defined versions of the UUID. | The following table lists the currently-defined versions for this | |||
| 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 | specified in this document. | |||
| document. | ||||
| 0 0 1 0 2 Reserved for DCE | 0 0 1 0 2 DCE Security version, with | |||
| 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. | |||
| 0 1 0 0 4 The randomly or pseudo- | 0 1 0 0 4 The randomly or pseudo- | |||
| randomly generated | randomly generated version | |||
| version specified in | specified in this document. | |||
| this document | ||||
| The version is more accurately a sub-type; again, we retain the term | ||||
| 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 100- | represented by Coordinated Universal Time (UTC) as a count of | |||
| nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of | 100-nanosecond intervals since 00:00:00.00, 15 October 1582 (the date | |||
| Gregorian reform to the Christian calendar). | of Gregorian reform to the Christian calendar). | |||
| For systems that do not have UTC available, but do have local time, | For systems that do not have UTC available, but do have the local | |||
| they MAY use local time 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, | consistently throughout the system. This is not recommended however, | |||
| however, and it should be noted that all that is needed to generate | particularly since all that is needed to generate UTC from local time | |||
| UTC, given local time, is a time zone offset. | is a time zone offset. | |||
| For UUID version 3, it is a 60 bit value constructed from a name. | For UUID version 3, the timestamp is a 60-bit value constructed from | |||
| a name as described in Section 4.3. | ||||
| For UUID version 4, it is a randomly or pseudo-randomly generated 60 | For UUID version 4, it is a randomly or pseudo-randomly generated | |||
| bit value. | 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. | For UUID version 3, it is a 14-bit value constructed from a name as | |||
| described in Section 4.3. | ||||
| For UUID version 4, it is a randomly or pseudo-randomly generated 14 | For UUID version 4, it is a randomly or pseudo-randomly generated | |||
| bit value. | 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 the IEEE address, | For UUID version 1, the node field consists of the IEEE address, | |||
| usually the host address. For systems with multiple IEEE 802 | usually the host address. For systems with multiple IEEE 802 | |||
| addresses, any available address can be used. The lowest addressed | addresses, any available address can be used. The lowest addressed | |||
| octet (octet number 10) contains the global/local bit and the | octet (octet number 10) contains the global/local bit and the | |||
| unicast/multicast bit, and is the first octet of the address | unicast/multicast bit, and is the first octet of the address | |||
| transmitted on 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). 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, the node field is a 48-bit value constructed from | |||
| a name. | 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. | 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 0 (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. UUID generation requires a | discussed in the following sections. | |||
| guarantee of uniqueness within the node ID for a given variant and | ||||
| version. Interoperability is provided by complying with the | ||||
| specified data structure. | ||||
| 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 (non-existent or corrupted), or the | o If the state was unavailable (e.g., non-existent or corrupted), or | |||
| saved node ID is different than the current node ID, generate a | the saved node ID is different than the current node ID, generate | |||
| 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 Format a UUID from the current time stamp, clock sequence, and | ||||
| node ID values according to the structure in section 3.1 (see | ||||
| section 3.2.6 for more details) | ||||
| 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 system wide global lock | o Release the global lock | |||
| o Format a UUID from the current time stamp, clock sequence, and | ||||
| 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 | the clock. We address each of them in turn in the following sections. | |||
| sections. | ||||
| 4.2.2 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 | it can always say that the values were unavailable. This is the least | |||
| least desirable implementation, because it will increase the | desirable implementation, because it will increase the frequency of | |||
| frequency of creation of new clock sequence numbers, which increases | creation of new clock sequence numbers, which increases the | |||
| the probability of duplicates. | 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.3 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 100- | stamp. The count will range between zero and the number of | |||
| 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.4 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.5 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 per- | allocate a block of time stamps each time it is called, and a | |||
| process generator can allocate from that block until it is exhausted. | per-process generator can allocate from that block until it is | |||
| exhausted. | ||||
| 4.2.6 UUID Generation details | 4.2.2 Generation details | |||
| 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 above. | 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 from 0 (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 numbered 0 to 31 inclusive) of the time stamp in the same | (bits zero through 31) of the time stamp in the same order of | |||
| order of significance. | significance. | |||
| o Set the time_mid field equal to the bits numbered 32 to 47 | o Set the time_mid field equal to bits 32 through 47 from the time | |||
| inclusive of the time stamp in the same order of significance. | stamp in the same order of significance. | |||
| o Set the 12 least significant bits (bits numbered 0 to 11 | o Set the 12 least significant bits (bits zero through 11) of the | |||
| inclusive) of the time_hi_and_version field equal to the bits | time_hi_and_version field equal to bits 48 through 59 from the | |||
| numbered 48 to 59 inclusive of the time stamp in the same order of | time stamp in the same order of significance. | |||
| significance. | ||||
| o Set the 4 most significant bits (bits numbered 12 to 15 inclusive) | o Set the four most significant bits (bits 12 through 15) of the | |||
| of the time_hi_and_version field to the 4-bit version number | time_hi_and_version field to the four-bit version number | |||
| corresponding to the UUID version being created, as shown in the | corresponding to the UUID version being created, as shown in the | |||
| table in section 3.1.3. | table above. | |||
| o Set the clock_seq_low field to the 8 least significant bits (bits | o Set the clock_seq_low field to the eight least significant bits | |||
| numbered 0 to 7 inclusive) of the clock sequence in the same order | (bits zero through seven) of the clock sequence in the same order | |||
| of significance. | of significance. | |||
| o Set the 6 least significant bits (bits numbered 0 to 5 inclusive) | o Set the six least significant bits (bits zero through five) of the | |||
| of the clock_seq_hi_and_reserved field to the 6 most significant | clock_seq_hi_and_reserved field to the six most significant bits | |||
| bits (bits numbered 8 to 13 inclusive) of the clock sequence in | (bits eight through 13) of the clock sequence in the same order of | |||
| the same order of significance. | significance. | |||
| o Set the 2 most significant bits (bits numbered 6 and 7) of the | o Set the two most significant bits (bits six and seven) of the | |||
| clock_seq_hi_and_reserved to 0 and 1, 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 UUID is meant for generating UUIDs from "names" that | |||
| are drawn from, and unique within, some "name space". Some examples | are drawn from, and unique within, some "name space." The concept of | |||
| of names (and, implicitly, name spaces) might be DNS names, URLs, ISO | name and name space should be broadly construed, and not limited to | |||
| Object IDs (OIDs), reserved words in a programming language, or X.500 | textual names. For example, some name spaces are the domain name | |||
| Distinguished Names (DNs); thus, the concept of name and name space | system, URLs, ISO Object IDs (OIDs), X.500 Distinguished Names (DNs), | |||
| should be broadly construed, and not limited to textual names. The | and reserved words in a programming language. The mechanisms or | |||
| mechanisms or conventions for allocating names from, and ensuring | conventions for allocating names from, and ensuring their uniqueness | |||
| their uniqueness within, their name spaces are beyond the scope of | within, their name spaces are beyond the scope of this specification. | |||
| this specification. | ||||
| The requirements for such UUIDs are as follows: | The requirements for version 3 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 | generated from names in that name space; see Appendix C for some | |||
| pre-defined values | ||||
| 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 MD5 [3] hash of the name space ID concatenated with | |||
| the name | the name | |||
| o Set octets 0-3 of time_low field to octets 0-3 of the MD5 hash | o Set octets zero through three of the time_low field to octets zero | |||
| through three of the MD5 hash | ||||
| o Set octets 0-1 of time_mid field to octets 4-5 of the MD5 hash | o Set octets zero and one of the time_mid field to octets four and | |||
| five of the MD5 hash | ||||
| o Set octets 0-1 of time_hi_and_version field to octets 6-7 of the | o Set octets zero and one of the time_hi_and_version field to octets | |||
| MD5 hash | six and seven of the MD5 hash | |||
| o Set the clock_seq_hi_and_reserved field to octet 8 of the MD5 hash | 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 | ||||
| Section 4.1.3. | ||||
| o Set the clock_seq_low field to octet 9 of the MD5 hash | o Set the clock_seq_hi_and_reserved field to octet eight of the MD5 | |||
| hash | ||||
| o Set octets 0-5 of the node field to octets 10-15 of the MD5 hash | o Set the two most significant bits (bits 6 and 7) of the | |||
| clock_seq_hi_and_reserved to zero and one, respectively. | ||||
| o Set the 2 most significant bits (bits numbered 6 and 7) of the | o Set the clock_seq_low field to octet nine of the MD5 hash | |||
| clock_seq_hi_and_reserved to 0 and 1, respectively. | ||||
| o Set the 4 most significant bits (bits numbered 12 to 15 inclusive) | o Set octets zero through five of the node field to octets then | |||
| of the time_hi_and_version field to the 4-bit version number | through fifteen of the MD5 hash | |||
| corresponding to the UUID version being created, as shown in the | ||||
| table above. | ||||
| o Convert the resulting UUID to local byte order. | o Convert the resulting UUID to local byte order. | |||
| 5. 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 2 most significant bits (bits numbered 6 and 7) of the | o Set the two most significant bits (bits six and seven) of the | |||
| clock_seq_hi_and_reserved to 0 and 1, respectively. | clock_seq_hi_and_reserved to zero and one, respectively. | |||
| o Set the 4 most significant bits (bits numbered 12 to 15 inclusive) | o Set the four most significant bits (bits 12 through 15) of the | |||
| of the time_hi_and_version field to the 4-bit version number | time_hi_and_version field to the four-bit version number from | |||
| corresponding to the UUID version being created, as shown in the | Section 4.1.3. | |||
| table above. | ||||
| 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. | |||
| Here are several possible ways to generate the random values: | See Section 4.5 for a discussion on random numbers. | |||
| o Use a physical source of randomness: for example, a white noise | ||||
| generator, radioactive decay, or a lava lamp. | ||||
| o Use a cryptographic strength random number generator. | ||||
| 6. Byte order of UUIDs | ||||
| UUIDs may be transmitted in many different forms, some of which may | ||||
| be dependent on the presentation or application protocol where the | ||||
| UUID may be used. In such cases, the order, sizes and byte orders of | ||||
| the UUIDs fields on the wire will depend on the relevant presentation | ||||
| or application protocol. However, it is strongly RECOMMENDED that | ||||
| the order of the fields conform with ordering set out in section 3.1 | ||||
| above. Furthermore, the payload size of each field in the | ||||
| application or presentation protocol MUST be large enough that no | ||||
| information lost in the process of encoding them for transmission. | ||||
| 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 in section 3.1, and with each field | ||||
| encoded with the Most Significant Byte first (also known as network | ||||
| byte order). | ||||
| 0 1 2 3 | 4.5 Node IDs that do not identify the host | |||
| 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) | | ||||
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||||
| 7. Node IDs when no IEEE 802 network card is available | This section describes how to generate a version 1 UUID if an IEEE | |||
| 802 address is not available, or its use is not desired. | ||||
| If a system wants to generate UUIDs but has no IEE 802 compliant | One approach is to contact the IEEE and get a separate block of | |||
| network card or other source of IEEE 802 addresses, then this section | addresses. At the time of writing, the application could be found at | |||
| describes how to generate one. | [6], and the cost was US$550. | |||
| The ideal 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 most | number, and use it as the low 47 bits of the node ID, with the most | |||
| significant bit of the first octet of the node ID set to 1. This bit | significant bit of the first octet of the node ID set to one. This | |||
| 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. | cards. | |||
| If a system does not have a primitive to generate cryptographic | If a system does not have the capability to generate cryptographic | |||
| quality random numbers, then in most systems there are usually a | quality random numbers, then in most systems there are usually a | |||
| fairly large number of sources of randomness available from which one | fairly large number of sources of randomness available from which one | |||
| can be generated. Such sources are system specific, but often | can be generated. Such sources are system specific, but often | |||
| include: | include: | |||
| o the percent of memory in use | o the percent of memory in use | |||
| o the size of main memory in bytes | o the size of main memory in bytes | |||
| o the amount of free main memory in bytes | o the amount of free main memory in bytes | |||
| o the size of the paging or swap file in bytes | o the size of the paging or swap file in bytes | |||
| skipping to change at page 18, line 4 ¶ | skipping to change at page 16, line 22 ¶ | |||
| o the creation, last read, and modification times of files in | o the creation, last read, and modification times of files in | |||
| various system directories | various system directories | |||
| o the utilization factors of various system resources (heap, etc.) | o the utilization factors of various system resources (heap, etc.) | |||
| o current mouse cursor position | o current mouse cursor position | |||
| o current caret position | o current caret position | |||
| o current number of running processes, threads | o current number of running processes, threads | |||
| o handles or IDs of the desktop window and the active window | o handles or IDs of the desktop window and the active window | |||
| o the value of stack pointer of the caller | o the value of stack pointer of the caller | |||
| o the process and thread ID of caller | o the process and thread ID of caller | |||
| o various processor architecture specific performance counters | o various processor architecture specific performance counters | |||
| (instructions executed, cache misses, TLB misses) | (instructions executed, cache misses, TLB misses) | |||
| (Note that it precisely the above kinds of sources of randomness that | ||||
| are used to seed cryptographic quality random number generators on | ||||
| systems without special hardware for their construction.) | ||||
| 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. However, assuming that one can | them are often very system specific. A generic approach, however is | |||
| concatenate all the values from the randomness sources into a buffer, | to accumulate as many sources as possible into a buffer, and use a | |||
| and that a cryptographic hash function such as MD5 [3] is available, | message digest such as MD5 [3], take an arbitrary six bytes from the | |||
| then any 6 bytes of the MD5 hash of the buffer, with the multicast | hash value, and set the multicast bit as described above. | |||
| bit (the high bit of the first byte) set will be an appropriately | ||||
| random node ID. | ||||
| Other hash functions, such as SHA-1 [5] , can also be used. The only | Other hash functions, such as SHA-1 [5], can also be used. The only | |||
| requirement is that the result be suitably random _ in the sense that | requirement is that the result be suitably random in the sense that | |||
| the outputs from a set uniformly distributed inputs are themselves | the outputs from a set uniformly distributed inputs are themselves | |||
| uniformly distributed, and that a single bit change in the input can | uniformly distributed, and that a single bit change in the input can | |||
| be expected to cause half of the output bits to change. | be expected to cause half of the output bits to change. | |||
| 8. Obtaining IEEE 802 addresses | 5. Community Considerations | |||
| At the time of writing, the following URL | ||||
| http://standards.ieee.org/regauth/oui/pilot-ind.html | ||||
| contains information on how to obtain an IEEE 802 address or | ||||
| "company_id" block. At the time of writing, the cost is $550 US. | ||||
| 9. 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. | many cases, become exposed to the web in many non-standard ways. This | |||
| This specification attempts to standardize that practice as openly as | 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. | |||
| 10. Security Considerations | 6. Security Considerations | |||
| It should not be assumed that UUIDs are hard to guess; they should | Do not assume that UUIDs are hard to guess; they should not be used | |||
| not be used as capabilities. It should also not be assumed that it | as capabilities, for example. | |||
| 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. | ||||
| 11. Acknowledgements | 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. | ||||
| Ninety-five percent of this document is original to Paul Leach and | 7. Acknowledgments | |||
| Rich Salz. The conversion to the format for registering a URN | ||||
| namespace was done by Michael Mealling who is indebted to them for | ||||
| providing a clear and extremely thorough document from which to | ||||
| start. The fact that their original document is still referenced | ||||
| even in draft form is a testament to a well done document that is | ||||
| timely and useful. | ||||
| 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). | |||
| Normative References | Normative References | |||
| [1] Zahn, L., Dineen, T. and P. Leach, "Network Computing | [1] Zahn, L., Dineen, T. and P. Leach, "Network Computing | |||
| skipping to change at page 20, line 5 ¶ | skipping to change at page 17, line 45 ¶ | |||
| [3] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April | [3] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April | |||
| 1992. | 1992. | |||
| [4] Moats, R., "URN Syntax", RFC 2141, May 1997. | [4] Moats, R., "URN Syntax", RFC 2141, May 1997. | |||
| [5] National Institute of Standards and Technology, "Secure Hash | [5] 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, <http://www.itl.nist.gov/ | |||
| fipspubs/fip180-1.htm>. | fipspubs/fip180-1.htm>. | |||
| Authors' Addresses | [6] <http://standards.ieee.org/regauth/oui/pilot-ind.html> | |||
| Michael Mealling | ||||
| VeriSign, Inc. | ||||
| 21345 Ridgetop Circle | ||||
| Dulles, VA 21345 | ||||
| US | ||||
| Phone: +1 770-717-0732 | Authors' Addresses | |||
| EMail: michael@neonym.net | ||||
| URI: http://www.verisignlabs.com | ||||
| 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 | ||||
| VeriSign, Inc. | ||||
| 21345 Ridgetop Circle | ||||
| Dulles, VA 21345 | ||||
| US | ||||
| Phone: +1 678-581-9656 | ||||
| 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 - UUID 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. | (Red Hat 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. The | |||
| The code assumes 64 bit integer support, which makes it a lot | code assumes 64-bit integer support, which makes it a lot clearer. | |||
| 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. | |||
| ** Copyright (c) 1998 Microsoft. | ** Copyright (c) 1998 Microsoft. | |||
| ** To anyone who acknowledges that this file is provided "AS IS" | ** To anyone who acknowledges that this file is provided "AS IS" | |||
| ** without any express or implied warranty: permission to use, copy, | ** without any express or implied warranty: permission to use, copy, | |||
| ** modify, and distribute this file for any purpose is hereby | ** modify, and distribute this file for any purpose is hereby | |||
| ** granted without fee, provided that the above copyright notices and | ** granted without fee, provided that the above copyright notices and | |||
| ** this notice appears in all source code copies, and that none of | ** this notice appears in all source code copies, and that none of | |||
| ** the names of Open Software Foundation, Inc., Hewlett-Packard | ** the names of Open Software Foundation, Inc., Hewlett-Packard | |||
| ** Company, or Digital Equipment Corporation be used in advertising | ** Company, or Digital Equipment Corporation be used in advertising | |||
| ** or publicity pertaining to distribution of the software without | ** or publicity pertaining to distribution of the software without | |||
| ** specific, written prior permission. Neither Open Software | ** specific, written prior permission. Neither Open Software | |||
| ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital | ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital | |||
| Equipment | ** Equipment Corporation makes any representations about the | |||
| ** Corporation makes any representations about the suitability of | suitability | |||
| ** this software for any purpose. | ** of this software for any purpose. | |||
| */ | */ | |||
| uuid.h | uuid.h | |||
| #include "copyrt.h" | #include "copyrt.h" | |||
| #undef uuid_t | #undef uuid_t | |||
| typedef struct _uuid_t { | typedef struct { | |||
| unsigned32 time_low; | unsigned32 time_low; | |||
| 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_from_name -- create a UUID using a "name" | |||
| from a "name space" */ | from a "name space" */ | |||
| void uuid_create_from_name( | void uuid_create_from_name( | |||
| uuid_t * uuid, /* resulting UUID */ | uuid_t *uuid, /* resulting UUID */ | |||
| uuid_t nsid, /* UUID to serve as context, so identical | uuid_t nsid, /* UUID of the namespace */ | |||
| names from different name spaces generate | void *name, /* the name from which to generate a UUID | |||
| different UUIDs */ | */ | |||
| 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 | |||
| -1 u1 is lexically before u2 | ||||
| /* uuid_compare -- Compare two UUID's "lexically" and return | 0 u1 is equal to u2 | |||
| -1 u1 is lexically before u2 | 1 u1 is lexically after u2 | |||
| 0 u1 is equal to u2 | ||||
| 1 u1 is lexically after u2 | ||||
| Note: lexical ordering is not temporal ordering! | ||||
| */ | ||||
| int uuid_compare(uuid_t *u1, uuid_t *u2); | ||||
| uuid.c | Note that lexical ordering is not temporal ordering! | |||
| */ | ||||
| int uuid_compare(uuid_t *u1, uuid_t *u2); | ||||
| #include "copyrt.h" | uuid.c | |||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <time.h> | ||||
| #include "sysdep.h" | ||||
| #include "uuid.h" | ||||
| /* various forward declarations */ | #include "copyrt.h" | |||
| static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | #include <string.h> | |||
| uuid_node_t * node); | #include <stdio.h> | |||
| static void write_state(unsigned16 clockseq, uuid_time_t timestamp, | #include <stdlib.h> | |||
| uuid_node_t node); | #include <time.h> | |||
| static void format_uuid_v1(uuid_t * uuid, unsigned16 clockseq, | #include "sysdep.h" | |||
| uuid_time_t timestamp, uuid_node_t node); | #include "uuid.h" | |||
| 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 */ | /* various forward declarations */ | |||
| int uuid_create(uuid_t * uuid) { | static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | |||
| uuid_time_t timestamp, last_time; | uuid_node_t *node); | |||
| unsigned16 clockseq; | static void write_state(unsigned16 clockseq, uuid_time_t timestamp, | |||
| uuid_node_t node; | uuid_node_t node); | |||
| uuid_node_t last_node; | static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq, | |||
| int f; | 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); | ||||
| /* acquire system wide lock so we're alone */ | /* uuid_create -- generator a UUID */ | |||
| LOCK; | 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; | ||||
| /* get current time */ | /* acquire system-wide lock so we're alone */ | |||
| get_current_time(×tamp); | LOCK; | |||
| /* get node ID */ | /* get time, node ID, saved state from non-volatile storage */ | |||
| get_ieee_node_identifier(&node); | get_current_time(×tamp); | |||
| /* get saved state from NV storage */ | get_ieee_node_identifier(&node); | |||
| f = read_state(&clockseq, &last_time, &last_node); | f = read_state(&clockseq, &last_time, &last_node); | |||
| /* if no NV state, or if clock went backwards, or node ID changed | /* if no NV state, or if clock went backwards, or node ID | |||
| (e.g., net card swap) change clockseq */ | changed | |||
| if (!f || memcmp(&node, &last_node, sizeof(uuid_node_t))) | (e.g., new network card) change clockseq */ | |||
| clockseq = true_random(); | if (!f || memcmp(&node, &last_node, sizeof node)) | |||
| else if (timestamp < last_time) | clockseq = true_random(); | |||
| clockseq++; | else if (timestamp < last_time) | |||
| clockseq++; | ||||
| /* stuff fields into the UUID */ | /* save the state for next time */ | |||
| format_uuid_v1(uuid, clockseq, timestamp, node); | write_state(clockseq, timestamp, node); | |||
| /* save the state for next time */ | UNLOCK; | |||
| write_state(clockseq, timestamp, node); | ||||
| UNLOCK; | /* stuff fields into the UUID */ | |||
| return(1); | format_uuid_v1(uuid, clockseq, timestamp, node); | |||
| }; | return 1; | |||
| } | ||||
| /* format_uuid_v1 -- make a UUID from the timestamp, clockseq, | /* format_uuid_v1 -- make a UUID from the timestamp, clockseq, | |||
| and node ID */ | and node ID */ | |||
| void format_uuid_v1(uuid_t * uuid, unsigned16 clock_seq, uuid_time_t | void format_uuid_v1(uuid_t* uuid, unsigned16 clock_seq, | |||
| timestamp, uuid_node_t node) { | uuid_time_t timestamp, uuid_node_t node) | |||
| /* Construct a version 1 uuid with the information we've gathered | { | |||
| * plus a few constants. */ | /* Construct a version 1 uuid with the information we've gathered | |||
| plus a few constants. */ | ||||
| uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF); | uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF); | |||
| uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF); | uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF); | |||
| uuid->time_hi_and_version = (unsigned short)((timestamp >> 48) & | uuid->time_hi_and_version = | |||
| 0x0FFF); | (unsigned short)((timestamp >> 48) & 0x0FFF); | |||
| uuid->time_hi_and_version |= (1 << 12); | uuid->time_hi_and_version |= (1 << 12); | |||
| uuid->clock_seq_low = clock_seq & 0xFF; | uuid->clock_seq_low = clock_seq & 0xFF; | |||
| uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8; | uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8; | |||
| uuid->clock_seq_hi_and_reserved |= 0x80; | uuid->clock_seq_hi_and_reserved |= 0x80; | |||
| memcpy(&uuid->node, &node, sizeof uuid->node); | memcpy(&uuid->node, &node, sizeof uuid->node); | |||
| }; | } | |||
| /* data type for UUID generator persistent state */ | /* data type for UUID generator persistent state */ | |||
| typedef struct { | typedef struct { | |||
| uuid_time_t ts; /* saved timestamp */ | uuid_time_t ts; /* saved timestamp */ | |||
| uuid_node_t node; /* saved node ID */ | uuid_node_t node; /* saved node ID */ | |||
| unsigned16 cs; /* saved clock sequence */ | unsigned16 cs; /* saved clock sequence */ | |||
| } uuid_state; | } uuid_state; | |||
| static uuid_state st; | static uuid_state st; | |||
| /* read_state -- read UUID generator state from non-volatile store */ | /* read_state -- read UUID generator state from non-volatile store */ | |||
| int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, | |||
| uuid_node_t *node) { | uuid_node_t *node) | |||
| FILE * fd; | { | |||
| static int inited = 0; | static int inited = 0; | |||
| FILE *fp; | ||||
| /* only need to read state once per boot */ | /* only need to read state once per boot */ | |||
| if (!inited) { | if (!inited) { | |||
| fd = fopen("state", "rb"); | fp = fopen("state", "rb"); | |||
| if (!fd) | if (fp == NULL) | |||
| return (0); | return 0; | |||
| fread(&st, sizeof(uuid_state), 1, fd); | fread(&st, sizeof st, 1, fp); | |||
| fclose(fd); | fclose(fp); | |||
| inited = 1; | inited = 1; | |||
| }; | } | |||
| *clockseq = st.cs; | *clockseq = st.cs; | |||
| *timestamp = st.ts; | *timestamp = st.ts; | |||
| *node = st.node; | *node = st.node; | |||
| return(1); | return 1; | |||
| }; | } | |||
| /* write_state -- save UUID generator state back to non-volatile | /* write_state -- save UUID generator state back to non-volatile | |||
| storage */ | storage */ | |||
| void write_state(unsigned16 clockseq, uuid_time_t timestamp, | void write_state(unsigned16 clockseq, uuid_time_t timestamp, | |||
| uuid_node_t node) { | uuid_node_t node) | |||
| FILE * fd; | { | |||
| static int inited = 0; | static int inited = 0; | |||
| static uuid_time_t next_save; | static uuid_time_t next_save; | |||
| FILE* fp; | ||||
| if (!inited) { | if (!inited) { | |||
| next_save = timestamp; | next_save = timestamp; | |||
| inited = 1; | inited = 1; | |||
| }; | } | |||
| /* always save state to volatile shared state */ | /* always save state to volatile shared state */ | |||
| st.cs = clockseq; | st.cs = clockseq; | |||
| st.ts = timestamp; | st.ts = timestamp; | |||
| st.node = node; | st.node = node; | |||
| if (timestamp >= next_save) { | if (timestamp >= next_save) { | |||
| fd = fopen("state", "wb"); | fp = fopen("state", "wb"); | |||
| fwrite(&st, sizeof(uuid_state), 1, fd); | fwrite(&st, sizeof st, 1, fp); | |||
| fclose(fd); | fclose(fp); | |||
| /* schedule next save for 10 seconds from now */ | /* schedule next save for 10 seconds from now */ | |||
| next_save = timestamp + (10 * 10 * 1000 * 1000); | next_save = timestamp + (10 * 10 * 1000 * 1000); | |||
| }; | } | |||
| }; | } | |||
| /* get-current_time -- get time as 60 bit 100ns ticks since whenever. | ||||
| Compensate for the fact that real clock resolution is | ||||
| less than 100ns. */ | ||||
| void get_current_time(uuid_time_t * timestamp) { | ||||
| uuid_time_t time_now; | ||||
| static uuid_time_t time_last; | ||||
| static unsigned16 uuids_this_tick; | ||||
| static int inited = 0; | ||||
| /* 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) { | if (!inited) { | |||
| get_system_time(&time_now); | get_system_time(&time_now); | |||
| uuids_this_tick = UUIDS_PER_TICK; | uuids_this_tick = UUIDS_PER_TICK; | |||
| inited = 1; | inited = 1; | |||
| }; | } | |||
| while (1) { | for ( ; ; ) { | |||
| get_system_time(&time_now); | get_system_time(&time_now); | |||
| /* if clock reading changed since last UUID generated... */ | /* if clock reading changed since last UUID generated, */ | |||
| if (time_last != time_now) { | if (time_last != time_now) { | |||
| /* reset count of uuids gen'd with this clock reading */ | /* reset count of uuids gen'd with this clock reading */ | |||
| uuids_this_tick = 0; | uuids_this_tick = 0; | |||
| break; | break; | |||
| }; | } | |||
| if (uuids_this_tick < UUIDS_PER_TICK) { | if (uuids_this_tick < UUIDS_PER_TICK) { | |||
| uuids_this_tick++; | uuids_this_tick++; | |||
| break; | break; | |||
| }; | } | |||
| /* going too fast for our clock; spin */ | /* going too fast for our clock; spin */ | |||
| }; | } | |||
| /* add the count of uuids to low order bits of the clock reading */ | /* add the count of uuids to low order bits of the clock reading | |||
| */ | ||||
| *timestamp = time_now + uuids_this_tick; | *timestamp = time_now + uuids_this_tick; | |||
| }; | } | |||
| /* true_random -- generate a crypto-quality random number. | /* true_random -- generate a crypto-quality random number. | |||
| This sample doesn't do that. */ | **This sample doesn't do that.** */ | |||
| static unsigned16 | static unsigned16 true_random(void) | |||
| 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 | ||||
| space" */ | /* uuid_create_from_name -- create a UUID using a "name" from a "name | |||
| void uuid_create_from_name( | space" */ | |||
| uuid_t * uuid, /* resulting UUID */ | void uuid_create_from_name(uuid_t *uuid, uuid_t nsid, void *name, | |||
| uuid_t nsid, /* UUID to serve as context, so identical | int namelen) | |||
| names from different name spaces generate | { | |||
| different UUIDs */ | ||||
| void * name, /* the name from which to generate a UUID */ | ||||
| int namelen /* the length of the name */ | ||||
| ) { | ||||
| MD5_CTX c; | MD5_CTX c; | |||
| unsigned char hash[16]; | unsigned char hash[16]; | |||
| uuid_t net_nsid; /* context UUID in network byte order */ | 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); | htonl(net_nsid.time_low); | |||
| htons(net_nsid.time_mid); | htons(net_nsid.time_mid); | |||
| htons(net_nsid.time_hi_and_version); | htons(net_nsid.time_hi_and_version); | |||
| MD5Init(&c); | MD5Init(&c); | |||
| MD5Update(&c, &net_nsid, sizeof(uuid_t)); | 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_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]) { | ||||
| /* Construct a version 3 uuid with the (pseudo-)random number | ||||
| * plus a few constants. */ | ||||
| memcpy(uuid, hash, sizeof(uuid_t)); | ||||
| /* 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 */ | /* convert UUID to local byte order */ | |||
| memcpy(uuid, hash, sizeof *uuid); | ||||
| ntohl(uuid->time_low); | ntohl(uuid->time_low); | |||
| ntohs(uuid->time_mid); | ntohs(uuid->time_mid); | |||
| ntohs(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 |= (3 << 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 */ | |||
| -1 u1 is lexically before u2 | #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; | |||
| 0 u1 is equal to u2 | int uuid_compare(uuid_t *u1, uuid_t *u2) | |||
| 1 u1 is lexically after u2 | { | |||
| Note: lexical ordering is not temporal ordering! | ||||
| */ | ||||
| int uuid_compare(uuid_t *u1, uuid_t *u2) | ||||
| { | ||||
| int i; | int i; | |||
| #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; | ||||
| CHECK(u1->time_low, u2->time_low); | CHECK(u1->time_low, u2->time_low); | |||
| CHECK(u1->time_mid, u2->time_mid); | CHECK(u1->time_mid, u2->time_mid); | |||
| CHECK(u1->time_hi_and_version, u2->time_hi_and_version); | 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_hi_and_reserved, | |||
| u2->clock_seq_hi_and_reserved); | ||||
| CHECK(u1->clock_seq_low, u2->clock_seq_low) | CHECK(u1->clock_seq_low, u2->clock_seq_low) | |||
| for (i = 0; i < 6; i++) { | for (i = 0; i < 6; i++) { | |||
| if (u1->node[i] < u2->node[i]) | if (u1->node[i] < u2->node[i]) | |||
| return -1; | return -1; | |||
| if (u1->node[i] > u2->node[i]) | if (u1->node[i] > u2->node[i]) | |||
| return 1; | return 1; | |||
| } | } | |||
| return 0; | return 0; | |||
| }; | } | |||
| #undef CHECK | ||||
| sysdep.h | sysdep.h | |||
| #include "copyrt.h" | #include "copyrt.h" | |||
| /* remove the following define if you aren't running WIN32 */ | /* remove the following define if you aren't running WIN32 */ | |||
| #define WININC 0 | #define WININC 0 | |||
| #ifdef WININC | #ifdef WININC | |||
| #include <windows.h> | #include <windows.h> | |||
| #else | #else | |||
| #include <sys/types.h> | #include <sys/types.h> | |||
| #include <sys/time.h> | #include <sys/time.h> | |||
| #include <sys/sysinfo.h> | #include <sys/sysinfo.h> | |||
| #endif | #endif | |||
| /* change to point to where MD5 .h's live */ | #include "global.h" | |||
| /* get MD5 sample implementation from RFC 1321 */ | /* change to point to where MD5 .h's live; RFC 1321 has sample | |||
| #include "global.h" | implementation */ | |||
| #include "md5.h" | #include "md5.h" | |||
| /* set the following to the number of 100ns ticks of the actual | /* set the following to the number of 100ns ticks of the actual | |||
| resolution of | resolution of your system's clock */ | |||
| your system's clock */ | #define UUIDS_PER_TICK 1024 | |||
| #define UUIDS_PER_TICK 1024 | ||||
| /* Set the following to a call to acquire a system wide global lock | /* Set the following to a calls to get and release a global lock */ | |||
| */ | #define LOCK | |||
| #define LOCK | #define UNLOCK | |||
| #define UNLOCK | ||||
| typedef unsigned long unsigned32; | typedef unsigned long unsigned32; | |||
| typedef unsigned short unsigned16; | typedef unsigned short unsigned16; | |||
| typedef unsigned char unsigned8; | typedef unsigned char unsigned8; | |||
| typedef unsigned char byte; | typedef unsigned char byte; | |||
| /* Set this to what your compiler uses for 64 bit data type */ | /* Set this to what your compiler uses for 64-bit data type */ | |||
| #ifdef WININC | #ifdef WININC | |||
| #define unsigned64_t unsigned __int64 | #define unsigned64_t unsigned __int64 | |||
| #define I64(C) C | #define I64(C) C | |||
| #else | #else | |||
| #define unsigned64_t unsigned long long | #define unsigned64_t unsigned long long | |||
| #define I64(C) C##LL | #define I64(C) C##LL | |||
| #endif | #endif | |||
| typedef unsigned64_t uuid_time_t; | typedef unsigned64_t uuid_time_t; | |||
| typedef struct { | typedef struct { | |||
| char nodeID[6]; | char nodeID[6]; | |||
| } uuid_node_t; | } uuid_node_t; | |||
| void get_ieee_node_identifier(uuid_node_t *node); | void get_ieee_node_identifier(uuid_node_t *node); | |||
| void get_system_time(uuid_time_t *uuid_time); | void get_system_time(uuid_time_t *uuid_time); | |||
| void get_random_info(char seed[16]); | void get_random_info(char seed[16]); | |||
| sysdep.c | sysdep.c | |||
| #include "copyrt.h" | #include "copyrt.h" | |||
| #include <stdio.h> | #include <stdio.h> | |||
| #include "sysdep.h" | #include "sysdep.h" | |||
| /* system dependent call to get IEEE node ID. | /* system dependent call to get IEEE node ID. | |||
| This sample implementation generates a random node ID | This sample implementation generates a random node ID. */ | |||
| */ | void get_ieee_node_identifier(uuid_node_t *node) | |||
| void get_ieee_node_identifier(uuid_node_t *node) { | { | |||
| char seed[16]; | ||||
| FILE * fd; | ||||
| static inited = 0; | static inited = 0; | |||
| static uuid_node_t saved_node; | static uuid_node_t saved_node; | |||
| char seed[16]; | ||||
| FILE *fp; | ||||
| if (!inited) { | if (!inited) { | |||
| fd = fopen("nodeid", "rb"); | fp = fopen("nodeid", "rb"); | |||
| if (fd) { | if (fp) { | |||
| fread(&saved_node, sizeof(uuid_node_t), 1, fd); | fread(&saved_node, sizeof saved_node, 1, fp); | |||
| fclose(fd); | fclose(fp); | |||
| } | } | |||
| else { | else { | |||
| get_random_info(seed); | get_random_info(seed); | |||
| seed[0] |= 0x80; | seed[0] |= 0x80; | |||
| memcpy(&saved_node, seed, sizeof(uuid_node_t)); | memcpy(&saved_node, seed, sizeof saved_node); | |||
| fd = fopen("nodeid", "wb"); | fp = fopen("nodeid", "wb"); | |||
| if (fd) { | if (fp) { | |||
| fwrite(&saved_node, sizeof(uuid_node_t), 1, fd); | fwrite(&saved_node, sizeof saved_node, 1, fp); | |||
| fclose(fd); | fclose(fp); | |||
| }; | } | |||
| }; | } | |||
| inited = 1; | inited = 1; | |||
| }; | } | |||
| *node = saved_node; | *node = saved_node; | |||
| }; | } | |||
| /* system dependent call to get the current system time. Returned as | ||||
| /* system dependent call to get the current system time. | 100ns ticks since UUID epoch, but resolution may be less than | |||
| Returned as 100ns ticks since Oct 15, 1582, but resolution may be | 100ns. */ | |||
| less than 100ns. | #ifdef _WINDOWS_ | |||
| */ | ||||
| #ifdef _WINDOWS_ | ||||
| void get_system_time(uuid_time_t *uuid_time) { | void get_system_time(uuid_time_t *uuid_time) | |||
| { | ||||
| ULARGE_INTEGER time; | ULARGE_INTEGER time; | |||
| GetSystemTimeAsFileTime((FILETIME *)&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. | ||||
| /* 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) | The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) | |||
| + 18 years and 5 leap days. | + 18 years and 5 leap days. */ | |||
| */ | GetSystemTimeAsFileTime((FILETIME *)&time); | |||
| time.QuadPart += | ||||
| time.QuadPart += | (unsigned __int64) (1000*1000*10) // seconds | |||
| (unsigned __int64) (1000*1000*10) // seconds | * (unsigned __int64) (60 * 60 * 24) // days | |||
| * (unsigned __int64) (60 * 60 * 24) // days | * (unsigned __int64) (17+30+31+365*18+5); // # of days | |||
| * (unsigned __int64) (17+30+31+365*18+5); // # of days | ||||
| *uuid_time = time.QuadPart; | *uuid_time = time.QuadPart; | |||
| } | ||||
| }; | void get_random_info(char seed[16]) | |||
| void get_random_info(char seed[16]) { | { | |||
| MD5_CTX c; | MD5_CTX c; | |||
| typedef struct { | struct { | |||
| MEMORYSTATUS m; | MEMORYSTATUS m; | |||
| SYSTEM_INFO s; | SYSTEM_INFO s; | |||
| FILETIME t; | FILETIME t; | |||
| LARGE_INTEGER pc; | LARGE_INTEGER pc; | |||
| DWORD tc; | DWORD tc; | |||
| DWORD l; | DWORD l; | |||
| char hostname[MAX_COMPUTERNAME_LENGTH + 1]; | char hostname[MAX_COMPUTERNAME_LENGTH + 1]; | |||
| } randomness; | } r; | |||
| randomness r; | ||||
| MD5Init(&c); | MD5Init(&c); | |||
| /* memory usage stats */ | ||||
| GlobalMemoryStatus(&r.m); | GlobalMemoryStatus(&r.m); | |||
| /* random system stats */ | ||||
| GetSystemInfo(&r.s); | GetSystemInfo(&r.s); | |||
| /* 100ns resolution (nominally) time of day */ | ||||
| GetSystemTimeAsFileTime(&r.t); | GetSystemTimeAsFileTime(&r.t); | |||
| /* high resolution performance counter */ | ||||
| QueryPerformanceCounter(&r.pc); | QueryPerformanceCounter(&r.pc); | |||
| /* milliseconds since last boot */ | ||||
| r.tc = GetTickCount(); | r.tc = GetTickCount(); | |||
| r.l = MAX_COMPUTERNAME_LENGTH + 1; | r.l = MAX_COMPUTERNAME_LENGTH + 1; | |||
| GetComputerName(r.hostname, &r.l); | ||||
| GetComputerName(r.hostname, &r.l ); | MD5Update(&c, &r, sizeof r); | |||
| MD5Update(&c, &r, sizeof(randomness)); | ||||
| MD5Final(seed, &c); | MD5Final(seed, &c); | |||
| }; | } | |||
| #else | ||||
| void get_system_time(uuid_time_t *uuid_time) | #else | |||
| { | ||||
| struct timeval tp; | ||||
| gettimeofday(&tp, (struct timezone *)0); | void get_system_time(uuid_time_t *uuid_time) | |||
| { | ||||
| struct timeval tp; | ||||
| /* Offset between UUID formatted times and Unix formatted times. | gettimeofday(&tp, (struct timezone *)0); | |||
| UUID UTC base time is October 15, 1582. | ||||
| Unix base time is January 1, 1970. | ||||
| */ | ||||
| *uuid_time = (tp.tv_sec * 10000000) + (tp.tv_usec * 10) + | ||||
| I64(0x01B21DD213814000); | ||||
| }; | ||||
| void get_random_info(char seed[16]) { | /* 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 = (tp.tv_sec * 10000000) + (tp.tv_usec * 10) | ||||
| + I64(0x01B21DD213814000); | ||||
| } | ||||
| void get_random_info(char seed[16]) | ||||
| { | ||||
| MD5_CTX c; | MD5_CTX c; | |||
| typedef struct { | struct { | |||
| struct sysinfo s; | struct sysinfo s; | |||
| struct timeval t; | struct timeval t; | |||
| char hostname[257]; | char hostname[257]; | |||
| } randomness; | } r; | |||
| randomness r; | ||||
| MD5Init(&c); | MD5Init(&c); | |||
| sysinfo(&r.s); | sysinfo(&r.s); | |||
| gettimeofday(&r.t, (struct timezone *)0); | gettimeofday(&r.t, (struct timezone *)0); | |||
| gethostname(r.hostname, 256); | gethostname(r.hostname, 256); | |||
| MD5Update(&c, &r, sizeof(randomness)); | MD5Update(&c, &r, sizeof r); | |||
| MD5Final(seed, &c); | MD5Final(seed, &c); | |||
| }; | } | |||
| #endif | #endif | |||
| utest.c | utest.c | |||
| #include "copyrt.h" | #include "copyrt.h" | |||
| #include "sysdep.h" | #include "sysdep.h" | |||
| #include <stdio.h> | #include <stdio.h> | |||
| #include "uuid.h" | #include "uuid.h" | |||
| uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | |||
| 0x6ba7b810, | 0x6ba7b810, | |||
| 0x9dad, | 0x9dad, | |||
| 0x11d1, | 0x11d1, | |||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | |||
| }; | }; | |||
| /* puid -- print a UUID */ | /* puid -- print a UUID */ | |||
| void puid(uuid_t u); | void puid(uuid_t u) | |||
| { | ||||
| int i; | ||||
| /* Simple driver for UUID generator */ | printf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", u.time_low, u.time_mid, | |||
| void main(int argc, char **argv) { | 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; | uuid_t u; | |||
| int f; | int f; | |||
| 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_from_name(&u, NameSpace_DNS, "www.widgets.com", 15); | |||
| printf("uuid_create_from_name() -> "); puid(u); | printf("uuid_create_from_name(): "); puid(u); | |||
| }; | } | |||
| 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"); | ||||
| }; | ||||
| 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_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 in section 3.5 | string representation defined above. | |||
| uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | ||||
| 0x6ba7b810, | ||||
| 0x9dad, | ||||
| 0x11d1, | ||||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | ||||
| }; | ||||
| uuid_t NameSpace_URL = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */ | /* Name string is a fully-qualified domain name */ | |||
| 0x6ba7b811, | uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ | |||
| 0x9dad, | 0x6ba7b810, | |||
| 0x11d1, | 0x9dad, | |||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | 0x11d1, | |||
| }; | 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | |||
| }; | ||||
| uuid_t NameSpace_OID = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */ | /* Name string is a URL */ | |||
| 0x6ba7b812, | uuid_t NameSpace_URL = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */ | |||
| 0x9dad, | 0x6ba7b811, | |||
| 0x11d1, | 0x9dad, | |||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | 0x11d1, | |||
| }; | 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | |||
| }; | ||||
| uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ | /* Name string is an ISO OID */ | |||
| 0x6ba7b814, | uuid_t NameSpace_OID = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */ | |||
| 0x9dad, | 0x6ba7b812, | |||
| 0x11d1, | 0x9dad, | |||
| 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 | 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 | ||||
| }; | ||||
| Intellectual Property Statement | ||||
| The IETF takes no position regarding the validity or scope of any | ||||
| intellectual property or other rights that might be claimed to | ||||
| pertain to the implementation or use of the technology described in | ||||
| this document or the extent to which any license under such rights | ||||
| might or might not be available; neither does it represent that it | ||||
| has made any effort to identify any such rights. Information on the | ||||
| IETF's procedures with respect to rights in standards-track and | ||||
| standards-related documentation can be found in BCP-11. Copies of | ||||
| claims of rights made available for publication and any assurances of | ||||
| licenses to be made available, or the result of an attempt made to | ||||
| obtain a general license or permission for the use of such | ||||
| proprietary rights by implementors or users of this specification can | ||||
| be obtained from the IETF Secretariat. | ||||
| The IETF invites any interested party to bring to its attention any | ||||
| copyrights, patents or patent applications, or other proprietary | ||||
| rights which may cover technology that may be required to practice | ||||
| this standard. Please address the information to the IETF Executive | ||||
| Director. | ||||
| Full Copyright Statement | Full Copyright Statement | |||
| Copyright (C) The Internet Society (2002). All Rights Reserved. | Copyright (C) The Internet Society (2003). All Rights Reserved. | |||
| This document and translations of it may be copied and furnished to | This document and translations of it may be copied and furnished to | |||
| others, and derivative works that comment on or otherwise explain it | others, and derivative works that comment on or otherwise explain it | |||
| or assist in its implementation may be prepared, copied, published | or assist in its implementation may be prepared, copied, published | |||
| and distributed, in whole or in part, without restriction of any | and distributed, in whole or in part, without restriction of any | |||
| kind, provided that the above copyright notice and this paragraph are | kind, provided that the above copyright notice and this paragraph are | |||
| included on all such copies and derivative works. However, this | included on all such copies and derivative works. However, this | |||
| document itself may not be modified in any way, such as by removing | document itself may not be modified in any way, such as by removing | |||
| the copyright notice or references to the Internet Society or other | the copyright notice or references to the Internet Society or other | |||
| Internet organizations, except as needed for the purpose of | Internet organizations, except as needed for the purpose of | |||
| developing Internet standards in which case the procedures for | developing Internet standards in which case the procedures for | |||
| copyrights defined in the Internet Standards process must be | copyrights defined in the Internet Standards process must be | |||
| followed, or as required to translate it into languages other than | followed, or as required to translate it into languages other than | |||
| English. | English. | |||
| The limited permissions granted above are perpetual and will not be | The limited permissions granted above are perpetual and will not be | |||
| revoked by the Internet Society or its successors or assigns. | revoked by the Internet Society or its successors or assignees. | |||
| This document and the information contained herein is provided on an | This document and the information contained herein is provided on an | |||
| "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING | "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING | |||
| TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING | TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING | |||
| BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION | BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION | |||
| HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF | HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF | |||
| MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | |||
| Acknowledgement | Acknowledgement | |||
| End of changes. 260 change blocks. | ||||
| 843 lines changed or deleted | 781 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/ | ||||