关于c#:如何为字符串生成GUID?


How can I generate a GUID for a string?

生成字符串的GUID时出现问题-例如:

1
Guid g = New Guid("Mehar");

如何计算"Mehar"的guid?我有个例外。


这条线很旧,但这就是我们解决这个问题的方法:

由于.NET框架中的guid是任意的16字节,或者分别是128位,您可以通过将任何哈希函数应用于生成16字节哈希的字符串,然后将结果传递给guid构造函数来计算任意字符串中的guid。

我们决定使用MD5哈希函数,示例代码如下:

1
2
3
4
5
6
string input ="asdfasdf";
using (MD5 md5 = MD5.Create())
{
    byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(input));
    Guid result = new Guid(hash);
}

请注意,此guid生成本身存在一些缺陷,因为它取决于哈希函数的质量!如果散列函数为您使用的许多字符串生成相等的散列,它将影响您的软件的行为。

下面列出了最流行的哈希函数,这些函数生成的摘要为128位:

  • ripemd(碰撞概率:2^18)
  • MD4(碰撞概率:肯定)
  • MD5(碰撞概率:2^20.96)

请注意,还可以使用其他产生更大摘要并简单地截断这些摘要的哈希函数。因此,使用新的哈希函数可能是明智的。列出一些:

  • SHA-1
  • 沙二号
  • 沙-3

今天(2013年8月),160位sha1哈希可以被认为是一个不错的选择。


我敢肯定你把System.Guid和想要给定字符串的散列(比如sha-256)混淆了。

注意,在选择加密安全哈希算法时,MD5、SHA0和SHA1通常都被认为是死的。Sha2和更高版本仍然可用。


您要查找的可能是生成版本3或版本5的UUID,它们是基于名称的UUID。(建议使用版本5)。我认为.NET框架没有内置的支持。参见http://en.wikipedia.org/wiki/universally_unique_identifier

我在谷歌上搜索了几次,看看是否能在win32 api中找到一些东西,但什么也没找到。但是,我确信.NET框架在某个地方隐藏了一些实现,因为据我所知,在.NET中生成COM对象时,如果不提供显式的GUID,.NET框架将生成基于名称的UUID以创建定义良好的ClassID和InterfaceID,即每次重新编译时都不会更改的UUID(如VB6)。但这可能是隐藏的,所以我想您需要自己实现算法。幸运的是,.NET同时提供了MD5和SHA1算法,所以我认为实现版本3和版本5 UUID不会太困难。


一般来说,有几种方法可以生成一个通用唯一的ID(UUID RFC 4122,A.K.A.GUID)。我们可以从python中借用这四个,并用c制作类似的东西:

uuid.uuid1([node[, clock_seq]])

Generate a UUID from a host ID, sequence number, and the current time.
If node is not given, getnode() is used to obtain the hardware
address. If clock_seq is given, it is used as the sequence number;
otherwise a random 14-bit sequence number is chosen.

uuid.uuid3(namespace, name)

Generate a UUID based on the MD5 hash of a namespace identifier (which is a UUID) and a name (which is a string).

uuid.uuid4()

Generate a random UUID.

uuid.uuid5(namespace, name)

Generate a UUID based on the SHA-1 hash of a namespace identifier (which is a UUID) and a name (which is a string).

因此,如果您需要字符串的ID作为对象,而不是值的ID,那么应该使用给定的字符串管理您的私有UUID,您的私有UUID使用uuid1生成一次,然后将其用作uuid3uuid5的命名空间。

维基百科上描述的这些变体和版本都是独一无二的


不能这样使用guid。guid的构造函数需要guid的有效字符串表示形式。

你要找的是一个散列函数。(例如:MD5)


我认为你对guid实际上是什么有误解。没有字符串的guid表示形式,如"mehar"。

出现new Guid(String s)重载的原因是,您可以从一个典型的字符串表示形式(如"00000000-0000-0000-0000-00000000000")创建一个guid。

有关guid实际是什么的详细信息,请参阅wiki文章。

http://en.wikipedia.org/wiki/globall_unique_标识符


如果op的目的是从某种类型的字符串散列(md5,sha-1,et.c.)创建一个uuid(guid),我发现这个问题非常相似,答案非常好:

https://stackoverflow.com/a/5657517/430885

它有一个链接,指向基于RFC 4122第4.3节的Github代码段,该代码段将从字符串和名称空间创建一个guid(您可以自己选择,以确保避免来自外部环境的冲突)。

直接链接到代码段:https://github.com/logosbible/logos.utility/blob/master/src/logos.utility/guidutility.cs


这里是我自己的方法,如果可能的话,我有意使用字符串到十六进制转储-从视觉上看,至少可以看出字符串有多大,如果需要的话,可以使用一些在线十六进制转换器进行解码。但如果字符串太长(超过16个字节),则使用sha-1计算哈希并从中生成guid。

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
/// <summary>
/// Generates Guid based on String. Key assumption for this algorithm is that name is unique (across where it it's being used)
/// and if name byte length is less than 16 - it will be fetched directly into guid, if over 16 bytes - then we compute sha-1
/// hash from string and then pass it to guid.
/// </summary>
/// <param name="name">Unique name which is unique across where this guid will be used.</param>
/// <returns>For example"{706C7567-696E-7300-0000-000000000000}" for"plugins"</returns>
static public String GenerateGuid(String name)
{
    byte[] buf = Encoding.UTF8.GetBytes(name);
    byte[] guid = new byte[16];
    if (buf.Length < 16)
    {
        Array.Copy(buf, guid, buf.Length);
    }
    else
    {
        using (SHA1 sha1 = SHA1.Create())
        {
            byte[] hash = sha1.ComputeHash(buf);
            // Hash is 20 bytes, but we need 16. We loose some of"uniqueness", but I doubt it will be fatal
            Array.Copy(hash, guid, 16);
        }
    }

    // Don't use Guid constructor, it tends to swap bytes. We want to preserve original string as hex dump.
    String guidS ="{" + String.Format("{0:X2}{1:X2}{2:X2}{3:X2}-{4:X2}{5:X2}-{6:X2}{7:X2}-{8:X2}{9:X2}-{10:X2}{11:X2}{12:X2}{13:X2}{14:X2}{15:X2}",
        guid[0], guid[1], guid[2], guid[3], guid[4], guid[5], guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]) +"}";

    return guidS;
}

guid是随机的,它们本质上不分配给任何字符串或其他值。

如果需要这样的链接,请将guid存储在字典中,并在创建新的guid之前先检查现有的guid。