mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-22 22:25:41 +01:00
Utils: add bytesToBigInteger() helper and use it
This is the antagonist to Utils.bigIntegerToBytes().
This commit is contained in:
parent
6ad636ccec
commit
435e39a841
13 changed files with 52 additions and 25 deletions
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -244,7 +244,7 @@ public class Sha256Hash implements Serializable, Comparable<Sha256Hash> {
|
|||
* Returns the bytes interpreted as a positive integer.
|
||||
*/
|
||||
public BigInteger toBigInteger() {
|
||||
return new BigInteger(1, bytes);
|
||||
return Utils.bytesToBigInteger(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -76,6 +76,7 @@ public class Utils {
|
|||
* Otherwise the representation is not minimal.
|
||||
* For example, if the sign bit is 0000_00<b>0</b>0, then the representation is not minimal due to the rightmost zero.
|
||||
* </p>
|
||||
* 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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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<ChildNumber> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1130,7 +1130,7 @@ public class WalletTool implements Callable<Integer> {
|
|||
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.
|
||||
|
|
Loading…
Add table
Reference in a new issue