2010-02-03 61 views
30

我有一個問題產生一個GUID的字符串 - 例如:如何爲字符串生成GUID?

Guid g = New Guid("Mehar"); 

我如何可以計算"Mehar"一個GUID?我收到一個例外。

+0

你是什麼意思「爲字符串生成GUID」? – 2010-02-03 09:30:51

+0

你在做什麼Mehar? 'Guid(string)'接收一個guid格式的字符串,如'{00000000-0000-0000-0000-000000000000}' – 2010-02-03 09:31:31

+0

我的疑問是我需要爲一個普通字符串(Mehar)生成唯一的id,就像這樣「fc098275- 7af6-4780-9bee-624563ec5cb0「 – Mehar 2010-02-03 09:48:03

回答

-2

使用靜態NewGuid()方法創建的GUID,即Guid g = Guid.NewGuid();string s = Guid.NewGuid().ToString()'

+1

-1不是OP已經明確的意圖 – 2014-11-16 15:44:50

4

不能使用GUID的方式。 constructor of Guid需要Guid的有效字符串表示形式。

你在找什麼叫做哈希函數。 (例如:MD5

3

我想你對Guid實際上有什麼誤解。沒有像「Mehar」這樣的字符串的Guid表示。

有一個new Guid(String s)過載的原因是,您可以從一個典型的字符串表示形式(例如「00000000-0000-0000-0000-000000000000」)創建一個guid。

請參閱wiki文章以獲取關於Guid實際是什麼的更多信息。

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

+0

謝謝,我現在明白 – Mehar 2010-02-03 11:09:38

-1

GUID是隨機的,它們本質上並沒有分配給任何的字符串或其它值。

如果您需要這種鏈接,請將GUID存儲在字典中,並在創建新GUID之前先檢查現有的GUID。

+3

Guid's不是完全隨機的(或者甚至大部分是隨機的,IIRC)。它們遵循嚴格的格式,因此它們確實可以但全球唯一,不僅「可能」是唯一的:) – 2010-02-03 09:34:00

+2

-1:僅版本4 GUID是隨機的。實際上,版本3 GUID和版本5 GUID本質上分配給一個字符串。 – 2012-08-29 17:37:57

+0

@DavidCary描述的GUID版本在哪裏?你確定你沒有考慮UUID嗎? – Taemyr 2016-08-17 09:01:29

17

我相當肯定你已經把System.Guid與想要給定字符串的散列(比如說,SHA-256)混淆了。

請注意,在選擇密碼安全散列算法時,MD5,SHA0和SHA1全部爲generally considered dead。 SHA2及以上仍然可用。

+0

SHA2如何使用和SHA1不可用,如果根據您的鏈接,SHA2具有與SHA1相同的狀態「弱化」,僅在以後纔有效? – Ruslan 2015-01-12 10:55:46

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算法,所以我不認爲實現版本3和版本5 UUID應該太難了。

71

很老的主題,但是這是我們解決了這個問題:

由於的GUID從.NET框架是任意的16字節,或分別爲128位,您可以通過應用任何哈希函數從任意字符串計算的Guid該字符串生成一個16字節的散列並隨後將結果傳遞給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)

請注意,人們也可以使用產生較大的消化和簡單地截斷那些其它散列函數。因此使用更新的散列函數可能很明智。要列出一些:

  • SHA1
  • SHA-2
  • SHA-3

今天(2013年8月)的160bit的SHA1哈希值可以被認爲是一個不錯的選擇。

+14

如果你打算從MD5哈希數據中創建一個GUID,你應該遵循這個標準,*表示*這是一個[** Type 3 ** guid](http://en.wikipedia.org /wiki/Universally_unique_identifier#Version_3_.28MD5_hash.29) - 表示數據來自MD5散列。類型3 GUID的格式爲'xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx',其中**'3' **表示類型3,y被掩蓋爲'10xx'。您也可以使用SHA1散列(類型5),將3更改爲5. – 2013-04-18 15:05:28

+1

我會將Ian的註釋添加到答案中,以幫助您澄清不能將散列轉置爲GUID:GUID中的某些位需要特殊的價值。 – 2013-07-04 14:41:41

+1

我們在這裏談論GUID而不是UUID。注意不同之處。 – 2013-08-06 07:03:59

3

通常有幾種方法可以製作一個通用唯一的ID(UUID RFC 4122,又名GUID)。我們可以借用這四個在Python,並在C#中的東西一樣:

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

生成從主機ID,序列號,以及當前時間的UUID。 如果沒有給出節點,則使用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

2

如果運的意圖是從某種類型的字符串哈希創建一個UUID(GUID)(MD5,SHA-1,et.c.),我發現這個與這個偉大的回答非常類似的問題:

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

0

這是我自己的方法,我故意用字符串十六進制轉儲如果可能的話 - 在視覺上可以看出串至少有多大,如果需要 - 解碼用一些在線十六進制轉換器但是,如果字符串太長(超過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; 
}