C# 如何为字符串生成 GUID?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2190890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:15:33  来源:igfitidea点击:

How can I generate a GUID for a string?

c#

提问by Mehar

I am having a problem generating a GUID for a string - for example:

我在为字符串生成 GUID 时遇到问题 - 例如:

Guid g = New Guid("Mehar");

How can I compute a GUID for "Mehar"? I am getting an exception.

如何计算 GUID "Mehar"?我得到了一个例外。

回答by Kobi

You cannot use GUID that way. The constructor of Guidexpects a valid, string representation of a Guid.

您不能那样使用 GUID。Guid构造函数需要一个Guid的有效字符串表示。

What you're looking for is called a Hash function. (for example: MD5)

您正在寻找的称为哈希函数。(例如:MD5

回答by Robin Day

I think you have a misunderstanding of what a Guid actually is. There is no Guid representation of a string such as "Mehar".

我认为您对 Guid 的实际含义有误解。没有诸如“Mehar”之类的字符串的 Guid 表示。

The reason there is a new Guid(String s)overload is so that you can create a guid from a typical string representation of one, such as "00000000-0000-0000-0000-000000000000".

存在new Guid(String s)重载的原因是您可以从一个典型的字符串表示形式创建一个 guid,例如“00000000-0000-0000-0000-000000000000”。

See the wiki article for more information on what a Guid actually is.

有关 Guid 实际上是什么的更多信息,请参阅 wiki 文章。

http://en.wikipedia.org/wiki/Globally_Unique_Identifier

http://en.wikipedia.org/wiki/Globally_Unique_Identifier

回答by Skrim

Guids are random, they are not intrinsically assigned to any string or other value.

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

If you need such linking, store the guids in a Dictionary and check for an existing guid first before creating a new one.

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

回答by Noon Silk

I'm fairly sure you've confused System.Guidwith wanting a hash (say, SHA-256) of a given string.

我很确定您对System.Guid想要给定字符串的哈希值(例如SHA-256)感到困惑。

Note that, when selecting a cryptographically-secure hashing algorithm, MD5, SHA0 and SHA1 are all generally considered dead. SHA2 and up are still usable.

请注意,在选择加密安全的散列算法时,MD5、SHA0 和 SHA1 通常都被认为是无效的。SHA2 及更高版本仍然可用。

回答by Pete

What you are looking for is probably generating version 3 or version 5 UUIDs, which are name based UUIDs. (version 5 is the recommended). I don't think that the .NET framework has build in support for it. See http://en.wikipedia.org/wiki/Universally_Unique_Identifier

您正在寻找的可能是生成版本 3 或版本 5 UUID,它们是基于名称的 UUID。(推荐使用第 5 版)。我认为 .NET 框架没有内置支持它。请参阅http://en.wikipedia.org/wiki/Universally_Unique_Identifier

I did a few google searches to see if I could find something in the Win32 API, but nothing came up. However, I am sure that the .NET framework has some implementation hidden somewhere, because as far as I know, when generating a COM object in .NET, and you don't supply an explicit GUID, then the .NET framework generates a name based UUID to create a well-defined ClassID and InterfaceID, i.e. UUIDs that don't change every time you recompile (like VB6). But this is probably hidden, so I guess you need to implement the algorithm yourself. Luckily, .NET provides both an MD5 and SHA1 algorithm so I don't think implementing a version3 and version5 UUID should be too difficult.

我做了一些谷歌搜索,看看我是否能在 Win32 API 中找到一些东西,但什么也没有出现。但是,我确信 .NET 框架在某处隐藏了一些实现,因为据我所知,在 .NET 中生成 COM 对象时,并且您没有提供显式 GUID,那么 .NET 框架会生成一个名称基于 UUID 来创建定义良好的 ClassID 和 InterfaceID,即每次重新编译时都不会更改的 UUID(如 VB6)。但这可能是隐藏的,所以我猜你需要自己实现算法。幸运的是,.NET 提供了 MD5 和 SHA1 算法,所以我认为实现 version3 和 version5 UUID 应该不会太困难。

回答by Nachbars Lumpi

Quite old this thread but this is how we solved this problem:

这个线程很老了,但这就是我们解决这个问题的方法:

Since Guid's from the .NET framework are arbitrary 16bytes, or respectively 128bits, you can calculate a Guid from arbitrary strings by applying any hash function to the string that generates a 16 byte hash and subsequently pass the result into the Guid constructor.

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

We decided to use the MD5 hash function and an example code could look like this:

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

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

Please note that this Guid generation has a few flaws by itself as it depends on the quality of the hash function!If your hash function generates equal hashes for lots of string you use, it's going to impact the behaviour of your software.

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

Here is a list of the most popular hash functions that produce a digest of 128bit:

以下是生成 128 位摘要的最流行的哈希函数列表:

  • RIPEMD (probability of collision: 2^18)
  • MD4 (probability of collision: for sure)
  • MD5 (probability of collision: 2^20.96)
  • RIPEMD(碰撞概率:2^18)
  • MD4(碰撞概率:肯定)
  • MD5(碰撞概率:2^20.96)

Please note that one can use also other hash functions that produce larger digests and simply truncate those. Therefore it may be smart to use a newer hash function. To list some:

请注意,您还可以使用其他散列函数来生成更大的摘要并简单地截断它们。因此,使用较新的哈希函数可能是明智之举。列出一些:

  • SHA-1
  • SHA-2
  • SHA-3
  • SHA-1
  • SHA-2
  • SHA-3

Today (Aug 2013) the 160bit SHA1 hash can be considered being a good choice.

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

回答by user2622016

In general there are few ways to make an universally unique ID (UUID RFC 4122, a.k.a. GUID). We could borrow these four from Python, and make in C# something alike:

一般来说,有几种方法可以制作通用唯一 ID(UUID RFC 4122,又名 GUID)。我们可以从 Python 借用这四个,并在 C# 中制作类似的东西:

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

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.

根据主机 ID、序列号和当前时间生成 UUID。如果没有给出节点,则使用 getnode() 获取硬件地址。如果给出clock_seq,则用作序列号;否则选择一个随机的 14 位序列号。

uuid.uuid3(namespace, name)

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)和名称(字符串)的 MD5 哈希生成 UUID。

uuid.uuid4()

uuid.uuid4()

Generate a random UUID.

生成随机 UUID。

uuid.uuid5(namespace, name)

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).

根据名称空间标识符(UUID)和名称(字符串)的 SHA-1 哈希生成 UUID。

So if you need ID of a string as an object, not ID of a value, you should mangle your private UUID with given string, Your private UUID generate once using uuid1, and then use it as namespace for uuid3or uuid5.

因此,如果您需要字符串的 ID 作为对象,而不是值的 ID,您应该使用给定的字符串修改您的私有 UUID,您的私有 UUID 生成一次使用uuid1,然后将其用作uuid3或的命名空间uuid5

These variants and versions described on Wikipedia Universally_unique_identifier#Variants_and_versions

维基百科上描述的这些变体和版本Universally_unique_identifier#Variants_and_versions

回答by Frederik Struck-Sch?ning

If op's intent is to create a UUID (Guid) from a string hash of some sort (MD5, SHA-1, et.c.), I found this very similar question with this great answer:

如果 op 的意图是从某种类型的字符串哈希(MD5、SHA-1 等)创建 UUID(Guid),我发现这个非常相似的问题与这个很好的答案:

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

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

It has a link to a github-snippet based on RFC 4122 §4.3, that will create a Guid from a string and a namespace (which you can choose for yourself to guarantee against collisions from outside environments).

它有一个指向基于 RFC 4122 §4.3 的 github-snippet 的链接,它将从一个字符串和一个命名空间(您可以自己选择以保证免受来自外部环境的冲突)创建一个 Guid。

Direct link to the snippet: https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

片段的直接链接:https: //github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

回答by TarmoPikaro

Here is my own approach, I'm intentionally using String to hex dump if possible - visually it can be seen at least how big string is, and if needed - decoded using some online hex converter. But if string is too long (more than 16 bytes) - then using sha-1 to compute hash and generate guid from it.

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

/// <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;
}