diff --git a/core/src/main/java/org/bitcoinj/core/Base58.java b/core/src/main/java/org/bitcoinj/core/Base58.java
index 6ec2c47ac..9718aa3f7 100644
--- a/core/src/main/java/org/bitcoinj/core/Base58.java
+++ b/core/src/main/java/org/bitcoinj/core/Base58.java
@@ -156,7 +156,7 @@ public class Base58 {
}
public static BigInteger decodeToBigInteger(String input) throws AddressFormatException {
- return new BigInteger(1, decode(input));
+ return Utils.bytesToBigInteger(decode(input));
}
/**
diff --git a/core/src/main/java/org/bitcoinj/core/ECKey.java b/core/src/main/java/org/bitcoinj/core/ECKey.java
index 4d089abec..75250cf15 100644
--- a/core/src/main/java/org/bitcoinj/core/ECKey.java
+++ b/core/src/main/java/org/bitcoinj/core/ECKey.java
@@ -212,7 +212,7 @@ public class ECKey implements EncryptableItem {
* public key is compressed.
*/
public static ECKey fromPrivate(byte[] privKeyBytes) {
- return fromPrivate(new BigInteger(1, privKeyBytes));
+ return fromPrivate(Utils.bytesToBigInteger(privKeyBytes));
}
/**
@@ -220,7 +220,7 @@ public class ECKey implements EncryptableItem {
* @param compressed Determines whether the resulting ECKey will use a compressed encoding for the public key.
*/
public static ECKey fromPrivate(byte[] privKeyBytes, boolean compressed) {
- return fromPrivate(new BigInteger(1, privKeyBytes), compressed);
+ return fromPrivate(Utils.bytesToBigInteger(privKeyBytes), compressed);
}
/**
@@ -241,7 +241,7 @@ public class ECKey implements EncryptableItem {
public static ECKey fromPrivateAndPrecalculatedPublic(byte[] priv, byte[] pub) {
checkNotNull(priv);
checkNotNull(pub);
- return new ECKey(new BigInteger(1, priv), new LazyECPoint(CURVE.getCurve(), pub));
+ return new ECKey(Utils.bytesToBigInteger(priv), new LazyECPoint(CURVE.getCurve(), pub));
}
/**
@@ -339,7 +339,7 @@ public class ECKey implements EncryptableItem {
/**
* Returns public key bytes from the given private key. To convert a byte array into a BigInteger,
- * use {@code new BigInteger(1, bytes);}
+ * use {@link Utils#bytesToBigInteger(byte[])}
*/
public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean compressed) {
ECPoint point = publicPointFromPrivate(privKey);
@@ -348,7 +348,7 @@ public class ECKey implements EncryptableItem {
/**
* Returns public key point from the given private key. To convert a byte array into a BigInteger,
- * use {@code new BigInteger(1, bytes);}
+ * use {@link Utils#bytesToBigInteger(byte[])}
*/
public static ECPoint publicPointFromPrivate(BigInteger privKey) {
/*
@@ -721,7 +721,7 @@ public class ECKey implements EncryptableItem {
"Input is of wrong version");
byte[] privbits = ((ASN1OctetString) seq.getObjectAt(1)).getOctets();
- BigInteger privkey = new BigInteger(1, privbits);
+ BigInteger privkey = Utils.bytesToBigInteger(privbits);
ASN1TaggedObject pubkey = (ASN1TaggedObject) seq.getObjectAt(3);
checkArgument(pubkey.getTagNo() == 1, "Input has 'publicKey' with bad tag number");
@@ -799,8 +799,8 @@ public class ECKey implements EncryptableItem {
// 0x1D = second key with even y, 0x1E = second key with odd y
if (header < 27 || header > 34)
throw new SignatureException("Header byte out of range: " + header);
- BigInteger r = new BigInteger(1, Arrays.copyOfRange(signatureEncoded, 1, 33));
- BigInteger s = new BigInteger(1, Arrays.copyOfRange(signatureEncoded, 33, 65));
+ BigInteger r = Utils.bytesToBigInteger(Arrays.copyOfRange(signatureEncoded, 1, 33));
+ BigInteger s = Utils.bytesToBigInteger(Arrays.copyOfRange(signatureEncoded, 33, 65));
ECDSASignature sig = new ECDSASignature(r, s);
byte[] messageBytes = formatMessageForSigning(message);
// Note that the C++ code doesn't actually seem to specify any character encoding. Presumably it's whatever
diff --git a/core/src/main/java/org/bitcoinj/core/Sha256Hash.java b/core/src/main/java/org/bitcoinj/core/Sha256Hash.java
index f2c40c844..61a03e291 100644
--- a/core/src/main/java/org/bitcoinj/core/Sha256Hash.java
+++ b/core/src/main/java/org/bitcoinj/core/Sha256Hash.java
@@ -244,7 +244,7 @@ public class Sha256Hash implements Serializable, Comparable {
* Returns the bytes interpreted as a positive integer.
*/
public BigInteger toBigInteger() {
- return new BigInteger(1, bytes);
+ return Utils.bytesToBigInteger(bytes);
}
/**
diff --git a/core/src/main/java/org/bitcoinj/core/StoredBlock.java b/core/src/main/java/org/bitcoinj/core/StoredBlock.java
index 5ce660d73..b9588ee35 100644
--- a/core/src/main/java/org/bitcoinj/core/StoredBlock.java
+++ b/core/src/main/java/org/bitcoinj/core/StoredBlock.java
@@ -142,7 +142,7 @@ public class StoredBlock {
public static StoredBlock deserializeCompact(NetworkParameters params, ByteBuffer buffer) throws ProtocolException {
byte[] chainWorkBytes = new byte[StoredBlock.CHAIN_WORK_BYTES];
buffer.get(chainWorkBytes);
- BigInteger chainWork = new BigInteger(1, chainWorkBytes);
+ BigInteger chainWork = Utils.bytesToBigInteger(chainWorkBytes);
int height = buffer.getInt(); // +4 bytes
byte[] header = new byte[Block.HEADER_SIZE + 1]; // Extra byte for the 00 transactions length.
buffer.get(header, 0, Block.HEADER_SIZE);
diff --git a/core/src/main/java/org/bitcoinj/core/Utils.java b/core/src/main/java/org/bitcoinj/core/Utils.java
index 2f2297c81..bdc0717b5 100644
--- a/core/src/main/java/org/bitcoinj/core/Utils.java
+++ b/core/src/main/java/org/bitcoinj/core/Utils.java
@@ -76,6 +76,7 @@ public class Utils {
* Otherwise the representation is not minimal.
* For example, if the sign bit is 0000_0000, then the representation is not minimal due to the rightmost zero.
*
+ * This is the antagonist to {@link #bytesToBigInteger(byte[])}.
* @param b the integer to format into a byte array
* @param numBytes the desired size of the resulting byte array
* @return numBytes byte long array.
@@ -94,6 +95,17 @@ public class Utils {
return dest;
}
+ /**
+ * Converts an array of bytes into a positive BigInteger. This is the antagonist to
+ * {@link #bigIntegerToBytes(BigInteger, int)}.
+ *
+ * @param bytes to convert into a BigInteger
+ * @return the converted BigInteger
+ */
+ public static BigInteger bytesToBigInteger(byte[] bytes) {
+ return new BigInteger(1, bytes);
+ }
+
/** Write 2 bytes to the byte array (starting at the offset) as unsigned 16-bit integer in little endian format. */
public static void uint16ToByteArrayLE(int val, byte[] out, int offset) {
out[offset] = (byte) (0xFF & val);
diff --git a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java
index 45fcee64f..ba8f98c57 100644
--- a/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java
+++ b/core/src/main/java/org/bitcoinj/crypto/BIP38PrivateKey.java
@@ -155,7 +155,7 @@ public class BIP38PrivateKey extends PrefixedChecksummedBytes {
checkState(hashBytes.length == 40);
passFactorBytes = Sha256Hash.hashTwice(hashBytes);
}
- BigInteger passFactor = new BigInteger(1, passFactorBytes);
+ BigInteger passFactor = Utils.bytesToBigInteger(passFactorBytes);
ECKey k = ECKey.fromPrivate(passFactor, true);
byte[] salt = Bytes.concat(addressHash, ownerEntropy);
@@ -181,7 +181,7 @@ public class BIP38PrivateKey extends PrefixedChecksummedBytes {
byte[] seed = Bytes.concat(decrypted1, Arrays.copyOfRange(decrypted2, 8, 16));
checkState(seed.length == 24);
- BigInteger seedFactor = new BigInteger(1, Sha256Hash.hashTwice(seed));
+ BigInteger seedFactor = Utils.bytesToBigInteger(Sha256Hash.hashTwice(seed));
checkState(passFactor.signum() >= 0);
checkState(seedFactor.signum() >= 0);
BigInteger priv = passFactor.multiply(seedFactor).mod(ECKey.CURVE.getN());
diff --git a/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java b/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java
index f1fe3a87f..409bb2786 100644
--- a/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java
+++ b/core/src/main/java/org/bitcoinj/crypto/DeterministicKey.java
@@ -394,7 +394,7 @@ public class DeterministicKey extends ECKey {
if (decryptedKey.length != 32)
throw new KeyCrypterException.InvalidCipherText(
"Decrypted key must be 32 bytes long, but is " + decryptedKey.length);
- return new BigInteger(1, decryptedKey);
+ return Utils.bytesToBigInteger(decryptedKey);
}
// Otherwise we don't have it, but maybe we can figure it out from our parents. Walk up the tree looking for
// the first key that has some encrypted private key data.
@@ -431,7 +431,7 @@ public class DeterministicKey extends ECKey {
private BigInteger derivePrivateKeyDownwards(DeterministicKey cursor, byte[] parentalPrivateKeyBytes) {
DeterministicKey downCursor = new DeterministicKey(cursor.childNumberPath, cursor.chainCode,
- cursor.pub, new BigInteger(1, parentalPrivateKeyBytes), cursor.parent);
+ cursor.pub, Utils.bytesToBigInteger(parentalPrivateKeyBytes), cursor.parent);
// Now we have to rederive the keys along the path back to ourselves. That path can be found by just truncating
// our path with the length of the parents path.
List path = childNumberPath.subList(cursor.getPath().size(), childNumberPath.size());
@@ -576,7 +576,7 @@ public class DeterministicKey extends ECKey {
if (pub) {
return new DeterministicKey(path, chainCode, new LazyECPoint(ECKey.CURVE.getCurve(), data), parent, depth, parentFingerprint);
} else {
- return new DeterministicKey(path, chainCode, new BigInteger(1, data), parent, depth, parentFingerprint);
+ return new DeterministicKey(path, chainCode, Utils.bytesToBigInteger(data), parent, depth, parentFingerprint);
}
}
diff --git a/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java b/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java
index b656c3b6a..357340301 100644
--- a/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java
+++ b/core/src/main/java/org/bitcoinj/crypto/HDKeyDerivation.java
@@ -81,7 +81,7 @@ public final class HDKeyDerivation {
* @throws HDDerivationException if privKeyBytes is invalid (not between 0 and n inclusive).
*/
public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException {
- BigInteger priv = new BigInteger(1, privKeyBytes);
+ BigInteger priv = Utils.bytesToBigInteger(privKeyBytes);
assertNonZero(priv, "Generated master key is invalid.");
assertLessThanN(priv, "Generated master key is invalid.");
return new DeterministicKey(HDPath.m(), chainCode, priv, null);
@@ -137,7 +137,7 @@ public final class HDKeyDerivation {
throws HDDerivationException {
RawKeyBytes rawKey = deriveChildKeyBytesFromPrivate(parent, childNumber);
return new DeterministicKey(parent.getPath().extend(childNumber), rawKey.chainCode,
- new BigInteger(1, rawKey.keyBytes), parent);
+ Utils.bytesToBigInteger(rawKey.keyBytes), parent);
}
public static RawKeyBytes deriveChildKeyBytesFromPrivate(DeterministicKey parent,
@@ -156,7 +156,7 @@ public final class HDKeyDerivation {
checkState(i.length == 64, i.length);
byte[] il = Arrays.copyOfRange(i, 0, 32);
byte[] chainCode = Arrays.copyOfRange(i, 32, 64);
- BigInteger ilInt = new BigInteger(1, il);
+ BigInteger ilInt = Utils.bytesToBigInteger(il);
assertLessThanN(ilInt, "Illegal derived key: I_L >= n");
final BigInteger priv = parent.getPrivKey();
BigInteger ki = priv.add(ilInt).mod(ECKey.CURVE.getN());
@@ -187,7 +187,7 @@ public final class HDKeyDerivation {
checkState(i.length == 64, i.length);
byte[] il = Arrays.copyOfRange(i, 0, 32);
byte[] chainCode = Arrays.copyOfRange(i, 32, 64);
- BigInteger ilInt = new BigInteger(1, il);
+ BigInteger ilInt = Utils.bytesToBigInteger(il);
assertLessThanN(ilInt, "Illegal derived key: I_L >= n");
final BigInteger N = ECKey.CURVE.getN();
diff --git a/core/src/main/java/org/bitcoinj/wallet/DeterministicKeyChain.java b/core/src/main/java/org/bitcoinj/wallet/DeterministicKeyChain.java
index d20912435..c5bea7524 100644
--- a/core/src/main/java/org/bitcoinj/wallet/DeterministicKeyChain.java
+++ b/core/src/main/java/org/bitcoinj/wallet/DeterministicKeyChain.java
@@ -889,7 +889,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
boolean isMarried = !isFollowingKey && !chains.isEmpty() && chains.get(chains.size() - 1).isFollowing();
// If this has a private key but no seed, then all we know is the spending key H
if (seed == null && key.hasSecretBytes()) {
- DeterministicKey accountKey = new DeterministicKey(immutablePath, chainCode, pubkey, new BigInteger(1, key.getSecretBytes().toByteArray()), null);
+ DeterministicKey accountKey = new DeterministicKey(immutablePath, chainCode, pubkey, Utils.bytesToBigInteger(key.getSecretBytes().toByteArray()), null);
accountKey.setCreationTimeSeconds(key.getCreationTimestamp() / 1000);
chain = factory.makeSpendingKeyChain(accountKey, isMarried, outputScriptType);
isSpendingKey = true;
@@ -918,7 +918,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
DeterministicKey detkey;
if (key.hasSecretBytes()) {
// Not encrypted: private key is available.
- final BigInteger priv = new BigInteger(1, key.getSecretBytes().toByteArray());
+ final BigInteger priv = Utils.bytesToBigInteger(key.getSecretBytes().toByteArray());
detkey = new DeterministicKey(immutablePath, chainCode, pubkey, priv, parent);
} else {
if (key.hasEncryptedData()) {
diff --git a/core/src/test/java/org/bitcoinj/core/Base58DecodeToBigIntegerTest.java b/core/src/test/java/org/bitcoinj/core/Base58DecodeToBigIntegerTest.java
index 4d7a4b80a..0efb8faaa 100644
--- a/core/src/test/java/org/bitcoinj/core/Base58DecodeToBigIntegerTest.java
+++ b/core/src/test/java/org/bitcoinj/core/Base58DecodeToBigIntegerTest.java
@@ -28,6 +28,6 @@ public class Base58DecodeToBigIntegerTest {
@Test
public void testDecodeToBigInteger() {
byte[] input = Base58.decode("129");
- assertEquals(new BigInteger(1, input), Base58.decodeToBigInteger("129"));
+ assertEquals(Utils.bytesToBigInteger(input), Base58.decodeToBigInteger("129"));
}
}
diff --git a/core/src/test/java/org/bitcoinj/core/ECKeyTest.java b/core/src/test/java/org/bitcoinj/core/ECKeyTest.java
index bf4546a8e..455157cfe 100644
--- a/core/src/test/java/org/bitcoinj/core/ECKeyTest.java
+++ b/core/src/test/java/org/bitcoinj/core/ECKeyTest.java
@@ -97,7 +97,7 @@ public class ECKeyTest {
public void testSignatures() throws Exception {
// Test that we can construct an ECKey from a private key (deriving the public from the private), then signing
// a message with it.
- BigInteger privkey = new BigInteger(1, HEX.decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
+ BigInteger privkey = Utils.bytesToBigInteger(HEX.decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
ECKey key = ECKey.fromPrivate(privkey);
byte[] output = key.sign(Sha256Hash.ZERO_HASH).encodeToDER();
assertTrue(key.verify(Sha256Hash.ZERO_HASH.getBytes(), output));
diff --git a/core/src/test/java/org/bitcoinj/core/UtilsTest.java b/core/src/test/java/org/bitcoinj/core/UtilsTest.java
index 47f53ff14..b41ff2920 100644
--- a/core/src/test/java/org/bitcoinj/core/UtilsTest.java
+++ b/core/src/test/java/org/bitcoinj/core/UtilsTest.java
@@ -20,6 +20,7 @@ package org.bitcoinj.core;
import java.math.BigInteger;
import java.util.Date;
+import java.util.Random;
import org.junit.Test;
@@ -54,6 +55,20 @@ public class UtilsTest {
assertEquals("2014-11-16T10:54:33Z", Utils.dateTimeFormat(new Date(1416135273781L)));
}
+ @Test
+ public void bigIntegerToBytes_roundTrip() {
+ int ITERATIONS = 100;
+ int LENGTH = 32;
+ Random rnd = new Random();
+ byte[] bytes = new byte[LENGTH];
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ rnd.nextBytes(bytes);
+ BigInteger bi = Utils.bytesToBigInteger(bytes);
+ assertArrayEquals(Utils.HEX.encode(bytes), bytes, Utils.bigIntegerToBytes(bi, LENGTH));
+ }
+ }
+
@Test(expected = IllegalArgumentException.class)
public void bigIntegerToBytes_convertNegativeNumber() {
BigInteger b = BigInteger.valueOf(-1);
diff --git a/wallettool/src/main/java/org/bitcoinj/wallettool/WalletTool.java b/wallettool/src/main/java/org/bitcoinj/wallettool/WalletTool.java
index 5bdb86221..7a5d93b17 100644
--- a/wallettool/src/main/java/org/bitcoinj/wallettool/WalletTool.java
+++ b/wallettool/src/main/java/org/bitcoinj/wallettool/WalletTool.java
@@ -1130,7 +1130,7 @@ public class WalletTool implements Callable {
System.err.println("Could not understand --privkey as either WIF, hex or base58: " + privKeyStr);
return;
}
- key = ECKey.fromPrivate(new BigInteger(1, decode));
+ key = ECKey.fromPrivate(Utils.bytesToBigInteger(decode));
}
if (pubKeyStr != null) {
// Give the user a hint.