main
cs 81 lines 3.46 KB
Raw
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.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 /// <returns>The UUID for the given namespace and value.</returns>
21 public static Guid NewUuid(Guid namespaceGuid, string value)
22 {
23 byte[] namespaceBytes = namespaceGuid.ToByteArray();
24 short uuidVersion = (short)0x5000;
25
26 // get the fields of the guid which are in host byte ordering
27 int timeLow = BitConverter.ToInt32(namespaceBytes, 0);
28 short timeMid = BitConverter.ToInt16(namespaceBytes, 4);
29 short timeHiAndVersion = BitConverter.ToInt16(namespaceBytes, 6);
30
31 // convert to network byte ordering
32 timeLow = IPAddress.HostToNetworkOrder(timeLow);
33 timeMid = IPAddress.HostToNetworkOrder(timeMid);
34 timeHiAndVersion = IPAddress.HostToNetworkOrder(timeHiAndVersion);
35
36 // get the bytes from the value
37 byte[] valueBytes = Encoding.Unicode.GetBytes(value);
38
39 // fill-in the hash input buffer
40 byte[] buffer = new byte[namespaceBytes.Length + valueBytes.Length];
41 Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, buffer, 0, 4);
42 Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, buffer, 4, 2);
43 Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, buffer, 6, 2);
44 Buffer.BlockCopy(namespaceBytes, 8, buffer, 8, 8);
45 Buffer.BlockCopy(valueBytes, 0, buffer, 16, valueBytes.Length);
46
47 // perform the appropriate hash of the namespace and value
48 byte[] hash;
49 using (SHA1 sha1 = SHA1.Create())
50 {
51 hash = sha1.ComputeHash(buffer);
52 }
53
54 // get the fields of the hash which are in network byte ordering
55 timeLow = BitConverter.ToInt32(hash, 0);
56 timeMid = BitConverter.ToInt16(hash, 4);
57 timeHiAndVersion = BitConverter.ToInt16(hash, 6);
58
59 // convert to network byte ordering
60 timeLow = IPAddress.NetworkToHostOrder(timeLow);
61 timeMid = IPAddress.NetworkToHostOrder(timeMid);
62 timeHiAndVersion = IPAddress.NetworkToHostOrder(timeHiAndVersion);
63
64 // set the version and variant bits
65 timeHiAndVersion &= 0x0FFF;
66 timeHiAndVersion += uuidVersion;
67 hash[8] &= 0x3F;
68 hash[8] |= 0x80;
69
70 // put back the converted values into a 128-bit value
71 byte[] guidBits = new byte[16];
72 Buffer.BlockCopy(hash, 0, guidBits, 0, 16);
73
74 Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, guidBits, 0, 4);
75 Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, guidBits, 4, 2);
76 Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, guidBits, 6, 2);
77
78 return new Guid(guidBits);
79 }
80 }
81 }