3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-12 18:25:51 +00:00

moved sha256-related utility methods into Sha256Hash class and renamed them

This commit is contained in:
Amichai Rothman 2015-06-22 21:42:17 +03:00 committed by Mike Hearn
parent a449e3b026
commit a6601066dd
19 changed files with 120 additions and 122 deletions

View File

@ -114,7 +114,7 @@ public class AlertMessage extends Message {
* doesn't verify, because that would allow arbitrary attackers to spam your users.
*/
public boolean isSignatureValid() {
return ECKey.verify(Utils.doubleDigest(content), signature, params.getAlertSigningKey());
return ECKey.verify(Sha256Hash.calcDoubleHashBytes(content), signature, params.getAlertSigningKey());
}
@Override

View File

@ -153,7 +153,7 @@ public class Base58 {
byte[] bytes = copyOfRange(tmp, 0, tmp.length - 4);
byte[] checksum = copyOfRange(tmp, tmp.length - 4, tmp.length);
tmp = Utils.doubleDigest(bytes);
tmp = Sha256Hash.calcDoubleHashBytes(bytes);
byte[] hash = copyOfRange(tmp, 0, 4);
if (!Arrays.equals(checksum, hash))
throw new AddressFormatException("Checksum does not validate");

View File

@ -112,7 +112,7 @@ public class BitcoinSerializer {
Utils.uint32ToByteArrayLE(message.length, header, 4 + COMMAND_LEN);
byte[] hash = doubleDigest(message);
byte[] hash = Sha256Hash.calcDoubleHashBytes(message);
System.arraycopy(hash, 0, header, 4 + COMMAND_LEN + 4, 4);
out.write(header);
out.write(message);
@ -174,7 +174,7 @@ public class BitcoinSerializer {
// Verify the checksum.
byte[] hash;
hash = doubleDigest(payloadBytes);
hash = Sha256Hash.calcDoubleHashBytes(payloadBytes);
if (header.checksum[0] != hash[0] || header.checksum[1] != hash[1] ||
header.checksum[2] != hash[2] || header.checksum[3] != hash[3]) {
throw new ProtocolException("Checksum failed to verify, actual " +

View File

@ -37,8 +37,7 @@ import java.util.LinkedList;
import java.util.List;
import static org.bitcoinj.core.Coin.FIFTY_COINS;
import static org.bitcoinj.core.Utils.doubleDigest;
import static org.bitcoinj.core.Utils.doubleDigestTwoBuffers;
import static org.bitcoinj.core.Sha256Hash.calcDoubleHashBytes;
/**
* <p>A block is a group of transactions, and is one of the fundamental data structures of the Bitcoin system.
@ -192,7 +191,7 @@ public class Block extends Message {
difficultyTarget = readUint32();
nonce = readUint32();
hash = new Sha256Hash(Utils.reverseBytes(Utils.doubleDigest(payload, offset, cursor)));
hash = new Sha256Hash(Utils.reverseBytes(Sha256Hash.calcDoubleHashBytes(payload, offset, cursor)));
headerParsed = true;
headerBytesValid = parseRetain;
@ -512,7 +511,7 @@ public class Block extends Message {
try {
ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(HEADER_SIZE);
writeHeader(bos);
return new Sha256Hash(Utils.reverseBytes(doubleDigest(bos.toByteArray())));
return new Sha256Hash(Utils.reverseBytes(Sha256Hash.calcDoubleHashBytes(bos.toByteArray())));
} catch (IOException e) {
throw new RuntimeException(e); // Cannot happen.
}
@ -750,7 +749,7 @@ public class Block extends Message {
int right = Math.min(left + 1, levelSize - 1);
byte[] leftBytes = Utils.reverseBytes(tree.get(levelOffset + left));
byte[] rightBytes = Utils.reverseBytes(tree.get(levelOffset + right));
tree.add(Utils.reverseBytes(doubleDigestTwoBuffers(leftBytes, 0, 32, rightBytes, 0, 32)));
tree.add(Utils.reverseBytes(calcDoubleHashBytes(leftBytes, 0, 32, rightBytes, 0, 32)));
}
// Move to the next level.
levelOffset += levelSize;

View File

@ -100,7 +100,7 @@ public class CheckpointManager {
private Sha256Hash readBinary(InputStream inputStream) throws IOException {
DataInputStream dis = null;
try {
MessageDigest digest = Utils.newSha256Digest();
MessageDigest digest = Sha256Hash.newDigest();
DigestInputStream digestInputStream = new DigestInputStream(inputStream, digest);
dis = new DataInputStream(digestInputStream);
digestInputStream.on(false);

View File

@ -214,9 +214,9 @@ public class PartialMerkleTree extends Message {
}
private static Sha256Hash combineLeftRight(byte[] left, byte[] right) {
return new Sha256Hash(reverseBytes(doubleDigestTwoBuffers(
reverseBytes(left), 0, 32,
reverseBytes(right), 0, 32)));
return new Sha256Hash(reverseBytes(Sha256Hash.calcDoubleHashBytes(
reverseBytes(left), 0, 32,
reverseBytes(right), 0, 32)));
}
/**

View File

@ -36,6 +36,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* map. It also checks that the length is correct and provides a bit more type safety.
*/
public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
private static final MessageDigest digest = newDigest();
private final byte[] bytes;
public static final Sha256Hash ZERO_HASH = new Sha256Hash(new byte[32]);
@ -65,7 +66,7 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
* Calculates the (one-time) hash of contents and returns it.
*/
public static Sha256Hash hash(byte[] contents) {
return new Sha256Hash(Utils.singleDigest(contents));
return new Sha256Hash(calcHashBytes(contents));
}
/** Use hashTwice(byte[]) instead: this old name is ambiguous. */
@ -78,7 +79,7 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
* Calculates the hash of the hash of the contents. This is a standard operation in Bitcoin.
*/
public static Sha256Hash hashTwice(byte[] contents) {
return new Sha256Hash(Utils.doubleDigest(contents));
return new Sha256Hash(calcDoubleHashBytes(contents));
}
/**
@ -95,6 +96,89 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
}
}
/**
* Returns a new SHA-256 MessageDigest instance.
*
* This is a convenience method which wraps the checked
* exception that can never occur with a RuntimeException.
*
* @return a new SHA-256 MessageDigest instance
*/
public static MessageDigest newDigest() {
try {
return MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e); // Can't happen.
}
}
/**
* Calculates the SHA-256 hash of the given bytes.
*
* @param input the bytes to hash
* @return the hash (in big-endian order)
*/
public static byte[] calcHashBytes(byte[] input) {
return calcHashBytes(input, 0, input.length);
}
/**
* Calculates the SHA-256 hash of the given byte range.
*
* @param input the array containing the bytes to hash
* @param offset the offset within the array of the bytes to hash
* @param length the number of bytes to hash
* @return the hash (in big-endian order)
*/
public static byte[] calcHashBytes(byte[] input, int offset, int length) {
MessageDigest digest = newDigest();
digest.update(input, offset, length);
return digest.digest();
}
/**
* Calculates the SHA-256 hash of the given bytes,
* and then hashes the resulting hash again.
*
* @param input the bytes to hash
* @return the double-hash (in big-endian order)
*/
public static byte[] calcDoubleHashBytes(byte[] input) {
return calcDoubleHashBytes(input, 0, input.length);
}
/**
* Calculates the SHA-256 hash of the given byte range,
* and then hashes the resulting hash again.
*
* @param input the array containing the bytes to hash
* @param offset the offset within the array of the bytes to hash
* @param length the number of bytes to hash
* @return the double-hash (in big-endian order)
*/
public static byte[] calcDoubleHashBytes(byte[] input, int offset, int length) {
synchronized (digest) {
digest.reset();
digest.update(input, offset, length);
byte[] first = digest.digest();
return digest.digest(first);
}
}
/**
* Calculates SHA256(SHA256(byte range 1 + byte range 2)).
*/
public static byte[] calcDoubleHashBytes(byte[] input1, int offset1, int length1,
byte[] input2, int offset2, int length2) {
synchronized (digest) {
digest.reset();
digest.update(input1, offset1, length1);
digest.update(input2, offset2, length2);
byte[] first = digest.digest();
return digest.digest(first);
}
}
@Override
public boolean equals(Object o) {
return this == o || o != null && getClass() == o.getClass() && Arrays.equals(bytes, ((Sha256Hash)o).bytes);

View File

@ -226,7 +226,7 @@ public class Transaction extends ChildMessage implements Serializable {
public Sha256Hash getHash() {
if (hash == null) {
byte[] bits = bitcoinSerialize();
hash = new Sha256Hash(reverseBytes(doubleDigest(bits)));
hash = new Sha256Hash(reverseBytes(Sha256Hash.calcDoubleHashBytes(bits)));
}
return hash;
}
@ -1010,7 +1010,7 @@ public class Transaction extends ChildMessage implements Serializable {
uint32ToByteStreamLE(0x000000ff & sigHashType, bos);
// Note that this is NOT reversed to ensure it will be signed correctly. If it were to be printed out
// however then we would expect that it is IS reversed.
Sha256Hash hash = new Sha256Hash(doubleDigest(bos.toByteArray()));
Sha256Hash hash = new Sha256Hash(Sha256Hash.calcDoubleHashBytes(bos.toByteArray()));
bos.close();
// Put the transaction back to how we found it.

View File

@ -33,8 +33,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
@ -50,7 +48,6 @@ import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterrup
* To enable debug logging from the library, run with -Dbitcoinj.logging=true on your command line.
*/
public class Utils {
private static final MessageDigest digest = newSha256Digest();
/** The string that prefixes all text messages signed using Bitcoin keys. */
public static final String BITCOIN_SIGNED_MESSAGE_HEADER = "Bitcoin Signed Message:\n";
@ -58,22 +55,6 @@ public class Utils {
private static BlockingQueue<Boolean> mockSleepQueue;
/**
* Returns a new SHA-256 MessageDigest instance.
*
* This is a convenience method which wraps the checked
* exception that can never occur with a RuntimeException.
*
* @return a new SHA-256 MessageDigest instance
*/
public static MessageDigest newSha256Digest() {
try {
return MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e); // Can't happen.
}
}
/**
* The regular {@link java.math.BigInteger#toByteArray()} method isn't quite what we often need: it appends a
* leading zero to indicate that the number is positive and may need padding.
@ -150,73 +131,6 @@ public class Utils {
}
}
/**
* Calculates the SHA-256 hash of the given bytes,
* and then hashes the resulting hash again.
*
* @param input the bytes to hash
* @return the double-hash (in big-endian order)
*/
public static byte[] doubleDigest(byte[] input) {
return doubleDigest(input, 0, input.length);
}
/**
* Calculates the SHA-256 hash of the given byte range,
* and then hashes the resulting hash again.
*
* @param input the array containing the bytes to hash
* @param offset the offset within the array of the bytes to hash
* @param length the number of bytes to hash
* @return the double-hash (in big-endian order)
*/
public static byte[] doubleDigest(byte[] input, int offset, int length) {
synchronized (digest) {
digest.reset();
digest.update(input, offset, length);
byte[] first = digest.digest();
return digest.digest(first);
}
}
/**
* Calculates the SHA-256 hash of the given bytes.
*
* @param input the bytes to hash
* @return the hash (in big-endian order)
*/
public static byte[] singleDigest(byte[] input) {
return singleDigest(input, 0, input.length);
}
/**
* Calculates the SHA-256 hash of the given byte range.
*
* @param input the array containing the bytes to hash
* @param offset the offset within the array of the bytes to hash
* @param length the number of bytes to hash
* @return the hash (in big-endian order)
*/
public static byte[] singleDigest(byte[] input, int offset, int length) {
MessageDigest digest = newSha256Digest();
digest.update(input, offset, length);
return digest.digest();
}
/**
* Calculates SHA256(SHA256(byte range 1 + byte range 2)).
*/
public static byte[] doubleDigestTwoBuffers(byte[] input1, int offset1, int length1,
byte[] input2, int offset2, int length2) {
synchronized (digest) {
digest.reset();
digest.update(input1, offset1, length1);
digest.update(input2, offset2, length2);
byte[] first = digest.digest();
return digest.digest(first);
}
}
/**
* Work around lack of unsigned types in Java.
*/
@ -302,7 +216,7 @@ public class Utils {
* Calculates RIPEMD160(SHA256(input)). This is used in Address calculations.
*/
public static byte[] sha256hash160(byte[] input) {
byte[] sha256 = singleDigest(input);
byte[] sha256 = Sha256Hash.calcHashBytes(input);
RIPEMD160Digest digest = new RIPEMD160Digest();
digest.update(sha256, 0, sha256.length);
byte[] out = new byte[20];

View File

@ -61,7 +61,7 @@ public class VersionedChecksummedBytes implements Serializable, Cloneable, Compa
byte[] addressBytes = new byte[1 + bytes.length + 4];
addressBytes[0] = (byte) version;
System.arraycopy(bytes, 0, addressBytes, 1, bytes.length);
byte[] checksum = Utils.doubleDigest(addressBytes, 0, bytes.length + 1);
byte[] checksum = Sha256Hash.calcDoubleHashBytes(addressBytes, 0, bytes.length + 1);
System.arraycopy(checksum, 0, addressBytes, bytes.length + 1, 4);
return Base58.encode(addressBytes);
}

View File

@ -122,7 +122,7 @@ public class BIP38PrivateKey extends VersionedChecksummedBytes {
if (hasLotAndSequence) {
byte[] hashBytes = Bytes.concat(passFactorBytes, ownerEntropy);
checkState(hashBytes.length == 40);
passFactorBytes = Utils.doubleDigest(hashBytes);
passFactorBytes = Sha256Hash.calcDoubleHashBytes(hashBytes);
}
BigInteger passFactor = new BigInteger(1, passFactorBytes);
ECKey k = ECKey.fromPrivate(passFactor, true);
@ -150,7 +150,7 @@ public class BIP38PrivateKey extends VersionedChecksummedBytes {
byte[] seed = Bytes.concat(decrypted1, Arrays.copyOfRange(decrypted2, 8, 16));
checkState(seed.length == 24);
BigInteger seedFactor = new BigInteger(1, Utils.doubleDigest(seed));
BigInteger seedFactor = new BigInteger(1, Sha256Hash.calcDoubleHashBytes(seed));
checkState(passFactor.signum() >= 0);
checkState(seedFactor.signum() >= 0);
BigInteger priv = passFactor.multiply(seedFactor).mod(ECKey.CURVE.getN());

View File

@ -283,7 +283,7 @@ public class DeterministicKey extends ECKey {
int inputLength = input.length;
byte[] checksummed = new byte[inputLength + 4];
System.arraycopy(input, 0, checksummed, 0, inputLength);
byte[] checksum = Utils.doubleDigest(input);
byte[] checksum = Sha256Hash.calcDoubleHashBytes(input);
System.arraycopy(checksum, 0, checksummed, inputLength, 4);
return checksummed;
}

View File

@ -17,6 +17,7 @@
package org.bitcoinj.crypto;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;
import com.google.common.base.Joiner;
import org.slf4j.Logger;
@ -86,7 +87,7 @@ public class MnemonicCode {
public MnemonicCode(InputStream wordstream, String wordListDigest) throws IOException, IllegalArgumentException {
BufferedReader br = new BufferedReader(new InputStreamReader(wordstream, "UTF-8"));
this.wordList = new ArrayList<String>(2048);
MessageDigest md = Utils.newSha256Digest();
MessageDigest md = Sha256Hash.newDigest();
String word;
while ((word = br.readLine()) != null) {
md.update(word.getBytes());
@ -173,7 +174,7 @@ public class MnemonicCode {
entropy[ii] |= 1 << (7 - jj);
// Take the digest of the entropy.
byte[] hash = Utils.singleDigest(entropy);
byte[] hash = Sha256Hash.calcHashBytes(entropy);
boolean[] hashBits = bytesToBits(hash);
// Check all the checksum bits.
@ -197,7 +198,7 @@ public class MnemonicCode {
// We take initial entropy of ENT bits and compute its
// checksum by taking first ENT / 32 bits of its SHA256 hash.
byte[] hash = Utils.singleDigest(entropy);
byte[] hash = Sha256Hash.calcHashBytes(entropy);
boolean[] hashBits = bytesToBits(hash);
boolean[] entropyBits = bytesToBits(entropy);

View File

@ -101,7 +101,7 @@ public class HttpDiscovery implements PeerDiscovery {
if (details.pubkey != null) {
if (!Arrays.equals(proto.getPubkey().toByteArray(), details.pubkey.getPubKey()))
throw new PeerDiscoveryException("Public key mismatch");
byte[] hash = Utils.singleDigest(proto.getPeerSeeds().toByteArray());
byte[] hash = Sha256Hash.calcHashBytes(proto.getPeerSeeds().toByteArray());
details.pubkey.verifyOrThrow(hash, proto.getSignature().toByteArray());
}
PeerSeedProtos.PeerSeeds seeds = PeerSeedProtos.PeerSeeds.parseFrom(proto.getPeerSeeds());

View File

@ -1223,7 +1223,7 @@ public class Script {
case OP_SHA256:
if (stack.size() < 1)
throw new ScriptException("Attempted OP_SHA256 on an empty stack");
stack.add(Utils.singleDigest(stack.pollLast()));
stack.add(Sha256Hash.calcHashBytes(stack.pollLast()));
break;
case OP_HASH160:
if (stack.size() < 1)
@ -1233,7 +1233,7 @@ public class Script {
case OP_HASH256:
if (stack.size() < 1)
throw new ScriptException("Attempted OP_SHA256 on an empty stack");
stack.add(Utils.doubleDigest(stack.pollLast()));
stack.add(Sha256Hash.calcDoubleHashBytes(stack.pollLast()));
break;
case OP_CODESEPARATOR:
lastCodeSepLocation = chunk.getStartLocationInProgram() + 1;

View File

@ -339,11 +339,11 @@ public class ChannelConnectionTest extends TestWithWallet {
pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster);
pair.server.connectionOpen();
pair.server.receiveMessage(Protos.TwoWayChannelMessage.newBuilder()
.setType(MessageType.CLIENT_VERSION)
.setClientVersion(Protos.ClientVersion.newBuilder()
.setPreviousChannelContractHash(ByteString.copyFrom(Utils.singleDigest(new byte[]{0x03})))
.setMajor(CLIENT_MAJOR_VERSION).setMinor(42))
.build());
.setType(MessageType.CLIENT_VERSION)
.setClientVersion(Protos.ClientVersion.newBuilder()
.setPreviousChannelContractHash(ByteString.copyFrom(Sha256Hash.calcHashBytes(new byte[] { 0x03 })))
.setMajor(CLIENT_MAJOR_VERSION).setMinor(42))
.build());
pair.serverRecorder.checkNextMsg(MessageType.SERVER_VERSION);
pair.serverRecorder.checkNextMsg(MessageType.INITIATE);

View File

@ -39,7 +39,7 @@ import static org.junit.Assert.*;
public class DeterministicKeyChainTest {
private DeterministicKeyChain chain;
private final byte[] ENTROPY = Utils.singleDigest("don't use a string seed like this in real life".getBytes());
private final byte[] ENTROPY = Sha256Hash.calcHashBytes("don't use a string seed like this in real life".getBytes());
@Before
public void setup() {

View File

@ -64,7 +64,7 @@ public class KeyChainGroupTest {
}
private MarriedKeyChain createMarriedKeyChain() {
byte[] entropy = Utils.singleDigest("don't use a seed like this in real life".getBytes());
byte[] entropy = Sha256Hash.calcHashBytes("don't use a seed like this in real life".getBytes());
DeterministicSeed seed = new DeterministicSeed(entropy, "", MnemonicCode.BIP39_STANDARDISATION_TIME_SECS);
MarriedKeyChain chain = MarriedKeyChain.builder()
.seed(seed)

View File

@ -101,7 +101,7 @@ public class BuildCheckpoints {
private static void writeBinaryCheckpoints(TreeMap<Integer, StoredBlock> checkpoints, File file) throws Exception {
final FileOutputStream fileOutputStream = new FileOutputStream(file, false);
MessageDigest digest = Utils.newSha256Digest();
MessageDigest digest = Sha256Hash.newDigest();
final DigestOutputStream digestOutputStream = new DigestOutputStream(fileOutputStream, digest);
digestOutputStream.on(false);
final DataOutputStream dataOutputStream = new DataOutputStream(digestOutputStream);