mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-12 10:15:52 +00:00
Upgrade to Bouncy Castle 1.50. Patch from Peter Dettman. Resolves issue 497.
This commit is contained in:
parent
e372aa4430
commit
feba332e6e
@ -155,7 +155,7 @@
|
|||||||
<urn>com.google.protobuf:protobuf-java:2.5.0:jar:null:compile:a10732c76bfacdbd633a7eb0f7968b1059a65dfa</urn>
|
<urn>com.google.protobuf:protobuf-java:2.5.0:jar:null:compile:a10732c76bfacdbd633a7eb0f7968b1059a65dfa</urn>
|
||||||
<urn>com.h2database:h2:1.3.167:jar:null:compile:d3867d586f087e53eb12fc65e5693d8ee9a5da17</urn>
|
<urn>com.h2database:h2:1.3.167:jar:null:compile:d3867d586f087e53eb12fc65e5693d8ee9a5da17</urn>
|
||||||
<urn>com.lambdaworks:scrypt:1.3.3:jar:null:compile:06d6813de41e177189e1722717979b4fb5454b1d</urn>
|
<urn>com.lambdaworks:scrypt:1.3.3:jar:null:compile:06d6813de41e177189e1722717979b4fb5454b1d</urn>
|
||||||
<urn>com.madgag:sc-light-jdk15on:1.47.0.2:jar:null:compile:d5c98671cc97fa0d928be1c7eb5edd3fb95d3234</urn>
|
<urn>com.madgag.spongycastle:core:1.50.0.0:jar:null:compile:13e93b00ec9790315debd61fa25ab6a47d3a1c52</urn>
|
||||||
<urn>net.jcip:jcip-annotations:1.0:jar:null:compile:afba4942caaeaf46aab0b976afd57cc7c181467e</urn>
|
<urn>net.jcip:jcip-annotations:1.0:jar:null:compile:afba4942caaeaf46aab0b976afd57cc7c181467e</urn>
|
||||||
<urn>org.slf4j:slf4j-api:1.7.6:jar:null:compile:562424e36df3d2327e8e9301a76027fca17d54ea</urn>
|
<urn>org.slf4j:slf4j-api:1.7.6:jar:null:compile:562424e36df3d2327e8e9301a76027fca17d54ea</urn>
|
||||||
<urn>org.slf4j:slf4j-jdk14:1.7.6:jar:null:runtime:1a3301a32ea7d90c3d33e9d60edbfdc9589fc748</urn>
|
<urn>org.slf4j:slf4j-jdk14:1.7.6:jar:null:runtime:1a3301a32ea7d90c3d33e9d60edbfdc9589fc748</urn>
|
||||||
@ -242,9 +242,9 @@
|
|||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.madgag</groupId>
|
<groupId>com.madgag.spongycastle</groupId>
|
||||||
<artifactId>sc-light-jdk15on</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>1.47.0.2</version>
|
<version>1.50.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.protobuf</groupId>
|
<groupId>com.google.protobuf</groupId>
|
||||||
|
@ -30,9 +30,11 @@ import org.spongycastle.asn1.sec.SECNamedCurves;
|
|||||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||||
import org.spongycastle.asn1.x9.X9IntegerConverter;
|
import org.spongycastle.asn1.x9.X9IntegerConverter;
|
||||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||||
|
import org.spongycastle.crypto.digests.SHA256Digest;
|
||||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||||
import org.spongycastle.crypto.params.*;
|
import org.spongycastle.crypto.params.*;
|
||||||
import org.spongycastle.crypto.signers.ECDSASigner;
|
import org.spongycastle.crypto.signers.ECDSASigner;
|
||||||
|
import org.spongycastle.crypto.signers.HMacDSAKCalculator;
|
||||||
import org.spongycastle.math.ec.ECAlgorithms;
|
import org.spongycastle.math.ec.ECAlgorithms;
|
||||||
import org.spongycastle.math.ec.ECCurve;
|
import org.spongycastle.math.ec.ECCurve;
|
||||||
import org.spongycastle.math.ec.ECPoint;
|
import org.spongycastle.math.ec.ECPoint;
|
||||||
@ -125,19 +127,11 @@ public class ECKey implements Serializable {
|
|||||||
ECPrivateKeyParameters privParams = (ECPrivateKeyParameters) keypair.getPrivate();
|
ECPrivateKeyParameters privParams = (ECPrivateKeyParameters) keypair.getPrivate();
|
||||||
ECPublicKeyParameters pubParams = (ECPublicKeyParameters) keypair.getPublic();
|
ECPublicKeyParameters pubParams = (ECPublicKeyParameters) keypair.getPublic();
|
||||||
priv = privParams.getD();
|
priv = privParams.getD();
|
||||||
// Unfortunately Bouncy Castle does not let us explicitly change a point to be compressed, even though it
|
pub = pubParams.getQ().getEncoded(true);
|
||||||
// could easily do so. We must re-build it here so the ECPoints withCompression flag can be set to true.
|
|
||||||
ECPoint uncompressed = pubParams.getQ();
|
|
||||||
ECPoint compressed = compressPoint(uncompressed);
|
|
||||||
pub = compressed.getEncoded();
|
|
||||||
|
|
||||||
creationTimeSeconds = Utils.currentTimeSeconds();
|
creationTimeSeconds = Utils.currentTimeSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ECPoint compressPoint(ECPoint uncompressed) {
|
|
||||||
return new ECPoint.Fp(CURVE.getCurve(), uncompressed.getX(), uncompressed.getY(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an ECKey from an ASN.1 encoded private key. These are produced by OpenSSL and stored by the Bitcoin
|
* Construct an ECKey from an ASN.1 encoded private key. These are produced by OpenSSL and stored by the Bitcoin
|
||||||
* reference implementation in its wallet. Note that this is slow because it requires an EC point multiply.
|
* reference implementation in its wallet. Note that this is slow because it requires an EC point multiply.
|
||||||
@ -252,9 +246,7 @@ public class ECKey implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean compressed) {
|
public static byte[] publicKeyFromPrivate(BigInteger privKey, boolean compressed) {
|
||||||
ECPoint point = CURVE.getG().multiply(privKey);
|
ECPoint point = CURVE.getG().multiply(privKey);
|
||||||
if (compressed)
|
return point.getEncoded(compressed);
|
||||||
point = compressPoint(point);
|
|
||||||
return point.getEncoded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the hash160 form of the public key (as seen in addresses). */
|
/** Gets the hash160 form of the public key (as seen in addresses). */
|
||||||
@ -485,7 +477,7 @@ public class ECKey implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ECDSASigner signer = new ECDSASigner();
|
ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
|
||||||
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKeyForSigning, CURVE);
|
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKeyForSigning, CURVE);
|
||||||
signer.init(true, privKey);
|
signer.init(true, privKey);
|
||||||
BigInteger[] components = signer.generateSignature(input.getBytes());
|
BigInteger[] components = signer.generateSignature(input.getBytes());
|
||||||
@ -781,11 +773,7 @@ public class ECKey implements Serializable {
|
|||||||
BigInteger srInv = rInv.multiply(sig.s).mod(n);
|
BigInteger srInv = rInv.multiply(sig.s).mod(n);
|
||||||
BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
|
BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
|
||||||
ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
|
ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
|
||||||
if (compressed) {
|
return new ECKey((byte[])null, q.getEncoded(compressed));
|
||||||
// We have to manually recompress the point as the compressed-ness gets lost when multiply() is used.
|
|
||||||
q = new ECPoint.Fp(curve, q.getX(), q.getY(), true);
|
|
||||||
}
|
|
||||||
return new ECKey((byte[])null, q.getEncoded());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decompress a compressed public key (x co-ord and low-bit of y-coord). */
|
/** Decompress a compressed public key (x co-ord and low-bit of y-coord). */
|
||||||
|
@ -61,7 +61,7 @@ public class DeterministicKey implements Serializable {
|
|||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.childNumberPath = childNumberPath;
|
this.childNumberPath = childNumberPath;
|
||||||
this.chainCode = Arrays.copyOf(chainCode, chainCode.length);
|
this.chainCode = Arrays.copyOf(chainCode, chainCode.length);
|
||||||
this.publicAsPoint = publicAsPoint == null ? null : HDUtils.compressedCopy(publicAsPoint);
|
this.publicAsPoint = publicAsPoint == null ? null : publicAsPoint.normalize();
|
||||||
this.privateAsFieldElement = privateKeyFieldElt;
|
this.privateAsFieldElement = privateKeyFieldElt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,13 +109,13 @@ public class DeterministicKey implements Serializable {
|
|||||||
ECPoint getPubPoint() {
|
ECPoint getPubPoint() {
|
||||||
if (publicAsPoint == null) {
|
if (publicAsPoint == null) {
|
||||||
checkNotNull(privateAsFieldElement);
|
checkNotNull(privateAsFieldElement);
|
||||||
publicAsPoint = ECKey.CURVE.getG().multiply(privateAsFieldElement);
|
publicAsPoint = ECKey.CURVE.getG().multiply(privateAsFieldElement).normalize();
|
||||||
}
|
}
|
||||||
return HDUtils.compressedCopy(publicAsPoint);
|
return publicAsPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getPubKeyBytes() {
|
public byte[] getPubKeyBytes() {
|
||||||
return getPubPoint().getEncoded();
|
return getPubPoint().getEncoded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,9 +127,8 @@ public final class HDKeyDerivation {
|
|||||||
} else {
|
} else {
|
||||||
checkArgument(!childNumber.isPrivateDerivation(), "Can't use private derivation with public keys only.");
|
checkArgument(!childNumber.isPrivateDerivation(), "Can't use private derivation with public keys only.");
|
||||||
ECPoint Ki = ECKey.CURVE.getG().multiply(ilInt).add(parent.getPubPoint());
|
ECPoint Ki = ECKey.CURVE.getG().multiply(ilInt).add(parent.getPubPoint());
|
||||||
checkArgument(!Ki.equals(ECKey.CURVE.getCurve().getInfinity()),
|
checkArgument(!Ki.isInfinity(), "Illegal derived key: derived public key equals infinity.");
|
||||||
"Illegal derived key: derived public key equals infinity.");
|
keyBytes = Ki.getEncoded(true);
|
||||||
keyBytes = HDUtils.toCompressed(Ki.getEncoded());
|
|
||||||
}
|
}
|
||||||
return new RawKeyBytes(keyBytes, chainCode);
|
return new RawKeyBytes(keyBytes, chainCode);
|
||||||
}
|
}
|
||||||
|
@ -52,16 +52,8 @@ public final class HDUtils {
|
|||||||
return hmacSha512(createHmacSha512Digest(key), data);
|
return hmacSha512(createHmacSha512Digest(key), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ECPoint compressedCopy(ECPoint pubKPoint) {
|
|
||||||
return ECKey.CURVE.getCurve().createPoint(pubKPoint.getX().toBigInteger(), pubKPoint.getY().toBigInteger(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ECPoint toUncompressed(ECPoint pubKPoint) {
|
|
||||||
return ECKey.CURVE.getCurve().createPoint(pubKPoint.getX().toBigInteger(), pubKPoint.getY().toBigInteger(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static byte[] toCompressed(byte[] uncompressedPoint) {
|
static byte[] toCompressed(byte[] uncompressedPoint) {
|
||||||
return compressedCopy(ECKey.CURVE.getCurve().decodePoint(uncompressedPoint)).getEncoded();
|
return ECKey.CURVE.getCurve().decodePoint(uncompressedPoint).getEncoded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] longTo4ByteArray(long n) {
|
static byte[] longTo4ByteArray(long n) {
|
||||||
@ -71,7 +63,7 @@ public final class HDUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static byte[] getBytes(ECPoint pubKPoint) {
|
static byte[] getBytes(ECPoint pubKPoint) {
|
||||||
return compressedCopy(pubKPoint).getEncoded();
|
return pubKPoint.getEncoded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImmutableList<ChildNumber> append(ImmutableList<ChildNumber> path, ChildNumber childNumber) {
|
static ImmutableList<ChildNumber> append(ImmutableList<ChildNumber> path, ChildNumber childNumber) {
|
||||||
|
@ -37,6 +37,7 @@ import org.junit.Test;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.crypto.params.KeyParameter;
|
import org.spongycastle.crypto.params.KeyParameter;
|
||||||
|
import org.spongycastle.util.encoders.DecoderException;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -424,8 +425,11 @@ public class ECKeyTest {
|
|||||||
sig.append((char)c);
|
sig.append((char)c);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
assertFalse(TransactionSignature.isEncodingCanonical(Hex.decode(sig.toString())));
|
final String sigStr = sig.toString();
|
||||||
} catch (StringIndexOutOfBoundsException e) { } // Expected for non-hex strings in the JSON that we should ignore
|
assertFalse(TransactionSignature.isEncodingCanonical(Hex.decode(sigStr)));
|
||||||
|
} catch (DecoderException e) {
|
||||||
|
// Expected for non-hex strings in the JSON that we should ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
|
@ -1618,6 +1618,7 @@ public class FullBlockTestGenerator {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte uniquenessCounter = 0;
|
||||||
private Block createNextBlock(Block baseBlock, int nextBlockHeight, TransactionOutPointWithValue prevOut,
|
private Block createNextBlock(Block baseBlock, int nextBlockHeight, TransactionOutPointWithValue prevOut,
|
||||||
BigInteger additionalCoinbaseValue) throws ScriptException {
|
BigInteger additionalCoinbaseValue) throws ScriptException {
|
||||||
Integer height = blockToHeightMap.get(baseBlock.getHash());
|
Integer height = blockToHeightMap.get(baseBlock.getHash());
|
||||||
@ -1634,7 +1635,7 @@ public class FullBlockTestGenerator {
|
|||||||
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(1),
|
t.addOutput(new TransactionOutput(params, t, BigInteger.valueOf(1),
|
||||||
ScriptBuilder.createOutputScript(new ECKey(null, coinbaseOutKeyPubKey)).getProgram()));
|
ScriptBuilder.createOutputScript(new ECKey(null, coinbaseOutKeyPubKey)).getProgram()));
|
||||||
// Spendable output
|
// Spendable output
|
||||||
t.addOutput(new TransactionOutput(params, t, BigInteger.ZERO, new byte[] {OP_1}));
|
t.addOutput(new TransactionOutput(params, t, BigInteger.ZERO, new byte[] {OP_1, uniquenessCounter++}));
|
||||||
addOnlyInputToTransaction(t, prevOut);
|
addOnlyInputToTransaction(t, prevOut);
|
||||||
block.addTransaction(t);
|
block.addTransaction(t);
|
||||||
block.solve();
|
block.solve();
|
||||||
|
@ -19,8 +19,6 @@ package com.google.bitcoin.core;
|
|||||||
|
|
||||||
import com.google.bitcoin.core.Transaction.SigHash;
|
import com.google.bitcoin.core.Transaction.SigHash;
|
||||||
import com.google.bitcoin.core.Wallet.SendRequest;
|
import com.google.bitcoin.core.Wallet.SendRequest;
|
||||||
import com.google.bitcoin.wallet.DefaultCoinSelector;
|
|
||||||
import com.google.bitcoin.wallet.RiskAnalysis;
|
|
||||||
import com.google.bitcoin.crypto.KeyCrypter;
|
import com.google.bitcoin.crypto.KeyCrypter;
|
||||||
import com.google.bitcoin.crypto.KeyCrypterException;
|
import com.google.bitcoin.crypto.KeyCrypterException;
|
||||||
import com.google.bitcoin.crypto.KeyCrypterScrypt;
|
import com.google.bitcoin.crypto.KeyCrypterScrypt;
|
||||||
@ -30,9 +28,7 @@ import com.google.bitcoin.utils.MockTransactionBroadcaster;
|
|||||||
import com.google.bitcoin.utils.TestUtils;
|
import com.google.bitcoin.utils.TestUtils;
|
||||||
import com.google.bitcoin.utils.TestWithWallet;
|
import com.google.bitcoin.utils.TestWithWallet;
|
||||||
import com.google.bitcoin.utils.Threading;
|
import com.google.bitcoin.utils.Threading;
|
||||||
import com.google.bitcoin.wallet.KeyTimeCoinSelector;
|
import com.google.bitcoin.wallet.*;
|
||||||
import com.google.bitcoin.wallet.WalletFiles;
|
|
||||||
import com.google.bitcoin.wallet.WalletTransaction;
|
|
||||||
import com.google.bitcoin.wallet.WalletTransaction.Pool;
|
import com.google.bitcoin.wallet.WalletTransaction.Pool;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@ -692,12 +688,12 @@ public class WalletTest extends TestWithWallet {
|
|||||||
final BigInteger value2 = Utils.toNanoCoins(2, 0);
|
final BigInteger value2 = Utils.toNanoCoins(2, 0);
|
||||||
// Give us three coins and make sure we have some change.
|
// Give us three coins and make sure we have some change.
|
||||||
sendMoneyToWallet(value.add(value2), AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
sendMoneyToWallet(value.add(value2), AbstractBlockChain.NewBlockType.BEST_CHAIN);
|
||||||
// The two transactions will have different hashes due to the lack of deterministic signing, but will be
|
|
||||||
// otherwise identical. Once deterministic signatures are implemented, this test will have to be tweaked.
|
|
||||||
final Address address = new ECKey().toAddress(params);
|
final Address address = new ECKey().toAddress(params);
|
||||||
Transaction send1 = checkNotNull(wallet.createSend(address, value2));
|
Transaction send1 = checkNotNull(wallet.createSend(address, value2));
|
||||||
Transaction send2 = checkNotNull(wallet.createSend(address, value2));
|
Transaction send2 = checkNotNull(wallet.createSend(address, value2));
|
||||||
send1 = roundTripTransaction(params, send1);
|
byte[] buf = send1.bitcoinSerialize();
|
||||||
|
buf[43] = 0; // Break the signature: bitcoinj won't check in SPV mode and this is easier than other mutations.
|
||||||
|
send1 = new Transaction(params, buf);
|
||||||
wallet.commitTx(send2);
|
wallet.commitTx(send2);
|
||||||
wallet.allowSpendingUnconfirmedTransactions();
|
wallet.allowSpendingUnconfirmedTransactions();
|
||||||
assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
|
assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
|
||||||
|
@ -10,7 +10,6 @@ import org.spongycastle.math.ec.ECCurve;
|
|||||||
import org.spongycastle.math.ec.ECPoint;
|
import org.spongycastle.math.ec.ECPoint;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -126,14 +125,11 @@ public class HDUtilsTest {
|
|||||||
for (String testpkStr : testPubKey) {
|
for (String testpkStr : testPubKey) {
|
||||||
byte[] testpk = Hex.decode(testpkStr);
|
byte[] testpk = Hex.decode(testpkStr);
|
||||||
|
|
||||||
BigInteger pubX = new BigInteger(1, Arrays.copyOfRange(testpk, 1, 33));
|
|
||||||
BigInteger pubY = new BigInteger(1, Arrays.copyOfRange(testpk, 33, 65));
|
|
||||||
|
|
||||||
ECPoint ptFlat = curve.createPoint(pubX, pubY, false); // 65
|
|
||||||
ECPoint ptComp = curve.createPoint(pubX, pubY, true); // 33
|
|
||||||
ECPoint uncompressed = HDUtils.toUncompressed(ptComp);
|
|
||||||
ECPoint recompressed = HDUtils.compressedCopy(uncompressed);
|
|
||||||
ECPoint orig = curve.decodePoint(testpk);
|
ECPoint orig = curve.decodePoint(testpk);
|
||||||
|
ECPoint ptFlat = curve.decodePoint(orig.getEncoded(false));
|
||||||
|
ECPoint ptComp = curve.decodePoint(ptFlat.getEncoded(true));
|
||||||
|
ECPoint uncompressed = curve.decodePoint(ptComp.getEncoded(false));
|
||||||
|
ECPoint recompressed = curve.decodePoint(uncompressed.getEncoded(true));
|
||||||
|
|
||||||
log.info("====================");
|
log.info("====================");
|
||||||
log.info("Flat: {}", asHexStr(ptFlat));
|
log.info("Flat: {}", asHexStr(ptFlat));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user