2012-06-14 57 views
4

我正在使用SHA-256算法來檢測數據庫中的相同圖像。因爲我們使用了很多不同的圖像格式,我不想直接在文件上計算散列。相反,我想提取像素數據並在其上計算散列。使用SHA-256散列圖像字節會產生很多隨機衝突,我做錯了什麼?

不幸的是我得到了很多隨機衝突:68個圖像沒有相同的字節,使用相同的像素提取(下圖)在6000個圖像中散列爲相同的值。我覺得這是一個瘋狂的碰撞數量。此外,我將我計算的字節從像素數據轉儲到文件中,然後嘗試:

echo -n [byteDumpFile] | sha256sum

這導致了轉儲圖像的不同哈希值,這導致我相信我在使用MessageDigest時做錯了什麼。

這裏是我得到的像素數據:

imageBytes = new byte[4 * width * height]; 
    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 

      // grab color information 
      int argb = image.getRGB(x, y); 

      // a,r,g,b ordered bytes per this pixel. the values are always 0-255 so the byte cast is safe 
      int offset = y * width; 
      int pushX = x * 4; 
      imageBytes[pushX + offset] = (byte) ((argb >> 24) & 0xff); 
      imageBytes[pushX + 1 + offset] = (byte) ((argb >> 16) & 0xff); 
      imageBytes[pushX + 2 + offset] = (byte) ((argb >> 8) & 0xff); 
      imageBytes[pushX + 3 + offset] = (byte) (argb & 0xff); 

     } 
    } 

然後我計算使用MessageDigest類散:

MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
    digest.reset(); 


    for (int i = 0; i < imageBytes.length; i++) 
    { 
     digest.update(imageBytes[i]); 
    } 

    String hashString = new String(encodeHex(digest.digest())); 

其中encodeHex就是:

private static String encodeHex(byte data[]) 
    { 
     StringBuilder hex = new StringBuilder(2 * data.length); 
     for (byte b : data) 
     { 
      hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F))); 
     } 

    return hex.toString(); 
} 

回答

2

我認爲offset正在計算錯誤。它應該是:

int offset = y * width * 4; 

一種更好的方式來創建imageBytes可能是一個ByteBuffer;它允許您按順序簡單地put而不計算索引。另外,它可以直接與MessageDigest一起使用。

+0

* facepalm *謝謝。 –

+0

@TylerBettilyon你能分享你的最終解決方案嗎? – Tarion

+0

對不起@Tarion,我是爲一家公司做的,但我不再在那裏工作,也無法再訪問代碼庫。 –

1

digest.update(imageBytes); 
0

我想出了這個。根據以上意見:

private String calculateHash(BufferedImage img) throws NoSuchAlgorithmException { 
    final int width = img.getWidth(); 
    final int height = img.getHeight(); 
    final ByteBuffer byteBuffer = ByteBuffer.allocate(4 * width * height); 
    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      // grab color information 
      int argb = img.getRGB(x, y); 

      // a,r,g,b ordered bytes per this pixel. the values are always 0-255 so the byte cast is safe 
      byteBuffer.put((byte) ((argb >> 24) & 0xff)); 
      byteBuffer.put((byte) ((argb >> 16) & 0xff)); 
      byteBuffer.put((byte) ((argb >> 8) & 0xff)); 
      byteBuffer.put((byte) (argb & 0xff)); 
     } 
    } 


    MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
    digest.reset(); 

    byte[] hashBytes = digest.digest(byteBuffer.array()); 
    return Base64Utils.encodeToString(hashBytes); 
} 
相關問題