我在为字符串生成GUID时遇到问题 - 例如:
Guid g = New Guid("Mehar");
如何计算"Mehar"
的GUID?我正在例外。
答案 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位摘要的最流行的哈希函数列表:
请注意,也可以使用其他散列函数来生成更大的摘要,并简单地截断它们。因此,使用更新的散列函数可能是明智的。列出一些:
今天(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
生成一次,然后将其用作uuid3
或uuid5
的命名空间。
答案 5 :(得分:3)
我认为你对Guid究竟是什么有误解。没有像“Mehar”这样的字符串的Guid表示。
存在new Guid(String s)
重载的原因是您可以从典型的字符串表示形式创建一个guid,例如“00000000-0000-0000-0000-000000000000”。
有关Guid实际上是什么的更多信息,请参阅wiki文章。
答案 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。