How can I generate a GUID for a string?
生成字符串的GUID时出现问题-例如:
1 |
如何计算
这条线很旧,但这就是我们解决这个问题的方法:
由于.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哈希可以被认为是一个不错的选择。
我敢肯定你把
注意,在选择加密安全哈希算法时,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制作类似的东西:
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.
Generate a UUID based on the MD5 hash of a namespace identifier (which is a UUID) and a name (which is a string).
Generate a random UUID.
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使用
维基百科上描述的这些变体和版本都是独一无二的
不能这样使用guid。guid的构造函数需要guid的有效字符串表示形式。
你要找的是一个散列函数。(例如:MD5)
我认为你对guid实际上是什么有误解。没有字符串的guid表示形式,如"mehar"。
出现
有关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。