2013-05-11 55 views
1

我找不到Java的自包含UUID5實現,所以我試着在下面滾動這個解決方案。它通過了我的一些單元測試,但是失敗了。這有什麼明顯的錯誤?這個Java UUID5實現沒有通過單元測試

public static UUID UUID5(UUID namespace, String name) { 
    MessageDigest md; 
    try { 
     md = MessageDigest.getInstance("SHA-1"); 
    } catch (NoSuchAlgorithmException nsae) { 
     throw new InternalError("SHA-1 not supported"); 
    } 

    byte[] namespaceBytes = ByteBuffer.allocate(16).putLong(namespace.getMostSignificantBits()).putLong(namespace.getLeastSignificantBits()).array(); 
    byte[] nameBytes; 
    try { 
     nameBytes = name.getBytes("UTF-8"); 
    } catch (UnsupportedEncodingException e) { 
     throw new InternalError("UTF-8 encoding not supported"); 
    } 

    byte[] toHashify = new byte[namespaceBytes.length + nameBytes.length]; 
    System.arraycopy(namespaceBytes, 0, toHashify, 0, namespaceBytes.length); 
    System.arraycopy(nameBytes, 0, toHashify, namespaceBytes.length, nameBytes.length); 

    byte[] data = md.digest(toHashify); 
    data = Arrays.copyOfRange(data, 0, 16); // Wikipedia says "Note that the 160 bit SHA-1 hash is truncated to 128 bits to make the length work out." 

    data[6] &= 0x0f; /* clear version  */ 
    data[6] |= 0x50; /* set to version 5  TODO is this the correct way to do it  */ 
    data[8] &= 0x3f; /* clear variant  */ 
    data[8] |= 0x80; /* set to IETF variant */ 

    long msb = 0; 
    long lsb = 0; 
    assert data.length == 16 : "data must be 16 bytes in length"; 
    for (int i=0; i<8; i++) 
     {msb = (msb << 8) | (data[i] & 0xff);} 
    for (int i=8; i<16; i++) 
     {lsb = (lsb << 8) | (data[i] & 0xff);} 

    return new UUID(msb, lsb); 
} 
+0

你可能也想發佈你的單元測試。 – Dave 2013-05-11 20:21:21

+1

選中此行:'data = Arrays.copyOfRange(data,0,128);'...散列值爲128 *位*,但您將數組填充爲128 *字節*。 – sehrope 2013-05-11 20:21:55

+0

@sehrope謝謝,我修正了這個問題,但它仍然通過並且失敗了與之前相同的測試 – AlcubierreDrive 2013-05-11 20:25:54

回答

4

使用Apache Commons Id,更具體地爲UUID.nameUUIDFromString

UUID uuid5 = UUID.nameUUIDFromString("www.ford.com", 
     UUID.fromString("078d4e79-244f-440e-844d-9454eadfd411"), 
     UUID.SHA1_ENCODING); 

UUID.SHA1_ENCODING將產生第5點的UUID。

+0

謝謝,會做。仍然好奇,如果有人能夠回答這個問題,並修復我的手動滾動代碼的錯誤 – AlcubierreDrive 2013-05-11 21:42:56

+0

+1爲不重新發明輪子 – 2013-05-11 22:04:59

+0

其實,我找不到任何方法來下載Commons Id !!發佈頁面沒有任何:http://commons.apache.org/sandbox/commons-id/downloads .html鏈接到源代碼回購破壞:http://svn.apache.org/viewvc/jakarta/commons/sandbox/id/ – AlcubierreDrive 2013-05-11 22:26:41