package org.ripple.power.txns.btc; import org.ripple.bouncycastle.util.encoders.Hex; import org.ripple.power.Helper; import java.math.BigInteger; import java.util.Arrays; /** * A Sha256Hash wraps a byte[] so that equals and hashCode work correctly, allowing it to * be used as a key in a map. */ public class Sha256Hash { /** A zero hash */ public static final Sha256Hash ZERO_HASH = new Sha256Hash(); /** The byte value of the SHA-256 digest */ private byte[] bytes; /** * Creates a Sha256Hash with a zero value */ public Sha256Hash() { bytes = new byte[32]; } /** Creates a Sha256Hash by wrapping the given byte array * * @param rawHashBytes 32-byte hash digest */ public Sha256Hash(byte[] rawHashBytes) { this(rawHashBytes, 0, rawHashBytes.length); } /** * Creates a Sha256Hash by wrapping the given byte array * * @param rawHashBytes 32-byte hash digest * @param offset Offset within the byte array * @param length Number of bytes */ public Sha256Hash(byte[] rawHashBytes, int offset, int length) { if (length != 32) throw new IllegalArgumentException("SHA-256 hash must be 32 bytes"); if (offset+length > rawHashBytes.length) throw new IllegalArgumentException("Hash byte array overflow"); bytes = new byte[32]; System.arraycopy(rawHashBytes, offset, bytes, 0, length); } /** * Creates a Sha256Hash by decoding the given hex string. It must be 64 characters long. * * @param hexString 64-character hex string */ public Sha256Hash(String hexString) { if (hexString.length() != 64) throw new IllegalArgumentException("SHA-256 hash string must be 64 characters"); bytes = Hex.decode(hexString); } /** * Returns the bytes interpreted as a positive integer. * * @return The integer representation of the hash digest */ public BigInteger toBigInteger() { return new BigInteger(1, bytes); } /** * Returns the hash digest * * @return The hash digest */ public byte[] getBytes() { return bytes; } /** * Compares this Sha256Hash object to another one * * @param other The object to compare * @return TRUE if the objects are equal */ @Override public boolean equals(Object other) { return (other!=null && (other instanceof Sha256Hash) && Arrays.equals(bytes, ((Sha256Hash)other).bytes)); } /** * Generates the hash code for this object. We use the last 4 bytes of the value to form the hash because * the first 4 bytes often contain zero values in the Bitcoin protocol. * * @return Hash code */ @Override public int hashCode() { return (((int)bytes[28]&0xff)<<24) | (((int)bytes[29]&0xff)<<16) | (((int)bytes[30]&0xff)<<8) | ((int)bytes[31]&0xff); } /** * Creates a string representation of the hash value of this object * * @return The string representation */ @Override public String toString() { return Helper.bytesToHexString(bytes); } }