package org.bitseal.crypt; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.bitseal.util.ArrayCopier; import org.spongycastle.crypto.digests.RIPEMD160Digest; /** * Provides methods for several hashing functions based on SHA-512 * * @author Sebastian Schmidt, modified by Jonathan Coe */ public final class SHA512 { /** * Returns the sha512 sum of a given byte[] of data. * * @param data - A byte[] containing the input for sha512. * * @return A byte[] containing the sha512 sum of the input data */ public static byte[] sha512(byte[] data) { return sha512(data, 64); // 64 bytes is the standard output size for a SHA-512 hash } /** * Returns the sha512 sum of all given bytes. * * @param data - A byte[] containing the bytes * * @return A byte[] containing the sha512 sum of all given bytes. */ public static byte[] sha512(byte[]... data) { MessageDigest sha512; try { sha512 = MessageDigest.getInstance("SHA-512"); for (byte[] bytes : data) { sha512.update(bytes); } return sha512.digest(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("NoSuchAlgorithmException occurred in DigestSHA512.sha512()", e); } } /** * Returns the first x number of bytes of the SHA-512 hash of the input data. * * @param bytes - A byte[] containing the input for sha512. * @param digestLength - An int representing the number of bytes to return. * * @return A byte[] containing the first x number of bytes of the SHA-512 hash of the input data. */ public static byte[] sha512(byte[] bytes, int digestLength) { MessageDigest sha512; try { sha512 = MessageDigest.getInstance("SHA-512"); byte[] sum = sha512.digest(bytes); return ArrayCopier.copyOf(sum, digestLength); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("NoSuchAlgorithmException occurred in DigestSHA512.sha512()", e); } } /** * Calculates the double SHA-512 hash of a given byte[] * * @param input - A byte[] containing the data to be hashed * * @return A byte[] containing the double SHA-512 hash of the input data */ public static byte[] doubleHash(byte[] input) { return doubleHash(input, 0, input.length); } /** * Calculates the SHA-512 hash of the given byte range, and then hashes the resulting hash again. This is * standard procedure in BitCoin. The resulting hash is in big endian form. * * @param input - A byte[] containing the data to hash * @param offset - An int representing the index in the data byte[] at which to begin * @param length - An int representing the number of bytes from the data byte[] to process * * @return A byte[] containing the doubly SHA-512 hashed data */ public static byte[] doubleHash(byte[] input, int offset, int length) { try { MessageDigest digest = MessageDigest.getInstance("SHA-512"); digest.update(input, offset, length); byte[] first = digest.digest(); return digest.digest(first); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("NoSuchAlgorithmException occurred in DigestSHA512.doubleDigest()", e); } } /** * Calculates RIPEMD160(SHA512(input)). This is used in Address calculations. * * @param input - A byte[] containing the data to hash * * @return A byte[] containing the hash of the data */ public static byte[] sha512hash160(byte[] input) { try { byte[] sha512 = MessageDigest.getInstance("SHA-512").digest(input); RIPEMD160Digest digest = new RIPEMD160Digest(); digest.update(sha512, 0, sha512.length); byte[] out = new byte[20]; digest.doFinal(out, 0); return out; } catch (NoSuchAlgorithmException e) { throw new RuntimeException("NoSuchAlgorithmException occurred in DigestSHA512.sha512hash160()", e); } } }