diff --git a/core/src/main/java/com/google/bitcoin/crypto/DeterministicKey.java b/core/src/main/java/com/google/bitcoin/crypto/DeterministicKey.java index 5585303c..00e33ad7 100644 --- a/core/src/main/java/com/google/bitcoin/crypto/DeterministicKey.java +++ b/core/src/main/java/com/google/bitcoin/crypto/DeterministicKey.java @@ -109,7 +109,7 @@ public class DeterministicKey implements Serializable { ECPoint getPubPoint() { if (publicAsPoint == null) { checkNotNull(privateAsFieldElement); - publicAsPoint = HDUtils.getEcParams().getG().multiply(privateAsFieldElement); + publicAsPoint = ECKey.CURVE.getG().multiply(privateAsFieldElement); } return HDUtils.compressedCopy(publicAsPoint); } diff --git a/core/src/main/java/com/google/bitcoin/crypto/HDKeyDerivation.java b/core/src/main/java/com/google/bitcoin/crypto/HDKeyDerivation.java index 32c03d0d..15280e18 100644 --- a/core/src/main/java/com/google/bitcoin/crypto/HDKeyDerivation.java +++ b/core/src/main/java/com/google/bitcoin/crypto/HDKeyDerivation.java @@ -16,6 +16,7 @@ package com.google.bitcoin.crypto; +import com.google.bitcoin.core.ECKey; import com.google.common.collect.ImmutableList; import org.spongycastle.crypto.macs.HMac; import org.spongycastle.math.ec.ECPoint; @@ -66,14 +67,14 @@ public final class HDKeyDerivation { */ public static DeterministicKey createMasterPrivKeyFromBytes( byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException { - BigInteger privateKeyFieldElt = HDUtils.toBigInteger(privKeyBytes); + BigInteger privateKeyFieldElt = new BigInteger(1, privKeyBytes); assertNonZero(privateKeyFieldElt, "Generated master key is invalid."); assertLessThanN(privateKeyFieldElt, "Generated master key is invalid."); return new DeterministicKey(ImmutableList.of(), chainCode, null, privateKeyFieldElt, null); } public static DeterministicKey createMasterPubKeyFromBytes(byte[] pubKeyBytes, byte[] chainCode) { - return new DeterministicKey(ImmutableList.of(), chainCode, HDUtils.getCurve().decodePoint(pubKeyBytes), null, null); + return new DeterministicKey(ImmutableList.of(), chainCode, ECKey.CURVE.getCurve().decodePoint(pubKeyBytes), null, null); } /** @@ -94,8 +95,8 @@ public final class HDKeyDerivation { return new DeterministicKey( HDUtils.append(parent.getChildNumberPath(), childNumber), rawKey.chainCode, - parent.hasPrivate() ? null : HDUtils.getCurve().decodePoint(rawKey.keyBytes), - parent.hasPrivate() ? HDUtils.toBigInteger(rawKey.keyBytes) : null, + parent.hasPrivate() ? null : ECKey.CURVE.getCurve().decodePoint(rawKey.keyBytes), + parent.hasPrivate() ? new BigInteger(1, rawKey.keyBytes) : null, parent); } @@ -115,18 +116,18 @@ public final class HDKeyDerivation { assert i.length == 64 : i.length; byte[] il = Arrays.copyOfRange(i, 0, 32); byte[] chainCode = Arrays.copyOfRange(i, 32, 64); - BigInteger ilInt = HDUtils.toBigInteger(il); + BigInteger ilInt = new BigInteger(1, il); assertLessThanN(ilInt, "Illegal derived key: I_L >= n"); byte[] keyBytes; final BigInteger privAsFieldElement = parent.getPrivAsFieldElement(); if (privAsFieldElement != null) { - BigInteger ki = privAsFieldElement.add(ilInt).mod(HDUtils.getEcParams().getN()); + BigInteger ki = privAsFieldElement.add(ilInt).mod(ECKey.CURVE.getN()); assertNonZero(ki, "Illegal derived key: derived private key equals 0."); keyBytes = ki.toByteArray(); } else { checkArgument(!childNumber.isPrivateDerivation(), "Can't use private derivation with public keys only."); - ECPoint Ki = HDUtils.getEcParams().getG().multiply(ilInt).add(parent.getPubPoint()); - checkArgument(!Ki.equals(HDUtils.getCurve().getInfinity()), + ECPoint Ki = ECKey.CURVE.getG().multiply(ilInt).add(parent.getPubPoint()); + checkArgument(!Ki.equals(ECKey.CURVE.getCurve().getInfinity()), "Illegal derived key: derived public key equals infinity."); keyBytes = HDUtils.toCompressed(Ki.getEncoded()); } @@ -138,7 +139,7 @@ public final class HDKeyDerivation { } private static void assertLessThanN(BigInteger integer, String errorMessage) { - checkArgument(integer.compareTo(HDUtils.getEcParams().getN()) < 0, errorMessage); + checkArgument(integer.compareTo(ECKey.CURVE.getN()) < 0, errorMessage); } private static class RawKeyBytes { diff --git a/core/src/main/java/com/google/bitcoin/crypto/HDUtils.java b/core/src/main/java/com/google/bitcoin/crypto/HDUtils.java index a8eff185..d7cdb9dd 100644 --- a/core/src/main/java/com/google/bitcoin/crypto/HDUtils.java +++ b/core/src/main/java/com/google/bitcoin/crypto/HDUtils.java @@ -16,17 +16,13 @@ package com.google.bitcoin.crypto; +import com.google.bitcoin.core.ECKey; import com.google.common.collect.ImmutableList; -import org.spongycastle.asn1.sec.SECNamedCurves; -import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.crypto.digests.SHA512Digest; import org.spongycastle.crypto.macs.HMac; -import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.KeyParameter; -import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECPoint; -import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.Arrays; @@ -37,14 +33,6 @@ public final class HDUtils { private HDUtils() { } - private static final ECDomainParameters ecParams; - - static { - // All clients must agree on the curve to use by agreement. Bitcoin uses secp256k1. - X9ECParameters params = SECNamedCurves.getByName("secp256k1"); - ecParams = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); - } - static HMac createHmacSha512Digest(byte[] key) { SHA512Digest digest = new SHA512Digest(); HMac hMac = new HMac(digest); @@ -64,24 +52,16 @@ public final class HDUtils { return hmacSha512(createHmacSha512Digest(key), data); } - static BigInteger toBigInteger(byte[] bytes) { - return new BigInteger(1, bytes); - } - static ECPoint compressedCopy(ECPoint pubKPoint) { - return getCurve().createPoint(pubKPoint.getX().toBigInteger(), pubKPoint.getY().toBigInteger(), true); - } - - static ECCurve getCurve() { - return getEcParams().getCurve(); + return ECKey.CURVE.getCurve().createPoint(pubKPoint.getX().toBigInteger(), pubKPoint.getY().toBigInteger(), true); } static ECPoint toUncompressed(ECPoint pubKPoint) { - return getCurve().createPoint(pubKPoint.getX().toBigInteger(), pubKPoint.getY().toBigInteger(), false); + return ECKey.CURVE.getCurve().createPoint(pubKPoint.getX().toBigInteger(), pubKPoint.getY().toBigInteger(), false); } static byte[] toCompressed(byte[] uncompressedPoint) { - return compressedCopy(getCurve().decodePoint(uncompressedPoint)).getEncoded(); + return compressedCopy(ECKey.CURVE.getCurve().decodePoint(uncompressedPoint)).getEncoded(); } static byte[] longTo4ByteArray(long n) { @@ -90,10 +70,6 @@ public final class HDUtils { return bytes; } - static ECDomainParameters getEcParams() { - return ecParams; - } - static byte[] getBytes(ECPoint pubKPoint) { return compressedCopy(pubKPoint).getEncoded(); } diff --git a/core/src/test/java/com/google/bitcoin/crypto/HDUtilsTest.java b/core/src/test/java/com/google/bitcoin/crypto/HDUtilsTest.java index c4ab9bc3..ce43ab89 100644 --- a/core/src/test/java/com/google/bitcoin/crypto/HDUtilsTest.java +++ b/core/src/test/java/com/google/bitcoin/crypto/HDUtilsTest.java @@ -1,5 +1,6 @@ package com.google.bitcoin.crypto; +import com.google.bitcoin.core.ECKey; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; @@ -119,14 +120,14 @@ public class HDUtilsTest { "04ed83704c95d829046f1ac27806211132102c34e9ac7ffa1b71110658e5b9d1bdedc416f5cefc1db0625cd0c75de8192d2b592d7e3b00bcfb4a0e860d880fd1fc", "042596957532fc37e40486b910802ff45eeaa924548c0e1c080ef804e523ec3ed3ed0a9004acf927666eee18b7f5e8ad72ff100a3bb710a577256fd7ec81eb1cb3"); - ECDomainParameters ecp = HDUtils.getEcParams(); + ECDomainParameters ecp = ECKey.CURVE; ECCurve curve = ecp.getCurve(); for (String testpkStr : testPubKey) { byte[] testpk = Hex.decode(testpkStr); - BigInteger pubX = HDUtils.toBigInteger(Arrays.copyOfRange(testpk, 1, 33)); - BigInteger pubY = HDUtils.toBigInteger(Arrays.copyOfRange(testpk, 33, 65)); + 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