2010-02-03 41 views
30

Tôi gặp một vấn đề tạo ra một GUID cho một chuỗi - ví dụ:Làm cách nào để tạo GUID cho chuỗi?

Guid g = New Guid("Mehar"); 

Làm thế nào tôi có thể tính toán một GUID cho "Mehar"? Tôi nhận được một ngoại lệ.

+0

Ý bạn là gì bằng cách "tạo GUID cho chuỗi"? –

+0

Bạn đang cố gắng làm gì Mehar? 'Guid (string)' nhận được một chuỗi định dạng guid, như '{00000000-0000-0000-0000-000000000000}' –

+0

nghi ngờ của tôi là tôi cần tạo id duy nhất cho một chuỗi chung (Mehar) giống như thế này "fc098275- 7af6-4780-9bee-624563ec5cb0 " – Mehar

Trả lời

-2

Bạn sử dụng phương pháp tĩnh NewGuid() để tạo Guids, I.E., Guid g = Guid.NewGuid(); hoặc string s = Guid.NewGuid().ToString()'

+1

-1 Không phải những gì OP đã làm rõ được dự định –

4

Bạn không thể sử dụng GUID như vậy. constructor of Guid mong đợi một biểu diễn chuỗi hợp lệ của Hướng dẫn.

Điều bạn đang tìm kiếm được gọi là hàm băm. (ví dụ: MD5)

3

Tôi nghĩ rằng bạn hiểu sai về một hướng dẫn thực sự là gì. Không có đại diện Guid của một chuỗi như "Mehar".

Lý do có quá tải là new Guid(String s) để bạn có thể tạo một guid từ một chuỗi đại diện điển hình của một, chẳng hạn như "00000000-0000-0000-0000-000000000000".

Xem bài viết wiki để biết thêm thông tin về những gì một Guid thực sự là.

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

+0

Cảm ơn bạn tôi hiểu ngay bây giờ – Mehar

-1

Guids là ngẫu nhiên, họ không được về bản chất được gán cho bất kỳ chuỗi hoặc giá trị khác.

Nếu bạn cần liên kết như vậy, hãy lưu trữ các tài liệu trong một từ điển và kiểm tra hướng dẫn hiện tại trước khi tạo một tài liệu mới.

+3

Hướng dẫn không hoàn toàn ngẫu nhiên (hoặc thậm chí chủ yếu là ngẫu nhiên, IIRC). Họ tuân theo một định dạng nghiêm ngặt để họ có thể, thực sự, nhưng độc đáo trên toàn cầu, không chỉ là "có thể" duy nhất :) –

+2

-1: Chỉ có phiên bản GUID 4 là ngẫu nhiên. Phiên bản 3 GUIDs và GUIDs phiên bản 5, trên thực tế, về bản chất được gán cho một chuỗi. –

+0

@DavidCary Các phiên bản GUID được mô tả ở đâu? Bạn có chắc bạn không nghĩ về UUID? – Taemyr

17

Tôi khá chắc chắn bạn đã nhầm lẫn System.Guid khi muốn có hàm băm (ví dụ: SHA-256) của một chuỗi nhất định.

Lưu ý rằng, khi chọn thuật toán băm mật mã an toàn, MD5, SHA0 và SHA1 là tất cả generally considered dead. SHA2 trở lên vẫn có thể sử dụng được.

+0

Làm thế nào là SHA2 có thể sử dụng và SHA1 không, nếu, theo liên kết của bạn, SHA2 có cùng trạng thái "yếu" như SHA1, chỉ sau một ngày? – Ruslan

5

Điều bạn đang tìm kiếm có lẽ là tạo UUID phiên bản 3 hoặc phiên bản 5, là UUID dựa trên tên. (phiên bản 5 là khuyến cáo). Tôi không nghĩ rằng các.NET framework đã xây dựng trong hỗ trợ cho nó. Xem http://en.wikipedia.org/wiki/Universally_Unique_Identifier

Tôi đã thực hiện một vài tìm kiếm trên google để xem liệu tôi có thể tìm thấy thứ gì đó trong API Win32 hay không, nhưng không có gì xuất hiện. Tuy nhiên, tôi chắc chắn rằng khuôn khổ .NET có một số thực hiện ẩn ở đâu đó, bởi vì theo như tôi biết, khi tạo một đối tượng COM trong .NET, và bạn không cung cấp một GUID rõ ràng, thì khung công tác .NET tạo ra một tên dựa UUID để tạo ra một ClassID và InterfaceID được xác định rõ ràng, tức là UUID không thay đổi mỗi khi bạn biên dịch lại (như VB6). Nhưng điều này có lẽ là ẩn, vì vậy tôi đoán bạn cần phải thực hiện các thuật toán chính mình. May mắn thay, .NET cung cấp cả một thuật toán MD5 và SHA1 vì vậy tôi không nghĩ việc triển khai UUID phiên bản 3 và version5 quá khó.

71

Khá cũ chủ đề này nhưng đây là cách chúng tôi giải quyết vấn đề này:

Kể từ Guid từ NET framework là 16bytes tùy ý, hoặc tương ứng 128bits, bạn có thể tính toán một Guid từ chuỗi tùy ý bằng cách áp dụng bất kỳ hàm băm để chuỗi tạo ra băm 16 byte và sau đó chuyển kết quả vào hàm tạo Guid.

Chúng tôi quyết định để sử dụng chức năng MD5 băm và một mã số ví dụ có thể trông như thế này:

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

Xin lưu ý rằng hệ Guid này có một vài sai sót của chính nó như là nó phụ thuộc vào chất lượng của các hash chức năng! Nếu hàm băm của bạn tạo ra các băm bằng nhau cho nhiều chuỗi bạn sử dụng, nó sẽ tác động đến hành vi của phần mềm của bạn.

Dưới đây là một danh sách các hàm băm phổ biến nhất mà tạo ra một digest của 128bit:

  • RIPEMD (xác suất va chạm: 2^18)
  • MD4 (xác suất va chạm: cho chắc chắn)
  • MD5 (xác suất va chạm: 2^20,96)

Xin lưu ý rằng người ta có thể sử dụng cũng hàm băm khác mà sản xuất tiêu hóa lớn hơn và chỉ cần cắt những. Do đó, có thể thông minh để sử dụng hàm băm mới hơn. Để liệt kê một số:

  • SHA1
  • SHA-2
  • SHA-3

Hôm nay (tháng 8 2013) là 160bit SHA1 băm có thể được coi là một lựa chọn tốt.

+14

Nếu bạn định tạo GUID từ dữ liệu băm MD5, bạn thực sự phải tuân thủ tiêu chuẩn và * chỉ ra * rằng đây là [** Type 3 ** guid] (http://en.wikipedia.org /wiki/Universally_unique_identifier#Version_3_.28MD5_hash.29) - nghĩa là dữ liệu đến từ một băm MD5. GUID loại 3 có dạng «xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx', trong đó **' 3' ** cho biết 'Loại 3' và y được che dấu thành' 10xx'.Bạn cũng có thể sử dụng hàm băm SHA1 (Loại 5), nơi bạn thay đổi từ 3 đến 5. –

+1

Tôi sẽ thêm nhận xét của Ian vào câu trả lời để giúp làm rõ rằng bạn không thể chuyển đổi băm thành GUID: một số bit trong GUID cần các giá trị đặc biệt. –

+1

Chúng ta đang nói ở đây về một GUID không phải là UUID. Hãy lưu ý sự khác biệt. –

3

Nói chung, có một số cách để tạo ID duy nhất trên toàn cầu (UUID RFC 4122, GUID a.k.a.). Chúng tôi có thể mượn Bốn những từ Python, và thực hiện trong C# một cái gì đó giống nhau:

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

Tạo một UUID từ một host ID, số thứ tự, và thời gian hiện tại. Nếu nút không được cung cấp, getnode() được sử dụng để lấy địa chỉ phần cứng. Nếu clock_seq được đưa ra, nó được sử dụng như số thứ tự; nếu không, một số thứ tự 14 bit ngẫu nhiên sẽ được chọn.

uuid.uuid3(namespace, name)

Tạo một UUID dựa trên băm MD5 của một định danh namespace (mà là một UUID) và một tên (mà là một chuỗi).

uuid.uuid4()

Tạo một UUID ngẫu nhiên.

uuid.uuid5(namespace, name)

Tạo một UUID dựa trên băm SHA-1 của một định danh namespace (mà là một UUID) và một tên (mà là một chuỗi).

Vì vậy, nếu bạn cần ID của một chuỗi như một đối tượng, không phải ID của một giá trị, bạn nên mangle UUID tin của bạn với chuỗi nhất định, UUID tin của bạn tạo ra một lần sử dụng uuid1, và sau đó sử dụng nó như là không gian tên cho uuid3 hoặc uuid5.

Những biến thể và các phiên bản được mô tả trên Wikipedia Universally_unique_identifier#Variants_and_versions

2

Nếu ý định op là để tạo ra một UUID (Guid) từ một chuỗi hash của một số loại (MD5, SHA-1, et.c.), tôi thấy điều này câu hỏi rất giống với câu trả lời tuyệt vời này:

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

Nó có một liên kết đến một github-đoạn dựa trên RFC 4122 §4.3, mà sẽ tạo ra một Guid từ một chuỗi và một không gian tên (mà bạn có thể chọn cho chính mình để đảm bảo chống lại va chạm từ môi trường bên ngoài).

liên kết trực tiếp đến đoạn: https://github.com/LogosBible/Logos.Utility/blob/master/src/Logos.Utility/GuidUtility.cs

0

Dưới đây là cách tiếp cận riêng của tôi, tôi cố ý sử dụng String để hex đổ nếu có thể - trực quan có thể thấy lớn ít nhất cách chuỗi là, và nếu cần thiết - giải mã sử dụng một số công cụ chuyển đổi hex trực tuyến. Nhưng nếu chuỗi quá dài (hơn 16 byte) - sau đó sử dụng sha-1 để tính toán băm và tạo ra guid từ nó.

/// <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; 
} 
Các vấn đề liên quan