Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hash a whole object without converting to byte[] first

Tags:

java

hash

sha256

I want to get sha2 hash of particular java object. I don't want it to be int, I want byte[] or at least String. I've got the following code to create sha2:

static byte[] sha2(byte[] message) {
    if (message == null || message.length == 0) {
        throw new IllegalArgumentException("message is null");
    }
    try {
        MessageDigest sha256 = MessageDigest.getInstance(SHA_256);
        return sha256.digest(message);
    } catch (NoSuchAlgorithmException e) {
        throw new IllegalArgumentException(e);
    }
}

I can just convert my object to byte[], but I don't think it's a good idea to store big array in memory just to create 32 byte array. So how can I compute sha2(or maybe another crypto hash function) of object?

like image 503
Tony Avatar asked Sep 20 '25 21:09

Tony


1 Answers

You do not have to load the whole object into memory, you can load parts of it into temporary buffer.

Dump object into a temporary file using FileOutputStream/BufferedOutputStream, this will make sure serialized object does not pollute JVM memory.

The load serialize object from temporary file using FileInputStream/BufferedInputStream and feed it to MessageDigest#update(buf) method in a loop.

Finally call MessageDigest#digest() to finish work:

int[] buf = new int[1024];
while (/* has more data */) {
    int readBytes = readIntoBuf(buf);
    sha256.update(buf, 0, readBytes);
}
return sha256.digest();

If you can afford to store entire serialized object in memory, use ByteArrayOutputStream and pass result byte[] to MessageDigest#digest(buf):

try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos)) {
    oos.writeObject(obj);

    MessageDigest sha256 = MessageDigest.getInstance(SHA_256);
    return sha256.digest(baos.toByteArray());
}
like image 57
hoaz Avatar answered Sep 22 '25 12:09

hoaz