【问题标题】:Hashing image bytes with SHA-256 yields many random collisions, what am I doing wrong?使用 SHA-256 散列图像字节会产生许多随机冲突,我做错了什么?
【发布时间】:2012-06-17 21:35:48
【问题描述】:

我正在使用 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();
}

【问题讨论】:

    标签: java bufferedimage sha hash-collision message-digest


    【解决方案1】:

    试试

    digest.update(imageBytes);
    

    【讨论】:

      【解决方案2】:

      我认为offset 计算错误。应该是:

      int offset = y * width * 4;
      

      创建imageBytes 的更好方法可能是ByteBuffer;它允许您按顺序简单地put 每个字节,而无需计算索引。另外,可以直接和MessageDigest一起使用。

      【讨论】:

      • @TylerBettilyon 你能分享你的最终解决方案吗?
      • 抱歉@Tarion,我是为一家公司做的,但我不再在那里工作,也无法再访问代码库。
      【解决方案3】:

      我想出了这个。基于上面的 cmets:

      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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-28
        • 1970-01-01
        • 2018-07-14
        • 1970-01-01
        • 2011-07-20
        • 2017-02-13
        相关资源
        最近更新 更多