如何为字符串生成GUID?

时间:2010-02-03 09:27:51

标签: c#

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

Guid g = New Guid("Mehar");

如何计算"Mehar"的GUID?我正在例外。

9 个答案:

答案 0 :(得分:96)

相当古老的这个帖子,但这就是我们解决这个问题的方法:

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

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

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
  • SHA-2
  • SHA-3

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

答案 1 :(得分:18)

我很确定你让System.Guid想要一个给定字符串的哈希值(比如SHA-256)。

请注意,在选择加密安全散列算法时,MD5,SHA0和SHA1都是generally considered dead。 SHA2及以上版本仍可使用。

答案 2 :(得分:5)

您正在寻找的可能是生成版本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算法,所以我不认为实现version3和version5 UUID应该太困难。

答案 3 :(得分:4)

您不能以这种方式使用GUID。 constructor of Guid期望Guid的有效字符串表示。

您正在寻找的是一种哈希函数。 (例如:MD5

答案 4 :(得分:4)

通常,制作通用唯一ID(UUID RFC 4122,a.k.a。GUID)的方法很少。我们可以从Python中借用这四个,并在C#中使用类似的东西:

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

  

从主机ID,序列号和当前时间生成UUID。   如果未给出node,则使用getnode()来获取硬件   地址。如果给出clock_seq,则将其用作序列号;   否则选择随机的14位序列号。

uuid.uuid3(namespace, name)

  

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

uuid.uuid4()

  

生成随机UUID。

uuid.uuid5(namespace, name)

  

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

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

维基百科Universally_unique_identifier#Variants_and_versions

中描述的这些变体和版本

答案 5 :(得分:3)

我认为你对Guid究竟是什么有误解。没有像“Mehar”这样的字符串的Guid表示。

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

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

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

答案 6 :(得分:2)

如果op的意图是从某种字符串哈希(MD5,SHA-1,et.c。)创建一个UUID(Guid),我发现这个非常相似的问题有这个很好的答案:

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

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

指向代码段的直接链接:https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

答案 7 :(得分:0)

这是我自己的方法,如果可能的话,我有意使用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;
}

答案 8 :(得分:-1)

Guids是随机的,它们本身并不分配给任何字符串或其他值。

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