1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
// 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.
namespace WixToolset
{
using System;
using System.Net;
using System.Security.Cryptography;
using System.Text;
/// <summary>
/// Implementation of RFC 4122 - A Universally Unique Identifier (UUID) URN Namespace.
/// </summary>
public static class Uuid
{
/// <summary>
/// Creates a version 3 name-based UUID.
/// </summary>
/// <param name="namespaceGuid">The namespace UUID.</param>
/// <param name="value">The value.</param>
/// <param name="backwardsCompatible">Flag to say to use MD5 instead of better SHA1.</param>
/// <returns>The UUID for the given namespace and value.</returns>
public static Guid NewUuid(Guid namespaceGuid, string value)
{
byte[] namespaceBytes = namespaceGuid.ToByteArray();
short uuidVersion = (short)0x5000;
// get the fields of the guid which are in host byte ordering
int timeLow = BitConverter.ToInt32(namespaceBytes, 0);
short timeMid = BitConverter.ToInt16(namespaceBytes, 4);
short timeHiAndVersion = BitConverter.ToInt16(namespaceBytes, 6);
// convert to network byte ordering
timeLow = IPAddress.HostToNetworkOrder(timeLow);
timeMid = IPAddress.HostToNetworkOrder(timeMid);
timeHiAndVersion = IPAddress.HostToNetworkOrder(timeHiAndVersion);
// get the bytes from the value
byte[] valueBytes = Encoding.Unicode.GetBytes(value);
// fill-in the hash input buffer
byte[] buffer = new byte[namespaceBytes.Length + valueBytes.Length];
Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, buffer, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, buffer, 4, 2);
Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, buffer, 6, 2);
Buffer.BlockCopy(namespaceBytes, 8, buffer, 8, 8);
Buffer.BlockCopy(valueBytes, 0, buffer, 16, valueBytes.Length);
// perform the appropriate hash of the namespace and value
byte[] hash;
using (SHA1 sha1 = SHA1.Create())
{
hash = sha1.ComputeHash(buffer);
}
// get the fields of the hash which are in network byte ordering
timeLow = BitConverter.ToInt32(hash, 0);
timeMid = BitConverter.ToInt16(hash, 4);
timeHiAndVersion = BitConverter.ToInt16(hash, 6);
// convert to network byte ordering
timeLow = IPAddress.NetworkToHostOrder(timeLow);
timeMid = IPAddress.NetworkToHostOrder(timeMid);
timeHiAndVersion = IPAddress.NetworkToHostOrder(timeHiAndVersion);
// set the version and variant bits
timeHiAndVersion &= 0x0FFF;
timeHiAndVersion += uuidVersion;
hash[8] &= 0x3F;
hash[8] |= 0x80;
// put back the converted values into a 128-bit value
byte[] guidBits = new byte[16];
Buffer.BlockCopy(hash, 0, guidBits, 0, 16);
Buffer.BlockCopy(BitConverter.GetBytes(timeLow), 0, guidBits, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(timeMid), 0, guidBits, 4, 2);
Buffer.BlockCopy(BitConverter.GetBytes(timeHiAndVersion), 0, guidBits, 6, 2);
return new Guid(guidBits);
}
}
}
|