aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/ExtensibilityServices/Uuid.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/ExtensibilityServices/Uuid.cs')
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/Uuid.cs82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/WixToolset.Core/ExtensibilityServices/Uuid.cs b/src/WixToolset.Core/ExtensibilityServices/Uuid.cs
new file mode 100644
index 00000000..a5692b71
--- /dev/null
+++ b/src/WixToolset.Core/ExtensibilityServices/Uuid.cs
@@ -0,0 +1,82 @@
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
3namespace WixToolset.Core.ExtensibilityServices
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 static class Uuid
14 {
15 /// <summary>
16 /// Creates a version 3 name-based UUID.
17 /// </summary>
18 /// <param name="namespaceGuid">The namespace UUID.</param>
19 /// <param name="value">The value.</param>
20 /// <param name="backwardsCompatible">Flag to say to use MD5 instead of better SHA1.</param>
21 /// <returns>The UUID for the given namespace and value.</returns>
22 public static Guid NewUuid(Guid namespaceGuid, string value)
23 {
24 byte[] namespaceBytes = namespaceGuid.ToByteArray();
25 short uuidVersion = (short)0x5000;
26
27 // get the fields of the guid which are in host byte ordering
28 int timeLow = BitConverter.ToInt32(namespaceBytes, 0);
29 short timeMid = BitConverter.ToInt16(namespaceBytes, 4);
30 short timeHiAndVersion = BitConverter.ToInt16(namespaceBytes, 6);
31
32 // convert to network byte ordering
33 timeLow = IPAddress.HostToNetworkOrder(timeLow);
34 timeMid = IPAddress.HostToNetworkOrder(timeMid);
35 timeHiAndVersion = IPAddress.HostToNetworkOrder(timeHiAndVersion);
36
37 // get the bytes from the value
38 byte[] valueBytes = Encoding.Unicode.GetBytes(value);
39
40 // fill-in the hash input buffer
41 byte[] buffer = new byte[namespaceBytes.Length + valueBytes.Length];
42 Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, buffer, 0, 4);
43 Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, buffer, 4, 2);
44 Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, buffer, 6, 2);
45 Buffer.BlockCopy(namespaceBytes, 8, buffer, 8, 8);
46 Buffer.BlockCopy(valueBytes, 0, buffer, 16, valueBytes.Length);
47
48 // perform the appropriate hash of the namespace and value
49 byte[] hash;
50 using (SHA1 sha1 = SHA1.Create())
51 {
52 hash = sha1.ComputeHash(buffer);
53 }
54
55 // get the fields of the hash which are in network byte ordering
56 timeLow = BitConverter.ToInt32(hash, 0);
57 timeMid = BitConverter.ToInt16(hash, 4);
58 timeHiAndVersion = BitConverter.ToInt16(hash, 6);
59
60 // convert to network byte ordering
61 timeLow = IPAddress.NetworkToHostOrder(timeLow);
62 timeMid = IPAddress.NetworkToHostOrder(timeMid);
63 timeHiAndVersion = IPAddress.NetworkToHostOrder(timeHiAndVersion);
64
65 // set the version and variant bits
66 timeHiAndVersion &= 0x0FFF;
67 timeHiAndVersion += uuidVersion;
68 hash[8] &= 0x3F;
69 hash[8] |= 0x80;
70
71 // put back the converted values into a 128-bit value
72 byte[] guidBits = new byte[16];
73 Buffer.BlockCopy(hash, 0, guidBits, 0, 16);
74
75 Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, guidBits, 0, 4);
76 Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, guidBits, 4, 2);
77 Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, guidBits, 6, 2);
78
79 return new Guid(guidBits);
80 }
81 }
82}