idnits 2.17.1 draft-mealling-uuid-urn-04.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- ** It looks like you're using RFC 3978 boilerplate. You should update this to the boilerplate described in the IETF Trust License Policy document (see https://trustee.ietf.org/license-info), which is required now. -- Found old boilerplate from RFC 3978, Section 5.1.a on line 20. -- Found old boilerplate from RFC 3978, Section 5.5 on line 1408. -- Found old boilerplate from RFC 3979, Section 5, paragraph 1 on line 1385. -- Found old boilerplate from RFC 3979, Section 5, paragraph 2 on line 1392. -- Found old boilerplate from RFC 3979, Section 5, paragraph 3 on line 1398. ** The document seems to lack an RFC 3978 Section 5.1 IPR Disclosure Acknowledgement. ** This document has an original RFC 3978 Section 5.4 Copyright Line, instead of the newer IETF Trust Copyright according to RFC 4748. ** This document has an original RFC 3978 Section 5.5 Disclaimer, instead of the newer disclaimer which includes the IETF Trust according to RFC 4748. ** The document uses RFC 3667 boilerplate or RFC 3978-like boilerplate instead of verbatim RFC 3978 boilerplate. After 6 May 2005, submission of drafts without verbatim RFC 3978 boilerplate is not accepted. The following non-3978 patterns matched text found in the document. That text should be removed or replaced: This document is an Internet-Draft and is subject to all provisions of Section 3 of RFC 3667. By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she becomes aware will be disclosed, in accordance with Section 6 of BCP 79. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- == No 'Intended status' indicated for this document; assuming Proposed Standard Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) ** There are 18 instances of too long lines in the document, the longest one being 10 characters in excess of 72. ** The document seems to lack a both a reference to RFC 2119 and the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords. RFC 2119 keyword, line 397: '...e clock sequence MUST be originally (i...' RFC 2119 keyword, line 401: '...he initial value MUST NOT be correlate...' RFC 2119 keyword, line 500: '...nterval, the UUID service MUST either:...' RFC 2119 keyword, line 582: '... same namespace MUST be equal...' Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the RFC 3978 Section 5.4 Copyright Line does not match the current year == Line 291 has weird spacing: '...version uns...' == Line 295 has weird spacing: '...nd_rese unsig...' == Line 1143 has weird spacing: '...ed long unsi...' == Line 1144 has weird spacing: '...d short unsig...' == Line 1145 has weird spacing: '...ed char unsi...' == (1 more instance...) -- The document seems to lack a disclaimer for pre-RFC5378 work, but may have content which was first submitted before 10 November 2008. If you have contacted all the original authors and they are all willing to grant the BCP78 rights to the IETF Trust, then this is fine, and you can ignore this comment. If not, you may need to add the pre-RFC5378 disclaimer. (See the Legal Provisions document at https://trustee.ietf.org/license-info for more information.) -- The document date (December 8, 2004) is 7079 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) == Missing Reference: '16' is mentioned on line 1266, but not defined == Missing Reference: '257' is mentioned on line 1272, but not defined == Unused Reference: '1' is defined on line 714, but no explicit reference was found in the text -- Possible downref: Non-RFC (?) normative reference: ref. '1' -- Possible downref: Non-RFC (?) normative reference: ref. '2' -- Possible downref: Non-RFC (?) normative reference: ref. '3' ** Downref: Normative reference to an Informational RFC: RFC 1321 (ref. '4') ** Obsolete normative reference: RFC 1750 (ref. '5') (Obsoleted by RFC 4086) ** Obsolete normative reference: RFC 2141 (ref. '6') (Obsoleted by RFC 8141) ** Obsolete normative reference: RFC 2234 (ref. '7') (Obsoleted by RFC 4234) -- Possible downref: Non-RFC (?) normative reference: ref. '8' Summary: 12 errors (**), 0 flaws (~~), 11 warnings (==), 12 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group P. Leach 3 Internet-Draft Microsoft 4 Expires: June 8, 2005 M. Mealling 5 VeriSign, Inc. 6 R. Salz 7 DataPower Technology, Inc. 8 December 8, 2004 10 A UUID URN Namespace 11 draft-mealling-uuid-urn-04.txt 13 Status of this Memo 15 This document is an Internet-Draft and is subject to all provisions 16 of section 3 of RFC 3667. By submitting this Internet-Draft, each 17 author represents that any applicable patent or other IPR claims of 18 which he or she is aware have been or will be disclosed, and any of 19 which he or she become aware will be disclosed, in accordance with 20 RFC 3668. 22 Internet-Drafts are working documents of the Internet Engineering 23 Task Force (IETF), its areas, and its working groups. Note that 24 other groups may also distribute working documents as 25 Internet-Drafts. 27 Internet-Drafts are draft documents valid for a maximum of six months 28 and may be updated, replaced, or obsoleted by other documents at any 29 time. It is inappropriate to use Internet-Drafts as reference 30 material or to cite them other than as "work in progress." 32 The list of current Internet-Drafts can be accessed at 33 http://www.ietf.org/ietf/1id-abstracts.txt. 35 The list of Internet-Draft Shadow Directories can be accessed at 36 http://www.ietf.org/shadow.html. 38 This Internet-Draft will expire on June 8, 2005. 40 Copyright Notice 42 Copyright (C) The Internet Society (2004). 44 Abstract 46 This specification defines a Uniform Resource Name namespace for 47 UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally 48 Unique IDentifier). A UUID is 128 bits long, and can provide a 49 guarantee of uniqueness across space and time. UUIDs were originally 50 used in the Apollo Network Computing System and later in the Open 51 Software Foundation's (OSF) Distributed Computing Environment (DCE), 52 and then in Microsoft Windows platforms. 54 This specification is derived from the DCE specification with the 55 kind permission of the OSF (now known as The Open Group). Earlier 56 versions of this document never left draft stage; this document 57 incorporates that information here. 59 Table of Contents 61 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 62 2. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . 3 63 3. Namespace Registration Template . . . . . . . . . . . . . . . 3 64 4. Specification . . . . . . . . . . . . . . . . . . . . . . . . 6 65 4.1 Format . . . . . . . . . . . . . . . . . . . . . . . . . . 6 66 4.1.1 Variant . . . . . . . . . . . . . . . . . . . . . . . 6 67 4.1.2 Layout and byte order . . . . . . . . . . . . . . . . 7 68 4.1.3 Version . . . . . . . . . . . . . . . . . . . . . . . 8 69 4.1.4 Timestamp . . . . . . . . . . . . . . . . . . . . . . 8 70 4.1.5 Clock sequence . . . . . . . . . . . . . . . . . . . . 9 71 4.1.6 Node . . . . . . . . . . . . . . . . . . . . . . . . . 9 72 4.1.7 Nil UUID . . . . . . . . . . . . . . . . . . . . . . . 10 73 4.2 Algorithms for creating a time-based UUID . . . . . . . . 10 74 4.2.1 Basic algorithm . . . . . . . . . . . . . . . . . . . 10 75 4.2.2 Generation details . . . . . . . . . . . . . . . . . . 12 76 4.3 Algorithm for creating a name-based UUID . . . . . . . . . 13 77 4.4 Algorithms for creating a UUID from truly random or 78 pseudo-random numbers . . . . . . . . . . . . . . . . . . 14 79 4.5 Node IDs that do not identify the host . . . . . . . . . . 14 80 5. Community Considerations . . . . . . . . . . . . . . . . . . . 15 81 6. Security Considerations . . . . . . . . . . . . . . . . . . . 15 82 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 15 83 8. Normative References . . . . . . . . . . . . . . . . . . . . . 16 84 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 16 85 A. Appendix A - Sample Implementation . . . . . . . . . . . . . . 17 86 B. Appendix B - Sample output of utest . . . . . . . . . . . . . 29 87 C. Appendix C - Some name space IDs . . . . . . . . . . . . . . . 29 88 Intellectual Property and Copyright Statements . . . . . . . . 31 90 1. Introduction 92 This specification defines a Uniform Resource Name namespace for 93 UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally 94 Unique IDentifier). A UUID is 128 bits long, and requires no central 95 registration process. 97 The information here is meant to be a concise guide for those wishing 98 to implement services using UUIDs as URNs. Nothing in this document 99 should be construed to mean that it overrides the DCE standards that 100 defined UUIDs to begin with. 102 There is an ITU-T Recommendation and ISO/IEC Standard [3] that are 103 derived from earlier versions of this document. Both sets of 104 specifications have been aligned, and are fully technically 105 compatible. In addition, a global registration function is being 106 provided by the Telecommunications Standardisation Bureau of ITU-T; 107 for details see . 109 2. Motivation 111 One of the main reasons for using UUIDs is that no centralized 112 authority is required to administer them (although one format uses 113 IEEE 802 node identifiers, others do not). As a result, generation 114 on demand can be completely automated, and they can be used for a 115 wide variety of purposes. The UUID generation algorithm described 116 here supports very high allocation rates: 10 million per second per 117 machine if necessary, so that they could even be used as transaction 118 IDs. 120 UUIDs are of a fixed size (128 bits) which is reasonably small 121 relative to other alternatives. This lends itself well to sorting, 122 ordering, and hashing of all sorts, storing in databases, simple 123 allocation, and ease of programming in general. 125 Since UUIDs are unique and persistent, they make excellent Uniform 126 Resource Names. The unique ability to generate a new UUID without a 127 registration process allows for UUIDs to be one of the URNs with the 128 lowest minting cost. 130 3. Namespace Registration Template 132 Namespace ID: UUID 133 Registration Information: 134 Registration date: 2003-10-01 136 Declared registrant of the namespace: 137 JTC 1/SC6 (ASN.1 Rapporteur Group) 138 Declaration of syntactic structure: 139 A UUID is an identifier that is unique across both space and time, 140 with respect to the space of all UUIDs. Since a UUID is a fixed 141 size and contains a time field, it is possible for values to 142 rollover (around A.D. 3400, depending on the specific algorithm 143 used). A UUID can be used for multiple purposes, from tagging 144 objects with an extremely short lifetime, to reliably identifying 145 very persistent objects across a network. 147 The internal representation of a UUID is a specific sequence of 148 bits in memory, as described in Section 4. In order to accurately 149 represent a UUID as a URN, it is necessary to convert the bit 150 sequence to a string representation. 152 Each field is treated as an integer and has its value printed as a 153 zero-filled hexadecimal digit string with the most significant 154 digit first. The hexadecimal values a through f are output as 155 lower case characters, and are case insensitive on input. 157 The formal definition of the UUID string representation is 158 provided by the following ABNF [7]: 160 UUID = time-low "-" time-mid "-" 161 time-high-and-version "-" 162 clock-seq-and-reserved 163 clock-seq-low "-" node 164 time-low = 4hexOctet 165 time-mid = 2hexOctet 166 time-high-and-version = 2hexOctet 167 clock-seq-and-reserved = hexOctet 168 clock-seq-low = hexOctet 169 node = 6hexOctet 170 hexOctet = hexDigit hexDigit 171 hexDigit = 172 "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / 173 "a" / "b" / "c" / "d" / "e" / "f" / 174 "A" / "B" / "C" / "D" / "E" / "F" 176 The following is an example of the string representation of a UUID 177 as a URN: 179 urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 180 Relevant ancillary documentation: 181 [2] 182 Identifier uniqueness considerations: 183 This document specifies three algorithms to generate UUIDs: the 184 first leverages the unique values of 802 MAC addresses to 185 guarantee uniqueness, the second another uses pseudo-random number 186 generators, and the third uses cryptographic hashing and 187 application-provided text strings. As a result, it is possible to 188 guarantee that UUIDs generated according to the mechanisms here 189 will be unique from all other UUIDs that have been or will be 190 assigned. 191 Identifier persistence considerations: 192 UUIDs are inherently very difficult to resolve in a global sense. 193 This, coupled with the fact that UUIDs are temporally unique 194 within their spatial context, ensures that UUIDs will remain as 195 persistent as possible. 196 Process of identifier assignment: 197 Generating a UUID does not require that it be a registration 198 authority be contacted. One algorithm requires a unique value 199 over space for each generator. This value is typically an IEEE 200 802 MAC address, usually already available on network-connected 201 hosts. The address can be assigned from an address block obtained 202 from the IEEE registration authority. If no such address is 203 available, or privacy concerns make its use undesirable, Section 204 4.5 specifies two alternatives; another approach is to use version 205 3 or version 4 UUIDs as defined below. 206 Process for identifier resolution: 207 Since UUIDs are not globally resolvable, this is not applicable. 208 Rules for Lexical Equivalence: 209 Consider each field of the UUID to be an unsigned integer as shown 210 in the table in section Section 4.1.2. Then, to compare a pair of 211 UUIDs, arithmetically compare the corresponding fields from each 212 UUID in order of significance and according to their data type. 213 Two UUIDs are equal if and only if all the corresponding fields 214 are equal. 216 As an implementation note, on many systems equality comparison can 217 be performed by doing the appropriate byte-order canonicalization, 218 and then treating the two UUIDs as 128-bit unsigned integers. 220 UUIDs as defined in this document can also be ordered 221 lexicographically. For a pair of UUIDs, the first one follows the 222 second if the most significant field in which the UUIDs differ is 223 greater for the first UUID. The second precedes the first if the 224 most significant field in which the UUIDs differ is greater for 225 the second UUID. 227 Conformance with URN Syntax: 228 The string representation of a UUID is fully compatible with the 229 URN syntax. When converting from an bit-oriented, in-memory 230 representation of a UUID into a URN, care must be taken to 231 strictly adhere to the byte order issues mentioned in the string 232 representation section. 233 Validation mechanism: 234 Apart from determining if the timestamp portion of the UUID is in 235 the future and therefore not yet assignable, there is no mechanism 236 for determining if a UUID is 'valid' in any real sense. 237 Scope: 238 UUIDs are global in scope. 240 4. Specification 242 4.1 Format 244 In its most general form, all that can be said of the UUID format is 245 that a UUID is 16 octets, and that some bits of the eight octet -- 246 the variant field specified below -- determine finer structure. 248 4.1.1 Variant 250 The variant field determines the layout of the UUID. That is, the 251 interpretation of all other bits in the UUID depends on the setting 252 of the bits in the variant field. As such, it could more accurately 253 be called a type field; we retain the original term for 254 compatibility. The variant field consists of a variable number of 255 the most significant bits of the eighth octet of the UUID. 257 The following table lists the contents of the variant field, where 258 the letter "x" indicates a "don't-care" value. 260 Msb0 Msb1 Msb2 Description 262 0 x x Reserved, NCS backward compatibility. 264 1 0 x The variant specified in this document. 266 1 1 0 Reserved, Microsoft Corporation backward 267 compatibility 269 1 1 1 Reserved for future definition. 271 Interoperability (in any form) with variants other than the one 272 defined here is not guaranteed. This is unlikely to be an issue in 273 practice. 275 4.1.2 Layout and byte order 277 To minimize confusion about bit assignments within octets, the UUID 278 record definition is defined only in terms of fields that are 279 integral numbers of octets. The fields are presented with the most 280 significant one first. 282 Field Data Type Octet Note 283 # 285 time_low unsigned 32 0-3 The low field of the 286 bit integer timestamp 288 time_mid unsigned 16 4-5 The middle field of the 289 bit integer timestamp 291 time_hi_and_version unsigned 16 6-7 The high field of the 292 bit integer timestamp multiplexed 293 with the version number 295 clock_seq_hi_and_rese unsigned 8 8 The high field of the 296 rved bit integer clock sequence 297 multiplexed with the 298 variant 300 clock_seq_low unsigned 8 9 The low field of the 301 bit integer clock sequence 303 node unsigned 48 10-15 The spatially unique 304 bit integer node identifier 306 In the absence of explicit application or presentation protocol 307 specification to the contrary, a UUID is encoded as a 128-bit object, 308 as follows: the fields are encoded as 16 octets, with the sizes and 309 order of the fields defined above, and with each field encoded with 310 the Most Significant Byte first (this is known as network byte 311 order). Note that the field names, particularly for multiplexed 312 fields, follow historical practice. 314 0 1 2 3 315 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 316 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 317 | time_low | 318 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 319 | time_mid | time_hi_and_version | 320 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 321 |clk_seq_hi_res | clk_seq_low | node (0-1) | 322 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 323 | node (2-5) | 324 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 326 4.1.3 Version 328 The version number is in the most significant four bits of the time 329 stamp (bits four through seven of the time_hi_and_version field). 331 The following table lists the currently-defined versions for this 332 UUID variant. 334 Msb0 Msb1 Msb2 Msb3 Version Description 336 0 0 0 1 1 The time-based version 337 specified in this document. 339 0 0 1 0 2 DCE Security version, with 340 embedded POSIX UIDs. 342 0 0 1 1 3 The name-based version 343 specified in this document 344 that uses MD5 hashing. 346 0 1 0 0 4 The randomly or pseudo- 347 randomly generated version 348 specified in this document. 350 0 0 1 1 5 The name-based version 351 specified in this document 352 that uses SHA-1 hashing. 354 The version is more accurately a sub-type; again, we retain the term 355 for compatibility. 357 4.1.4 Timestamp 359 The timestamp is a 60-bit value. For UUID version 1, this is 360 represented by Coordinated Universal Time (UTC) as a count of 361 100-nanosecond intervals since 00:00:00.00, 15 October 1582 (the date 362 of Gregorian reform to the Christian calendar). 364 For systems that do not have UTC available, but do have the local 365 time, they may use that instead of UTC, as long as they do so 366 consistently throughout the system. This is not recommended however, 367 particularly since all that is needed to generate UTC from local time 368 is a time zone offset. 370 For UUID version 3 or 5, the timestamp is a 60-bit value constructed 371 from a name as described in Section 4.3. 373 For UUID version 4, it is a randomly or pseudo-randomly generated 374 60-bit value, as described in Section 4.4. 376 4.1.5 Clock sequence 378 For UUID version 1, the clock sequence is used to help avoid 379 duplicates that could arise when the clock is set backwards in time 380 or if the node ID changes. 382 If the clock is set backwards, or even might have been set backwards 383 (e.g., while the system was powered off), and the UUID generator can 384 not be sure that no UUIDs were generated with timestamps larger than 385 the value to which the clock was set, then the clock sequence has to 386 be changed. If the previous value of the clock sequence is known, it 387 can be just incremented; otherwise it should be set to a random or 388 high-quality pseudo random value. 390 Similarly, if the node ID changes (e.g. because a network card has 391 been moved between machines), setting the clock sequence to a random 392 number minimizes the probability of a duplicate due to slight 393 differences in the clock settings of the machines. (If the value of 394 clock sequence associated with the changed node ID were known, then 395 the clock sequence could just be incremented, but that is unlikely.) 397 The clock sequence MUST be originally (i.e., once in the lifetime of 398 a system) initialized to a random number to minimize the correlation 399 across systems. This provides maximum protection against node 400 identifiers that may move or switch from system to system rapidly. 401 The initial value MUST NOT be correlated to the node identifier. 403 For UUID version 3 or 5, it is a 14-bit value constructed from a name 404 as described in Section 4.3. 406 For UUID version 4, it is a randomly or pseudo-randomly generated 407 14-bit value as described in Section 4.4. 409 4.1.6 Node 411 For UUID version 1, the node field consists of an IEEE 802 MAC 412 address, usually the host address. For systems with multiple IEEE 413 802 addresses, any available one can be used. The lowest addressed 414 octet (octet number 10) contains the global/local bit and the 415 unicast/multicast bit, and is the first octet of the address 416 transmitted on an 802.3 LAN. 418 For systems with no IEEE address, a randomly or pseudo-randomly 419 generated value may be used; see Section 4.5. The multicast bit must 420 be set in such addresses, in order that they will never conflict with 421 addresses obtained from network cards. 423 For UUID version 3 or 5, the node field is a 48-bit value constructed 424 from a name as described in Section 4.3. 426 For UUID version 4, the node field is a randomly or pseudo-randomly 427 generated 48-bit value as described in Section 4.4. 429 4.1.7 Nil UUID 431 The nil UUID is special form of UUID that is specified to have all 432 128 bits set to zero. 434 4.2 Algorithms for creating a time-based UUID 436 Various aspects of the algorithm for creating a version 1 UUID are 437 discussed in the following sections. 439 4.2.1 Basic algorithm 441 The following algorithm is simple, correct, and inefficient: 442 o Obtain a system-wide global lock 443 o From a system-wide shared stable store (e.g., a file), read the 444 UUID generator state: the values of the time stamp, clock 445 sequence, and node ID used to generate the last UUID. 446 o Get the current time as a 60-bit count of 100-nanosecond intervals 447 since 00:00:00.00, 15 October 1582 448 o Get the current node ID 449 o If the state was unavailable (e.g., non-existent or corrupted), or 450 the saved node ID is different than the current node ID, generate 451 a random clock sequence value 452 o If the state was available, but the saved time stamp is later than 453 the current time stamp, increment the clock sequence value 454 o Save the state (current time stamp, clock sequence, and node ID) 455 back to the stable store 456 o Release the global lock 457 o Format a UUID from the current time stamp, clock sequence, and 458 node ID values according to the steps in Section 4.2.2. 460 If UUIDs do not need to be frequently generated, the above algorithm 461 may be perfectly adequate. For higher performance requirements, 462 however, issues with the basic algorithm include: 463 o Reading the state from stable storage each time is inefficient 464 o The resolution of the system clock may not be 100-nanoseconds 465 o Writing the state to stable storage each time is inefficient 466 o Sharing the state across process boundaries may be inefficient 468 Each of these issues can be addressed in a modular fashion by local 469 improvements in the functions that read and write the state and read 470 the clock. We address each of them in turn in the following 471 sections. 473 4.2.1.1 Reading stable storage 475 The state only needs to be read from stable storage once at boot 476 time, if it is read into a system-wide shared volatile store (and 477 updated whenever the stable store is updated). 479 If an implementation does not have any stable store available, then 480 it can always say that the values were unavailable. This is the 481 least desirable implementation, because it will increase the 482 frequency of creation of new clock sequence numbers, which increases 483 the probability of duplicates. 485 If the node ID can never change (e.g., the net card is inseparable 486 from the system), or if any change also reinitializes the clock 487 sequence to a random value, then instead of keeping it in stable 488 store, the current node ID may be returned. 490 4.2.1.2 System clock resolution 492 The time stamp is generated from the system time, whose resolution 493 may be less than the resolution of the UUID time stamp. 495 If UUIDs do not need to be frequently generated, the time stamp can 496 simply be the system time multiplied by the number of 100-nanosecond 497 intervals per system time interval. 499 If a system overruns the generator by requesting too many UUIDs 500 within a single system time interval, the UUID service MUST either: 501 return an error, or stall the UUID generator until the system clock 502 catches up. 504 A high resolution time stamp can be simulated by keeping a count of 505 how many UUIDs have been generated with the same value of the system 506 time, and using it to construction the low-order bits of the time 507 stamp. The count will range between zero and the number of 508 100-nanosecond intervals per system time interval. 510 Note: if the processors overrun the UUID generation frequently, 511 additional node identifiers can be allocated to the system, which 512 will permit higher speed allocation by making multiple UUIDs 513 potentially available for each time stamp value. 515 4.2.1.3 Writing stable storage 517 The state does not always need to be written to stable store every 518 time a UUID is generated. The timestamp in the stable store can be 519 periodically set to a value larger than any yet used in a UUID; as 520 long as the generated UUIDs have time stamps less than that value, 521 and the clock sequence and node ID remain unchanged, only the shared 522 volatile copy of the state needs to be updated. Furthermore, if the 523 time stamp value in stable store is in the future by less than the 524 typical time it takes the system to reboot, a crash will not cause a 525 reinitialization of the clock sequence. 527 4.2.1.4 Sharing state across processes 529 If it is too expensive to access shared state each time a UUID is 530 generated, then the system-wide generator can be implemented to 531 allocate a block of time stamps each time it is called, and a 532 per-process generator can allocate from that block until it is 533 exhausted. 535 4.2.2 Generation details 537 Version 1 UUIDs are generated according to the following algorithm: 538 o Determine the values for the UTC-based timestamp and clock 539 sequence to be used in the UUID, as described in Section 4.2.1. 540 o For the purposes of this algorithm, consider the timestamp to be a 541 60-bit unsigned integer and the clock sequence to be a 14-bit 542 unsigned integer. Sequentially number the bits in a field, 543 starting with zero for the least significant bit. 544 o Set the time_low field equal to the least significant 32 bits 545 (bits zero through 31) of the time stamp in the same order of 546 significance. 547 o Set the time_mid field equal to bits 32 through 47 from the time 548 stamp in the same order of significance. 549 o Set the 12 least significant bits (bits zero through 11) of the 550 time_hi_and_version field equal to bits 48 through 59 from the 551 time stamp in the same order of significance. 552 o Set the four most significant bits (bits 12 through 15) of the 553 time_hi_and_version field to the four-bit version number 554 corresponding to the UUID version being created, as shown in the 555 table above. 556 o Set the clock_seq_low field to the eight least significant bits 557 (bits zero through seven) of the clock sequence in the same order 558 of significance. 559 o Set the six least significant bits (bits zero through five) of the 560 clock_seq_hi_and_reserved field to the six most significant bits 561 (bits eight through 13) of the clock sequence in the same order of 562 significance. 563 o Set the two most significant bits (bits six and seven) of the 564 clock_seq_hi_and_reserved to zero and one, respectively. 565 o Set the node field to the 48-bit IEEE address in the same order of 566 significance as the address. 568 4.3 Algorithm for creating a name-based UUID 570 The version 3 or 5 UUID is meant for generating UUIDs from "names" 571 that are drawn from, and unique within, some "name space." The 572 concept of name and name space should be broadly construed, and not 573 limited to textual names. For example, some name spaces are the 574 domain name system, URLs, ISO Object IDs (OIDs), X.500 Distinguished 575 Names (DNs), and reserved words in a programming language. The 576 mechanisms or conventions for allocating names from, and ensuring 577 their uniqueness within, their name spaces are beyond the scope of 578 this specification. 580 The requirements for these types of UUIDs are as follows: 581 o The UUIDs generated at different times from the same name in the 582 same namespace MUST be equal 583 o The UUIDs generated from two different names in the same namespace 584 should be different (with very high probability) 585 o The UUIDs generated from the same name in two different namespaces 586 should be different with (very high probability) 587 o If two UUIDs that were generated from names are equal, then they 588 were generated from the same name in the same namespace (with very 589 high probability). 591 The algorithm for generating the a UUID from a name and a name space 592 are as follows: 593 o Allocate a UUID to use as a "name space ID" for all UUIDs 594 generated from names in that name space; see Appendix C for some 595 pre-defined values 596 o Choose either MD5 [4] or SHA-1 [8] as the hash algorithm; If 597 backward compatibility is not an issue, SHA-1 is preferred 598 o Convert the name to a canonical sequence of octets (as defined by 599 the standards or conventions of its name space); put the name 600 space ID in network byte order 601 o Compute the hash of the name space ID concatenated with the name 602 o Set octets zero through three of the time_low field to octets zero 603 through three of the hash 604 o Set octets zero and one of the time_mid field to octets four and 605 five of the hash 606 o Set octets zero and one of the time_hi_and_version field to octets 607 six and seven of the MD5 hash 609 o Set the four most significant bits (bits 12 through 15) of the 610 time_hi_and_version field to the appropriate four-bit version 611 number from Section 4.1.3 612 o Set the clock_seq_hi_and_reserved field to octet eight of the hash 613 o Set the two most significant bits (bits six and seven) of the 614 clock_seq_hi_and_reserved to zero and one, respectively. 615 o Set the clock_seq_low field to octet nine of the hash 616 o Set octets zero through five of the node field to octets ten 617 through fifteen of the hash 618 o Convert the resulting UUID to local byte order. 620 4.4 Algorithms for creating a UUID from truly random or pseudo-random 621 numbers 623 The version 4 UUID is meant for generating UUIDs from truly-random or 624 pseudo-random numbers. 626 The algorithm is as follows: 627 o Set the two most significant bits (bits six and seven) of the 628 clock_seq_hi_and_reserved to zero and one, respectively. 629 o Set the four most significant bits (bits 12 through 15) of the 630 time_hi_and_version field to the four-bit version number from 631 Section 4.1.3. 632 o Set all the other bits to randomly (or pseudo-randomly) chosen 633 values. 635 See Section 4.5 for a discussion on random numbers. 637 4.5 Node IDs that do not identify the host 639 This section describes how to generate a version 1 UUID if an IEEE 640 802 address is not available, or its use is not desired. 642 One approach is to contact the IEEE and get a separate block of 643 addresses. At the time of writing, the application could be found at 644 , and the cost 645 was US$550. 647 A better solution is to obtain a 47-bit cryptographic quality random 648 number, and use it as the low 47 bits of the node ID, with the least 649 significant bit of the first octet of the node ID set to one. This 650 bit is the unicast/multicast bit, which will never be set in IEEE 802 651 addresses obtained from network cards; hence, there can never be a 652 conflict between UUIDs generated by machines with and without network 653 cards. (Recall that the IEEE 802 spec talks about transmission 654 order, which is the opposite of the in-memory representation that is 655 discussed in this document.) 656 (For compatibility with earlier specifications, note that this 657 document uses the unicast/multicast bit, instead of the arguably more 658 correct local/global bit.) 660 Advice on generating cryptographic-quality random numbers can be 661 found in RFC1750 [5]. 663 In addition, items such as the computer's name and the name of the 664 operating system, while not strictly speaking random, will help 665 differentiate the results from those obtained by other systems. 667 The exact algorithm to generate a node ID using these data is system 668 specific, because both the data available and the functions to obtain 669 them are often very system specific. A generic approach, however is 670 to accumulate as many sources as possible into a buffer, and use a 671 message digest such as MD5 [4] or SHA-1 [8], take an arbitrary six 672 bytes from the hash value, and set the multicast bit as described 673 above. 675 5. Community Considerations 677 The use of UUIDs is extremely pervasive in computing. They comprise 678 the core identifier infrastructure for many operating systems 679 (Microsoft Windows) and applications (the Mozilla browser) and in 680 many cases, become exposed to the web in many non-standard ways. 681 This specification attempts to standardize that practice as openly as 682 possible and in a way that attempts to benefit the entire Internet. 684 6. Security Considerations 686 Do not assume that UUIDs are hard to guess; they should not be used 687 as security capabilities (identifiers whose mere possession grants 688 access), for example. A predictable random number source will 689 exacerbate the situation. 691 Do not assume that it is easy to determine if a UUID has been 692 slightly transposed in order to redirect a reference to another 693 object. Humans do not have the ability to easily check the integrity 694 of a UUID by simply glancing at it. 696 Distributed applications generating UUIDs at a variety of hosts must 697 be willing to rely on the random number source at all hosts. If this 698 is not feasible, the namespace variant should be used. 700 7. Acknowledgments 702 This document draws heavily on the OSF DCE specification for UUIDs. 703 Ted Ts'o provided helpful comments, especially on the byte ordering 704 section which we mostly plagiarized from a proposed wording he 705 supplied (all errors in that section are our responsibility, 706 however). 708 We are also grateful to the careful reading and bit-twiddling of 709 Ralph S. Engelschall, John Larmouth, and Paul Thorpe. Professor 710 Larmouth was also invaluable in achieving coordination with ISO/IEC. 712 8 Normative References 714 [1] Zahn, L., Dineen, T. and P. Leach, "Network Computing 715 Architecture", ISBN 0-13-611674-4, January 1990. 717 [2] "DCE: Remote Procedure Call", Open Group CAE Specification C309, 718 ISBN 1-85912-041-5, August 1994. 720 [3] ISO/IEC 9834-8:2004 Information Technology, "Procedures for the 721 Operation of Registration Authorities - Generation of 722 Universally Unique/Globally Unique Identifiers (UUID/GUID)", 723 ITU-T Rec. X.687, 2004. 725 [4] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April 726 1992. 728 [5] Eastlake, D., Crocker, S. and J. Schiller, "Randomness 729 Recommendations for Security", RFC 1750, December 1994. 731 [6] Moats, R., "URN Syntax", RFC 2141, May 1997. 733 [7] Crocker, D. and P. Overell, "Augmented BNF for Syntax 734 Specifications: ABNF", RFC 2234, November 1997. 736 [8] National Institute of Standards and Technology, "Secure Hash 737 Standard", FIPS PUB 180-1, April 1995, 738 . 740 Authors' Addresses 742 Paul J. Leach 743 Microsoft 744 1 Microsoft Way 745 Redmond, WA 98052 746 US 748 Phone: +1 425-882-8080 749 EMail: paulle@microsoft.com 750 Michael Mealling 751 VeriSign, Inc. 752 21345 Ridgetop Circle 753 Dulles, VA 21345 754 US 756 Phone: +1 770-717-0732 757 EMail: michael@neonym.net 758 URI: http://www.verisignlabs.com 760 Rich Salz 761 DataPower Technology, Inc. 762 1 Alewife Center 763 Cambridge, MA 02142 764 US 766 Phone: +1 617-864-0455 767 EMail: rsalz@datapower.com 768 URI: http://www.datapower.com 770 Appendix A. Appendix A - Sample Implementation 772 This implementation consists of 5 files: uuid.h, uuid.c, sysdep.h, 773 sysdep.c and utest.c. The uuid.* files are the system independent 774 implementation of the UUID generation algorithms described above, 775 with all the optimizations described above except efficient state 776 sharing across processes included. The code has been tested on Linux 777 (Red Hat 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. 778 The code assumes 64-bit integer support, which makes it a lot 779 clearer. 781 All the following source files should be considered to have the 782 following copyright notice included: 784 copyrt.h 786 /* 787 ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. 788 ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & 789 ** Digital Equipment Corporation, Maynard, Mass. 790 ** Copyright (c) 1998 Microsoft. 791 ** To anyone who acknowledges that this file is provided "AS IS" 792 ** without any express or implied warranty: permission to use, copy, 793 ** modify, and distribute this file for any purpose is hereby 794 ** granted without fee, provided that the above copyright notices and 795 ** this notice appears in all source code copies, and that none of 796 ** the names of Open Software Foundation, Inc., Hewlett-Packard 797 ** Company, or Digital Equipment Corporation be used in advertising 798 ** or publicity pertaining to distribution of the software without 799 ** specific, written prior permission. Neither Open Software 800 ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital 801 ** Equipment Corporation makes any representations about the suitability 802 ** of this software for any purpose. 803 */ 805 uuid.h 807 #include "copyrt.h" 808 #undef uuid_t 809 typedef struct { 810 unsigned32 time_low; 811 unsigned16 time_mid; 812 unsigned16 time_hi_and_version; 813 unsigned8 clock_seq_hi_and_reserved; 814 unsigned8 clock_seq_low; 815 byte node[6]; 816 } uuid_t; 818 /* uuid_create -- generate a UUID */ 819 int uuid_create(uuid_t * uuid); 821 /* uuid_create_md5_from_name -- create a version 3 (MD5) UUID using a "name" 822 from a "name space" */ 823 void uuid_create_md5_from_name( 824 uuid_t *uuid, /* resulting UUID */ 825 uuid_t nsid, /* UUID of the namespace */ 826 void *name, /* the name from which to generate a UUID */ 827 int namelen /* the length of the name */ 828 ); 830 /* uuid_create_sha1_from_name -- create a version 5 (SHA-1) UUID using a "name" 831 from a "name space" */ 832 void uuid_create_sha1_from_name( 833 uuid_t *uuid, /* resulting UUID */ 834 uuid_t nsid, /* UUID of the namespace */ 835 void *name, /* the name from which to generate a UUID */ 836 int namelen /* the length of the name */ 837 ); 839 /* uuid_compare -- Compare two UUID's "lexically" and return 840 -1 u1 is lexically before u2 841 0 u1 is equal to u2 842 1 u1 is lexically after u2 843 Note that lexical ordering is not temporal ordering! 845 */ 846 int uuid_compare(uuid_t *u1, uuid_t *u2); 848 uuid.c 850 #include "copyrt.h" 851 #include 852 #include 853 #include 854 #include 855 #include "sysdep.h" 856 #include "uuid.h" 858 /* various forward declarations */ 859 static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, 860 uuid_node_t *node); 861 static void write_state(unsigned16 clockseq, uuid_time_t timestamp, 862 uuid_node_t node); 863 static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq, 864 uuid_time_t timestamp, uuid_node_t node); 865 static void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16], 866 int v); 867 static void get_current_time(uuid_time_t *timestamp); 868 static unsigned16 true_random(void); 870 /* uuid_create -- generator a UUID */ 871 int uuid_create(uuid_t *uuid) 872 { 873 uuid_time_t timestamp, last_time; 874 unsigned16 clockseq; 875 uuid_node_t node; 876 uuid_node_t last_node; 877 int f; 879 /* acquire system-wide lock so we're alone */ 880 LOCK; 882 /* get time, node ID, saved state from non-volatile storage */ 883 get_current_time(×tamp); 884 get_ieee_node_identifier(&node); 885 f = read_state(&clockseq, &last_time, &last_node); 887 /* if no NV state, or if clock went backwards, or node ID changed 888 (e.g., new network card) change clockseq */ 889 if (!f || memcmp(&node, &last_node, sizeof node)) 890 clockseq = true_random(); 891 else if (timestamp < last_time) 892 clockseq++; 894 /* save the state for next time */ 895 write_state(clockseq, timestamp, node); 897 UNLOCK; 899 /* stuff fields into the UUID */ 900 format_uuid_v1(uuid, clockseq, timestamp, node); 901 return 1; 902 } 904 /* format_uuid_v1 -- make a UUID from the timestamp, clockseq, 905 and node ID */ 906 void format_uuid_v1(uuid_t* uuid, unsigned16 clock_seq, 907 uuid_time_t timestamp, uuid_node_t node) 908 { 909 /* Construct a version 1 uuid with the information we've gathered 910 plus a few constants. */ 911 uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF); 912 uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF); 913 uuid->time_hi_and_version = 914 (unsigned short)((timestamp >> 48) & 0x0FFF); 915 uuid->time_hi_and_version |= (1 << 12); 916 uuid->clock_seq_low = clock_seq & 0xFF; 917 uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8; 918 uuid->clock_seq_hi_and_reserved |= 0x80; 919 memcpy(&uuid->node, &node, sizeof uuid->node); 920 } 922 /* data type for UUID generator persistent state */ 923 typedef struct { 924 uuid_time_t ts; /* saved timestamp */ 925 uuid_node_t node; /* saved node ID */ 926 unsigned16 cs; /* saved clock sequence */ 927 } uuid_state; 929 static uuid_state st; 931 /* read_state -- read UUID generator state from non-volatile store */ 932 int read_state(unsigned16 *clockseq, uuid_time_t *timestamp, 933 uuid_node_t *node) 934 { 935 static int inited = 0; 936 FILE *fp; 938 /* only need to read state once per boot */ 939 if (!inited) { 940 fp = fopen("state", "rb"); 941 if (fp == NULL) 942 return 0; 943 fread(&st, sizeof st, 1, fp); 944 fclose(fp); 945 inited = 1; 946 } 947 *clockseq = st.cs; 948 *timestamp = st.ts; 949 *node = st.node; 950 return 1; 951 } 953 /* write_state -- save UUID generator state back to non-volatile storage */ 954 void write_state(unsigned16 clockseq, uuid_time_t timestamp, 955 uuid_node_t node) 956 { 957 static int inited = 0; 958 static uuid_time_t next_save; 959 FILE* fp; 961 if (!inited) { 962 next_save = timestamp; 963 inited = 1; 964 } 966 /* always save state to volatile shared state */ 967 st.cs = clockseq; 968 st.ts = timestamp; 969 st.node = node; 970 if (timestamp >= next_save) { 971 fp = fopen("state", "wb"); 972 fwrite(&st, sizeof st, 1, fp); 973 fclose(fp); 974 /* schedule next save for 10 seconds from now */ 975 next_save = timestamp + (10 * 10 * 1000 * 1000); 976 } 977 } 979 /* get-current_time -- get time as 60-bit 100ns ticks since UUID epoch. 980 Compensate for the fact that real clock resolution is 981 less than 100ns. */ 982 void get_current_time(uuid_time_t *timestamp) 983 { 984 static int inited = 0; 985 static uuid_time_t time_last; 986 static unsigned16 uuids_this_tick; 987 uuid_time_t time_now; 988 if (!inited) { 989 get_system_time(&time_now); 990 uuids_this_tick = UUIDS_PER_TICK; 991 inited = 1; 992 } 994 for ( ; ; ) { 995 get_system_time(&time_now); 997 /* if clock reading changed since last UUID generated, */ 998 if (time_last != time_now) { 999 /* reset count of uuids gen'd with this clock reading */ 1000 uuids_this_tick = 0; 1001 time_last = time_now; 1002 break; 1003 } 1004 if (uuids_this_tick < UUIDS_PER_TICK) { 1005 uuids_this_tick++; 1006 break; 1007 } 1008 /* going too fast for our clock; spin */ 1009 } 1010 /* add the count of uuids to low order bits of the clock reading */ 1011 *timestamp = time_now + uuids_this_tick; 1012 } 1014 /* true_random -- generate a crypto-quality random number. 1015 **This sample doesn't do that.** */ 1016 static unsigned16 true_random(void) 1017 { 1018 static int inited = 0; 1019 uuid_time_t time_now; 1021 if (!inited) { 1022 get_system_time(&time_now); 1023 time_now = time_now / UUIDS_PER_TICK; 1024 srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff)); 1025 inited = 1; 1026 } 1028 return rand(); 1029 } 1031 /* uuid_create_md5_from_name -- create a version 3 (MD5) UUID using a "name" 1032 from a "name space" */ 1033 void uuid_create_md5_from_name(uuid_t *uuid, uuid_t nsid, void *name, 1034 int namelen) 1035 { 1036 MD5_CTX c; 1037 unsigned char hash[16]; 1038 uuid_t net_nsid; 1040 /* put name space ID in network byte order so it hashes the same 1041 no matter what endian machine we're on */ 1042 net_nsid = nsid; 1043 net_nsid.time_low = htonl(net_nsid.time_low); 1044 net_nsid.time_mid = htons(net_nsid.time_mid); 1045 net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version); 1047 MD5Init(&c); 1048 MD5Update(&c, &net_nsid, sizeof net_nsid); 1049 MD5Update(&c, name, namelen); 1050 MD5Final(hash, &c); 1052 /* the hash is in network byte order at this point */ 1053 format_uuid_v3or5(uuid, hash, 3); 1054 } 1056 void uuid_create_sha1_from_name(uuid_t *uuid, uuid_t nsid, void *name, 1057 int namelen) 1058 { 1059 SHA_CTX c; 1060 unsigned char hash[16]; 1061 uuid_t net_nsid; 1063 /* put name space ID in network byte order so it hashes the same 1064 no matter what endian machine we're on */ 1065 net_nsid = nsid; 1066 net_nsid.time_low = htonl(net_nsid.time_low); 1067 net_nsid.time_mid = htons(net_nsid.time_mid); 1068 net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version); 1070 SHA1_Init(&c); 1071 SHA1_Update(&c, &net_nsid, sizeof net_nsid); 1072 SHA1_Update(&c, name, namelen); 1073 SHA1_Final(hash, &c); 1075 /* the hash is in network byte order at this point */ 1076 format_uuid_v3or5(uuid, hash, 5); 1077 } 1079 /* format_uuid_v3or5 -- make a UUID from a (pseudo)random 128-bit number */ 1080 void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16], int v) 1081 { 1082 /* convert UUID to local byte order */ 1083 memcpy(uuid, hash, sizeof *uuid); 1084 uuid->time_low = ntohl(uuid->time_low); 1085 uuid->time_mid = ntohs(uuid->time_mid); 1086 uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version); 1088 /* put in the variant and version bits */ 1089 uuid->time_hi_and_version &= 0x0FFF; 1090 uuid->time_hi_and_version |= (v << 12); 1091 uuid->clock_seq_hi_and_reserved &= 0x3F; 1092 uuid->clock_seq_hi_and_reserved |= 0x80; 1093 } 1095 /* uuid_compare -- Compare two UUID's "lexically" and return */ 1096 #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1; 1097 int uuid_compare(uuid_t *u1, uuid_t *u2) 1098 { 1099 int i; 1101 CHECK(u1->time_low, u2->time_low); 1102 CHECK(u1->time_mid, u2->time_mid); 1103 CHECK(u1->time_hi_and_version, u2->time_hi_and_version); 1104 CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved); 1105 CHECK(u1->clock_seq_low, u2->clock_seq_low) 1106 for (i = 0; i < 6; i++) { 1107 if (u1->node[i] < u2->node[i]) 1108 return -1; 1109 if (u1->node[i] > u2->node[i]) 1110 return 1; 1111 } 1112 return 0; 1113 } 1114 #undef CHECK 1116 sysdep.h 1118 #include "copyrt.h" 1119 /* remove the following define if you aren't running WIN32 */ 1120 #define WININC 0 1122 #ifdef WININC 1123 #include 1124 #else 1125 #include 1126 #include 1127 #include 1128 #endif 1130 #include "global.h" 1131 /* change to point to where MD5 .h's live; RFC 1321 has sample 1132 implementation */ 1133 #include "md5.h" 1135 /* set the following to the number of 100ns ticks of the actual 1136 resolution of your system's clock */ 1137 #define UUIDS_PER_TICK 1024 1139 /* Set the following to a calls to get and release a global lock */ 1140 #define LOCK 1141 #define UNLOCK 1143 typedef unsigned long unsigned32; 1144 typedef unsigned short unsigned16; 1145 typedef unsigned char unsigned8; 1146 typedef unsigned char byte; 1148 /* Set this to what your compiler uses for 64-bit data type */ 1149 #ifdef WININC 1150 #define unsigned64_t unsigned __int64 1151 #define I64(C) C 1152 #else 1153 #define unsigned64_t unsigned long long 1154 #define I64(C) C##LL 1155 #endif 1157 typedef unsigned64_t uuid_time_t; 1158 typedef struct { 1159 char nodeID[6]; 1160 } uuid_node_t; 1162 void get_ieee_node_identifier(uuid_node_t *node); 1163 void get_system_time(uuid_time_t *uuid_time); 1164 void get_random_info(char seed[16]); 1166 sysdep.c 1168 #include "copyrt.h" 1169 #include 1170 #include "sysdep.h" 1172 /* system dependent call to get IEEE node ID. 1173 This sample implementation generates a random node ID. */ 1174 void get_ieee_node_identifier(uuid_node_t *node) 1175 { 1176 static inited = 0; 1177 static uuid_node_t saved_node; 1178 char seed[16]; 1179 FILE *fp; 1181 if (!inited) { 1182 fp = fopen("nodeid", "rb"); 1183 if (fp) { 1184 fread(&saved_node, sizeof saved_node, 1, fp); 1185 fclose(fp); 1186 } 1187 else { 1188 get_random_info(seed); 1189 seed[0] |= 0x01; 1190 memcpy(&saved_node, seed, sizeof saved_node); 1191 fp = fopen("nodeid", "wb"); 1192 if (fp) { 1193 fwrite(&saved_node, sizeof saved_node, 1, fp); 1194 fclose(fp); 1195 } 1196 } 1197 inited = 1; 1198 } 1200 *node = saved_node; 1201 } 1203 /* system dependent call to get the current system time. Returned as 1204 100ns ticks since UUID epoch, but resolution may be less than 100ns. */ 1205 #ifdef _WINDOWS_ 1207 void get_system_time(uuid_time_t *uuid_time) 1208 { 1209 ULARGE_INTEGER time; 1211 /* NT keeps time in FILETIME format which is 100ns ticks since 1212 Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. 1213 The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) 1214 + 18 years and 5 leap days. */ 1215 GetSystemTimeAsFileTime((FILETIME *)&time); 1216 time.QuadPart += 1217 (unsigned __int64) (1000*1000*10) // seconds 1218 * (unsigned __int64) (60 * 60 * 24) // days 1219 * (unsigned __int64) (17+30+31+365*18+5); // # of days 1220 *uuid_time = time.QuadPart; 1221 } 1223 /* Sample code, not for use in production; see RFC 1750 */ 1224 void get_random_info(char seed[16]) 1225 { 1226 MD5_CTX c; 1227 struct { 1228 MEMORYSTATUS m; 1229 SYSTEM_INFO s; 1230 FILETIME t; 1231 LARGE_INTEGER pc; 1232 DWORD tc; 1233 DWORD l; 1234 char hostname[MAX_COMPUTERNAME_LENGTH + 1]; 1235 } r; 1237 MD5Init(&c); 1238 GlobalMemoryStatus(&r.m); 1239 GetSystemInfo(&r.s); 1240 GetSystemTimeAsFileTime(&r.t); 1241 QueryPerformanceCounter(&r.pc); 1242 r.tc = GetTickCount(); 1243 r.l = MAX_COMPUTERNAME_LENGTH + 1; 1244 GetComputerName(r.hostname, &r.l); 1245 MD5Update(&c, &r, sizeof r); 1246 MD5Final(seed, &c); 1247 } 1249 #else 1251 void get_system_time(uuid_time_t *uuid_time) 1252 { 1253 struct timeval tp; 1255 gettimeofday(&tp, (struct timezone *)0); 1257 /* Offset between UUID formatted times and Unix formatted times. 1258 UUID UTC base time is October 15, 1582. 1259 Unix base time is January 1, 1970.*/ 1260 *uuid_time = ((unsigned64)tp.tv_sec * 10000000) 1261 + ((unsigned64)tp.tv_usec * 10) 1262 + I64(0x01B21DD213814000); 1263 } 1265 /* Sample code, not for use in production; see RFC 1750 */ 1266 void get_random_info(char seed[16]) 1267 { 1268 MD5_CTX c; 1269 struct { 1270 struct sysinfo s; 1271 struct timeval t; 1272 char hostname[257]; 1273 } r; 1274 MD5Init(&c); 1275 sysinfo(&r.s); 1276 gettimeofday(&r.t, (struct timezone *)0); 1277 gethostname(r.hostname, 256); 1278 MD5Update(&c, &r, sizeof r); 1279 MD5Final(seed, &c); 1280 } 1282 #endif 1284 utest.c 1286 #include "copyrt.h" 1287 #include "sysdep.h" 1288 #include 1289 #include "uuid.h" 1291 uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ 1292 0x6ba7b810, 1293 0x9dad, 1294 0x11d1, 1295 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 1296 }; 1298 /* puid -- print a UUID */ 1299 void puid(uuid_t u) 1300 { 1301 int i; 1303 printf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", u.time_low, u.time_mid, 1304 u.time_hi_and_version, u.clock_seq_hi_and_reserved, 1305 u.clock_seq_low); 1306 for (i = 0; i < 6; i++) 1307 printf("%2.2x", u.node[i]); 1308 printf("\n"); 1309 } 1311 /* Simple driver for UUID generator */ 1312 void main(int argc, char **argv) 1313 { 1314 uuid_t u; 1315 int f; 1317 uuid_create(&u); 1318 printf("uuid_create(): "); puid(u); 1320 f = uuid_compare(&u, &u); 1321 printf("uuid_compare(u,u): %d\n", f); /* should be 0 */ 1322 f = uuid_compare(&u, &NameSpace_DNS); 1323 printf("uuid_compare(u, NameSpace_DNS): %d\n", f); /* s.b. 1 */ 1324 f = uuid_compare(&NameSpace_DNS, &u); 1325 printf("uuid_compare(NameSpace_DNS, u): %d\n", f); /* s.b. -1 */ 1326 uuid_create_md5_from_name(&u, NameSpace_DNS, "www.widgets.com", 15); 1327 printf("uuid_create_md5_from_name(): "); puid(u); 1328 } 1330 Appendix B. Appendix B - Sample output of utest 1332 uuid_create(): 7d444840-9dc0-11d1-b245-5ffdce74fad2 1333 uuid_compare(u,u): 0 1334 uuid_compare(u, NameSpace_DNS): 1 1335 uuid_compare(NameSpace_DNS, u): -1 1336 uuid_create_md5_from_name(): e902893a-9d22-3c7e-a7b8-d6e313b71d9f 1338 Appendix C. Appendix C - Some name space IDs 1340 This appendix lists the name space IDs for some potentially 1341 interesting name spaces, as initialized C structures and in the 1342 string representation defined above. 1344 /* Name string is a fully-qualified domain name */ 1345 uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ 1346 0x6ba7b810, 1347 0x9dad, 1348 0x11d1, 1349 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 1350 }; 1352 /* Name string is a URL */ 1353 uuid_t NameSpace_URL = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */ 1354 0x6ba7b811, 1355 0x9dad, 1356 0x11d1, 1357 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 1358 }; 1360 /* Name string is an ISO OID */ 1361 uuid_t NameSpace_OID = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */ 1362 0x6ba7b812, 1363 0x9dad, 1364 0x11d1, 1365 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 1366 }; 1368 /* Name string is an X.500 DN (in DER or a text output format) */ 1369 uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ 1370 0x6ba7b814, 1371 0x9dad, 1372 0x11d1, 1373 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 1374 }; 1376 Intellectual Property Statement 1378 The IETF takes no position regarding the validity or scope of any 1379 Intellectual Property Rights or other rights that might be claimed to 1380 pertain to the implementation or use of the technology described in 1381 this document or the extent to which any license under such rights 1382 might or might not be available; nor does it represent that it has 1383 made any independent effort to identify any such rights. Information 1384 on the procedures with respect to rights in RFC documents can be 1385 found in BCP 78 and BCP 79. 1387 Copies of IPR disclosures made to the IETF Secretariat and any 1388 assurances of licenses to be made available, or the result of an 1389 attempt made to obtain a general license or permission for the use of 1390 such proprietary rights by implementers or users of this 1391 specification can be obtained from the IETF on-line IPR repository at 1392 http://www.ietf.org/ipr. 1394 The IETF invites any interested party to bring to its attention any 1395 copyrights, patents or patent applications, or other proprietary 1396 rights that may cover technology that may be required to implement 1397 this standard. Please address the information to the IETF at 1398 ietf-ipr@ietf.org. 1400 Disclaimer of Validity 1402 This document and the information contained herein are provided on an 1403 "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS 1404 OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET 1405 ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, 1406 INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE 1407 INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED 1408 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 1410 Copyright Statement 1412 Copyright (C) The Internet Society (2004). This document is subject 1413 to the rights, licenses and restrictions contained in BCP 78, and 1414 except as set forth therein, the authors retain all their rights. 1416 Acknowledgment 1418 Funding for the RFC Editor function is currently provided by the 1419 Internet Society.