diff options
Diffstat (limited to 'src/WixToolset.Core/Uuid.cs')
-rw-r--r-- | src/WixToolset.Core/Uuid.cs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Uuid.cs b/src/WixToolset.Core/Uuid.cs new file mode 100644 index 00000000..2e599793 --- /dev/null +++ b/src/WixToolset.Core/Uuid.cs | |||
@@ -0,0 +1,89 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset | ||
4 | { | ||
5 | using System; | ||
6 | using System.Net; | ||
7 | using System.Security.Cryptography; | ||
8 | using System.Text; | ||
9 | |||
10 | /// <summary> | ||
11 | /// Implementation of RFC 4122 - A Universally Unique Identifier (UUID) URN Namespace. | ||
12 | /// </summary> | ||
13 | internal sealed class Uuid | ||
14 | { | ||
15 | /// <summary> | ||
16 | /// Protect the constructor. | ||
17 | /// </summary> | ||
18 | private Uuid() | ||
19 | { | ||
20 | } | ||
21 | |||
22 | /// <summary> | ||
23 | /// Creates a version 3 name-based UUID. | ||
24 | /// </summary> | ||
25 | /// <param name="namespaceGuid">The namespace UUID.</param> | ||
26 | /// <param name="value">The value.</param> | ||
27 | /// <param name="backwardsCompatible">Flag to say to use MD5 instead of better SHA1.</param> | ||
28 | /// <returns>The UUID for the given namespace and value.</returns> | ||
29 | public static Guid NewUuid(Guid namespaceGuid, string value) | ||
30 | { | ||
31 | byte[] namespaceBytes = namespaceGuid.ToByteArray(); | ||
32 | short uuidVersion = (short)0x5000; | ||
33 | |||
34 | // get the fields of the guid which are in host byte ordering | ||
35 | int timeLow = BitConverter.ToInt32(namespaceBytes, 0); | ||
36 | short timeMid = BitConverter.ToInt16(namespaceBytes, 4); | ||
37 | short timeHiAndVersion = BitConverter.ToInt16(namespaceBytes, 6); | ||
38 | |||
39 | // convert to network byte ordering | ||
40 | timeLow = IPAddress.HostToNetworkOrder(timeLow); | ||
41 | timeMid = IPAddress.HostToNetworkOrder(timeMid); | ||
42 | timeHiAndVersion = IPAddress.HostToNetworkOrder(timeHiAndVersion); | ||
43 | |||
44 | // get the bytes from the value | ||
45 | byte[] valueBytes = Encoding.Unicode.GetBytes(value); | ||
46 | |||
47 | // fill-in the hash input buffer | ||
48 | byte[] buffer = new byte[namespaceBytes.Length + valueBytes.Length]; | ||
49 | Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, buffer, 0, 4); | ||
50 | Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, buffer, 4, 2); | ||
51 | Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, buffer, 6, 2); | ||
52 | Buffer.BlockCopy(namespaceBytes, 8, buffer, 8, 8); | ||
53 | Buffer.BlockCopy(valueBytes, 0, buffer, 16, valueBytes.Length); | ||
54 | |||
55 | // perform the appropriate hash of the namespace and value | ||
56 | byte[] hash; | ||
57 | using (SHA1 sha1 = SHA1.Create()) | ||
58 | { | ||
59 | hash = sha1.ComputeHash(buffer); | ||
60 | } | ||
61 | |||
62 | // get the fields of the hash which are in network byte ordering | ||
63 | timeLow = BitConverter.ToInt32(hash, 0); | ||
64 | timeMid = BitConverter.ToInt16(hash, 4); | ||
65 | timeHiAndVersion = BitConverter.ToInt16(hash, 6); | ||
66 | |||
67 | // convert to network byte ordering | ||
68 | timeLow = IPAddress.NetworkToHostOrder(timeLow); | ||
69 | timeMid = IPAddress.NetworkToHostOrder(timeMid); | ||
70 | timeHiAndVersion = IPAddress.NetworkToHostOrder(timeHiAndVersion); | ||
71 | |||
72 | // set the version and variant bits | ||
73 | timeHiAndVersion &= 0x0FFF; | ||
74 | timeHiAndVersion += uuidVersion; | ||
75 | hash[8] &= 0x3F; | ||
76 | hash[8] |= 0x80; | ||
77 | |||
78 | // put back the converted values into a 128-bit value | ||
79 | byte[] guidBits = new byte[16]; | ||
80 | Buffer.BlockCopy(hash, 0, guidBits, 0, 16); | ||
81 | |||
82 | Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, guidBits, 0, 4); | ||
83 | Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, guidBits, 4, 2); | ||
84 | Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, guidBits, 6, 2); | ||
85 | |||
86 | return new Guid(guidBits); | ||
87 | } | ||
88 | } | ||
89 | } | ||