2013-08-21 28 views
5

tôi có mã này để tạo ra một băm SHA-1:Làm cách nào để tạo một Guid từ mảng byte SHA-1?

SHA1 sha1 = SHA1CryptoServiceProvider.Create(); 
Byte[] myStringBytes = ASCIIEncoding.Default.GetBytes(myString); 
Byte[] hash = sha1.ComputeHash(myStringBytes); 

Có cách nào để biến hash thành một Guid (loại 5, tôi đoán, để phù hợp với SHA-1)?

+0

Đây là kinda khó hiểu như một băm và một guid những điều khác nhau. Một guid sẽ cung cấp cho bạn một chuỗi duy nhất/khác nhau mỗi khi bạn yêu cầu một guid mới. Hashes cho bạn kết quả nhất quán dựa trên cùng một đầu vào. – Justin

+0

Nó sẽ là một GUID xác định và lặp lại, dựa trên một băm, có ý định tạo ra các giá trị duy nhất tùy thuộc vào đầu vào. Thông tin thêm: http://waterjuice.org/2013/06/type-3-and-5-guids/ –

+3

@Justin: Bạn hiểu lầm những gì OP yêu cầu. GUID không là gì ngoài một định danh duy nhất toàn cầu; đó là điều GUID đại diện. Có nhiều cách để tạo GUID. Ví dụ, bạn có thể tạo GUID dựa trên thời gian và vị trí hiện tại; đó là duy nhất toàn cầu. (Chủ yếu.) Đó là loại GUID. Bạn có thể tạo GUID độc đáo về mặt thống kê với trình tạo số ngẫu nhiên; đó là một loại bốn GUID. Một băm mã hóa mạnh mẽ ** của một chuỗi duy nhất ** cũng là một nguồn duy nhất, và có thể được sử dụng để xây dựng một GUID. –

Trả lời

4

Bạn có thể sử dụng số này C# code dựa trên rfc4122.

Để ngăn chặn link rot, một số mã ở đây:

public static Guid Create(Guid namespaceId, string name) 
{ 
    if (name == null) 
     throw new ArgumentNullException("name"); 

    // convert the name to a sequence of octets (as defined by the standard or conventions of its namespace) (step 3) 
    // ASSUME: UTF-8 encoding is always appropriate 
    byte[] nameBytes = Encoding.UTF8.GetBytes(name); 

    // convert the namespace UUID to network order (step 3) 
    byte[] namespaceBytes = namespaceId.ToByteArray(); 
    SwapByteOrder(namespaceBytes); 

    // comput the hash of the name space ID concatenated with the name (step 4) 
    byte[] hash; 
    using (HashAlgorithm algorithm = SHA1.Create()) 
    { 
     algorithm.TransformBlock(namespaceBytes, 0, namespaceBytes.Length, null, 0); 
     algorithm.TransformFinalBlock(nameBytes, 0, nameBytes.Length); 
     hash = algorithm.Hash; 
    } 

    // most bytes from the hash are copied straight to the bytes of the new GUID (steps 5-7, 9, 11-12) 
    byte[] newGuid = new byte[16]; 
    Array.Copy(hash, 0, newGuid, 0, 16); 

    // set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the appropriate 4-bit version number from Section 4.1.3 (step 8) 
    newGuid[6] = (byte)((newGuid[6] & 0x0F) | (5 << 4)); 

    // set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively (step 10) 
    newGuid[8] = (byte)((newGuid[8] & 0x3F) | 0x80); 

    // convert the resulting UUID to local byte order (step 13) 
    SwapByteOrder(newGuid); 
    return new Guid(newGuid); 
} 

/// <summary> 
/// The namespace for fully-qualified domain names (from RFC 4122, Appendix C). 
/// </summary> 
public static readonly Guid DnsNamespace = new Guid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); 

/// <summary> 
/// The namespace for URLs (from RFC 4122, Appendix C). 
/// </summary> 
public static readonly Guid UrlNamespace = new Guid("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); 

/// <summary> 
/// The namespace for ISO OIDs (from RFC 4122, Appendix C). 
/// </summary> 
public static readonly Guid IsoOidNamespace = new Guid("6ba7b812-9dad-11d1-80b4-00c04fd430c8"); 

// Converts a GUID (expressed as a byte array) to/from network order (MSB-first). 
internal static void SwapByteOrder(byte[] guid) 
{ 
    SwapBytes(guid, 0, 3); 
    SwapBytes(guid, 1, 2); 
    SwapBytes(guid, 4, 5); 
    SwapBytes(guid, 6, 7); 
} 

private static void SwapBytes(byte[] guid, int left, int right) 
{ 
    byte temp = guid[left]; 
    guid[left] = guid[right]; 
    guid[right] = temp; 
} 
2

Như được chỉ ra bởi Justin, một hướng dẫn nên là duy nhất mỗi lần, trong khi một băm sẽ cung cấp cho một kết quả nhất quán mỗi lần cho cùng một giá trị.

Bây giờ tôi muốn thêm vào đó và nói rằng cả hai hướng dẫn và băm (hầu hết, nếu không phải tất cả thuật toán) đều bị va chạm, mặc dù cảm giác ruột của tôi là băm phải chịu mức va chạm lớn hơn Guids ... mặc dù điều này có thể tùy thuộc vào kích thước của băm (ví dụ: 128 bit, 256 bit, 512 bit, v.v ...).

Một vấn đề khác bạn sẽ gặp phải là byte[] từ giá trị băm SHA1 dài 20 byte, trong khi Guid dài 16 byte, do đó, việc tạo một Guid từ băm SHA1 sẽ không chính xác.

Ví dụ:

string myString = "Hello World"; 
SHA1 sha1 = SHA1CryptoServiceProvider.Create(); 
Byte[] myStringBytes = ASCIIEncoding.Default.GetBytes(myString); 
Byte[] hash = sha1.ComputeHash(myStringBytes); 
Console.WriteLine(new Guid(hash.Take(16).ToArray())); 

Ví dụ trên sẽ tạo ra một Guid từ băm của bạn, mặc dù nó sử dụng LINQ để có được 16 byte từ mảng băm (do đó thiếu chính xác ... 4 byte cuối cùng là chỉ cần bỏ qua)

MD5 là một băm 16 byte, do đó, điều này có vẻ như nó có thể phù hợp hơn để chuyển đổi thành Guid hơn SHA1.

Ví dụ:

string myString = "Hello World"; 
MD5 md5 = MD5.Create(); 
Byte[] myStringBytes = ASCIIEncoding.Default.GetBytes(myString); 
Byte[] hash = md5.ComputeHash(myStringBytes); 
Console.WriteLine(new Guid(hash)); 

Điều này tạo ra một Guid chính xác từ băm MD5, mặc dù tôi sẽ nêu, tất cả điều này là, là một đại diện Guid của băm MD5 ... không nên có thực tế thay đổi trong dữ liệu byte[].

+0

Đầu tiên, bạn hiểu nhầm lý do tại sao nó là hợp lý để sử dụng một hash brypto-sức mạnh ** của một chuỗi duy nhất ** để tạo ra một GUID. Xem bình luận của tôi ở trên. Thứ hai, mã này là sai; nó không thiết lập số phiên bản của GUID, đó là một yêu cầu được tài liệu của định dạng GUID. –

+0

@EricLippert, Quản lý văn bản ở đây: http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_5_.28SHA-1_hash.29 - Cho rằng điều này nói rằng GUIDv5 là SHA1 đã bị cắt ngắn từ 160bit đến 128bit, tôi tôi đoán rằng ví dụ mã đầu tiên của tôi gần với yêu cầu của OP hơn là ví dụ thứ hai của tôi? - Có lẽ một chút lại làm việc cũng được yêu cầu ở đây để thiết lập số phiên bản cũng? – series0ne

+0

Đúng vậy. –

Các vấn đề liên quan