mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-01-18 13:22:42 +01:00
ECKey: remove native interface to libsecp256k1
Of course, Bouncy Castle is still used.
This commit is contained in:
parent
576adf229b
commit
6686782ffa
@ -1,505 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoin;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static org.bitcoin.NativeSecp256k1Util.AssertFailException;
|
||||
import static org.bitcoin.NativeSecp256k1Util.assertEquals;
|
||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* <p>This class holds native methods to handle ECDSA verification.</p>
|
||||
*
|
||||
* <p>You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1</p>
|
||||
*
|
||||
* <p>To build secp256k1 for use with bitcoinj, run
|
||||
* `./configure --enable-jni --enable-experimental --enable-module-schnorr --enable-module-ecdh`
|
||||
* and `make` then copy `.libs/libsecp256k1.so` to your system library path
|
||||
* or point the JVM to the folder containing it with -Djava.library.path
|
||||
* </p>
|
||||
* @deprecated See https://github.com/bitcoinj/bitcoinj/issues/2267
|
||||
*/
|
||||
@Deprecated
|
||||
public class NativeSecp256k1 {
|
||||
|
||||
private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||
private static final Lock r = rwl.readLock();
|
||||
private static final Lock w = rwl.writeLock();
|
||||
private static ThreadLocal<ByteBuffer> nativeECDSABuffer = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* Verifies the given secp256k1 signature in native code. Calling when enabled == false is undefined (probably
|
||||
* library not loaded)
|
||||
*
|
||||
* @param data The data which was signed, must be exactly 32 bytes
|
||||
* @param signature The signature
|
||||
* @param pub The public key which did the signing
|
||||
* @return true if correct signature
|
||||
* @throws AssertFailException never thrown?
|
||||
*/
|
||||
public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException {
|
||||
checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < 520) {
|
||||
byteBuff = ByteBuffer.allocateDirect(520);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(data);
|
||||
byteBuff.put(signature);
|
||||
byteBuff.put(pub);
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1;
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 Create an ECDSA signature.
|
||||
*
|
||||
* @param data Message hash, 32 bytes
|
||||
* @param sec Secret key, 32 bytes
|
||||
* @return sig byte array of signature
|
||||
* @throws AssertFailException on bad signature length
|
||||
*/
|
||||
public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException {
|
||||
checkArgument(data.length == 32 && sec.length <= 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < 32 + 32) {
|
||||
byteBuff = ByteBuffer.allocateDirect(32 + 32);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(data);
|
||||
byteBuff.put(sec);
|
||||
|
||||
byte[][] retByteArray;
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] sigArr = retByteArray[0];
|
||||
int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(sigArr.length, sigLen, "Got bad signature length.");
|
||||
|
||||
return retVal == 0 ? new byte[0] : sigArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid
|
||||
*
|
||||
* @param seckey ECDSA Secret key, 32 bytes
|
||||
* @return true if valid, false if invalid
|
||||
*/
|
||||
public static boolean secKeyVerify(byte[] seckey) {
|
||||
checkArgument(seckey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < seckey.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(seckey.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(seckey);
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
return secp256k1_ec_seckey_verify(byteBuff, Secp256k1Context.getContext()) == 1;
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 Compute Pubkey - computes public key from secret key
|
||||
*
|
||||
* @param seckey ECDSA Secret key, 32 bytes
|
||||
* @return pubkey ECDSA Public key, 33 or 65 bytes
|
||||
* @throws AssertFailException if bad pubkey length
|
||||
*/
|
||||
// TODO add a 'compressed' arg
|
||||
public static byte[] computePubkey(byte[] seckey) throws AssertFailException {
|
||||
checkArgument(seckey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < seckey.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(seckey.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(seckey);
|
||||
|
||||
byte[][] retByteArray;
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] pubArr = retByteArray[0];
|
||||
int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(pubArr.length, pubLen, "Got bad pubkey length.");
|
||||
|
||||
return retVal == 0 ? new byte[0] : pubArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 Cleanup - This destroys the secp256k1 context object This should be called at the end of the program
|
||||
* for proper cleanup of the context.
|
||||
*/
|
||||
public static synchronized void cleanup() {
|
||||
w.lock();
|
||||
try {
|
||||
secp256k1_destroy_context(Secp256k1Context.getContext());
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone context
|
||||
*
|
||||
* @return context reference
|
||||
*/
|
||||
public static long cloneContext() {
|
||||
r.lock();
|
||||
try {
|
||||
return secp256k1_ctx_clone(Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param privkey 32-byte seckey
|
||||
* @return The tweaked private key
|
||||
* @throws AssertFailException assertion failure
|
||||
*/
|
||||
public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException {
|
||||
checkArgument(privkey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(privkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_privkey_tweak_mul(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] privArr = retByteArray[0];
|
||||
|
||||
int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(privArr.length, privLen, "Got bad pubkey length.");
|
||||
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return privArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param privkey 32-byte seckey
|
||||
* @return The tweaked private key
|
||||
* @throws AssertFailException assertion failure
|
||||
*/
|
||||
public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException {
|
||||
checkArgument(privkey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(privkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_privkey_tweak_add(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] privArr = retByteArray[0];
|
||||
|
||||
int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(privArr.length, privLen, "Got bad pubkey length.");
|
||||
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return privArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param pubkey 32-byte seckey
|
||||
* @return The tweaked private key
|
||||
* @throws AssertFailException assertion failure
|
||||
*/
|
||||
public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException {
|
||||
checkArgument(pubkey.length == 33 || pubkey.length == 65);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(pubkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_pubkey_tweak_add(byteBuff, Secp256k1Context.getContext(), pubkey.length);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] pubArr = retByteArray[0];
|
||||
|
||||
int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(pubArr.length, pubLen, "Got bad pubkey length.");
|
||||
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return pubArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param pubkey 32-byte seckey
|
||||
* @return The tweaked private key
|
||||
* @throws AssertFailException assertion failure
|
||||
*/
|
||||
public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException {
|
||||
checkArgument(pubkey.length == 33 || pubkey.length == 65);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(pubkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_pubkey_tweak_mul(byteBuff, Secp256k1Context.getContext(), pubkey.length);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] pubArr = retByteArray[0];
|
||||
|
||||
int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(pubArr.length, pubLen, "Got bad pubkey length.");
|
||||
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return pubArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 create ECDH secret - constant time ECDH calculation
|
||||
*
|
||||
* @param seckey byte array of secret key used in exponentiation
|
||||
* @param pubkey byte array of public key used in exponentiation
|
||||
* @return the secret
|
||||
* @throws AssertFailException assertion failure
|
||||
*/
|
||||
public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException {
|
||||
checkArgument(seckey.length <= 32 && pubkey.length <= 65);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(seckey);
|
||||
byteBuff.put(pubkey);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] resArr = retByteArray[0];
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
|
||||
assertEquals(resArr.length, 32, "Got bad result length.");
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return resArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 randomize - updates the context randomization
|
||||
*
|
||||
* @param seed 32-byte random seed
|
||||
* @return true if successful, false otherwise
|
||||
* @throws AssertFailException never thrown?
|
||||
*/
|
||||
public static synchronized boolean randomize(byte[] seed) throws AssertFailException {
|
||||
checkArgument(seed.length == 32 || seed == null);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < seed.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(seed.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(seed);
|
||||
|
||||
w.lock();
|
||||
try {
|
||||
return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1;
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data data to sign
|
||||
* @param sec secret key
|
||||
* @return Signature or byte[0]
|
||||
* @throws AssertFailException assertion failure
|
||||
*/
|
||||
public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailException {
|
||||
checkArgument(data.length == 32 && sec.length <= 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null) {
|
||||
byteBuff = ByteBuffer.allocateDirect(32 + 32);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
((Buffer) byteBuff).rewind();
|
||||
byteBuff.put(data);
|
||||
byteBuff.put(sec);
|
||||
|
||||
byte[][] retByteArray;
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] sigArr = retByteArray[0];
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
|
||||
assertEquals(sigArr.length, 64, "Got bad signature length.");
|
||||
|
||||
return retVal == 0 ? new byte[0] : sigArr;
|
||||
}
|
||||
|
||||
private static native long secp256k1_ctx_clone(long context);
|
||||
|
||||
private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen);
|
||||
|
||||
private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen);
|
||||
|
||||
private static native void secp256k1_destroy_context(long context);
|
||||
|
||||
private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen);
|
||||
|
||||
private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen);
|
||||
|
||||
private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoin;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Assertion utilities for {@link NativeSecp256k1}
|
||||
* @deprecated See https://github.com/bitcoinj/bitcoinj/issues/2267
|
||||
*/
|
||||
@Deprecated
|
||||
public class NativeSecp256k1Util {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NativeSecp256k1Util.class);
|
||||
|
||||
/**
|
||||
* Compare two integers and throw {@link AssertFailException} if not equal
|
||||
*
|
||||
* @param val first int
|
||||
* @param val2 second int
|
||||
* @param message failure error message
|
||||
* @throws AssertFailException when ints are not equal
|
||||
*/
|
||||
public static void assertEquals(int val, int val2, String message) throws AssertFailException {
|
||||
if (val != val2)
|
||||
throw new AssertFailException("FAIL: " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two booleans and throw {@link AssertFailException} if not equal
|
||||
*
|
||||
* @param val first boolean
|
||||
* @param val2 second boolean
|
||||
* @param message failure error message
|
||||
* @throws AssertFailException when booleans are not equal
|
||||
*/
|
||||
public static void assertEquals(boolean val, boolean val2, String message) throws AssertFailException {
|
||||
if (val != val2)
|
||||
throw new AssertFailException("FAIL: " + message);
|
||||
else
|
||||
log.debug("PASS: " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two Strings and throw {@link AssertFailException} if not equal
|
||||
*
|
||||
* @param val first String
|
||||
* @param val2 second String
|
||||
* @param message failure error message
|
||||
* @throws AssertFailException when Strings are not equal
|
||||
*/
|
||||
public static void assertEquals(String val, String val2, String message) throws AssertFailException {
|
||||
if (!val.equals(val2))
|
||||
throw new AssertFailException("FAIL: " + message);
|
||||
else
|
||||
log.debug("PASS: " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assertion failure exception
|
||||
*/
|
||||
public static class AssertFailException extends Exception {
|
||||
/**
|
||||
* @param message The failure message
|
||||
*/
|
||||
public AssertFailException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoin;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class holds the context reference used in native methods to handle ECDSA operations.
|
||||
* @deprecated See https://github.com/bitcoinj/bitcoinj/issues/2267
|
||||
*/
|
||||
@Deprecated
|
||||
public class Secp256k1Context {
|
||||
|
||||
private static final boolean enabled; // true if the library is loaded
|
||||
private static final long context; // ref to pointer to context obj
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Secp256k1Context.class);
|
||||
|
||||
static { // static initializer
|
||||
boolean isEnabled = true;
|
||||
long contextRef = -1;
|
||||
try {
|
||||
System.loadLibrary("secp256k1");
|
||||
contextRef = secp256k1_init_context();
|
||||
} catch (UnsatisfiedLinkError | SecurityException e) {
|
||||
log.debug(e.toString());
|
||||
isEnabled = false;
|
||||
}
|
||||
enabled = isEnabled;
|
||||
context = contextRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if enabled
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return context reference
|
||||
*/
|
||||
public static long getContext() {
|
||||
if (!enabled)
|
||||
return -1; // sanity check
|
||||
return context;
|
||||
}
|
||||
|
||||
private static native long secp256k1_init_context();
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
* Copyright 2014 Andreas Schildbach
|
||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,9 +18,6 @@
|
||||
package org.bitcoinj.crypto;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.bitcoin.NativeSecp256k1;
|
||||
import org.bitcoin.NativeSecp256k1Util;
|
||||
import org.bitcoin.Secp256k1Context;
|
||||
import org.bitcoinj.base.Address;
|
||||
import org.bitcoinj.base.BitcoinNetwork;
|
||||
import org.bitcoinj.base.LegacyAddress;
|
||||
@ -587,20 +583,6 @@ public class ECKey implements EncryptableItem {
|
||||
}
|
||||
|
||||
protected ECDSASignature doSign(Sha256Hash input, BigInteger privateKeyForSigning) {
|
||||
if (Secp256k1Context.isEnabled()) {
|
||||
try {
|
||||
byte[] signature = NativeSecp256k1.sign(
|
||||
input.getBytes(),
|
||||
ByteUtils.bigIntegerToBytes(privateKeyForSigning, 32)
|
||||
);
|
||||
return ECDSASignature.decodeFromDER(signature);
|
||||
} catch (NativeSecp256k1Util.AssertFailException e) {
|
||||
log.error("Caught AssertFailException inside secp256k1", e);
|
||||
throw new RuntimeException(e);
|
||||
} catch (SignatureDecodeException e) {
|
||||
throw new RuntimeException(e); // cannot happen
|
||||
}
|
||||
}
|
||||
Objects.requireNonNull(privateKeyForSigning);
|
||||
ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
|
||||
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(privateKeyForSigning, CURVE);
|
||||
@ -612,23 +594,11 @@ public class ECKey implements EncryptableItem {
|
||||
/**
|
||||
* <p>Verifies the given ECDSA signature against the message bytes using the public key bytes.</p>
|
||||
*
|
||||
* <p>When using native ECDSA verification, data must be 32 bytes, and no element may be
|
||||
* larger than 520 bytes.</p>
|
||||
*
|
||||
* @param data Hash of the data to verify.
|
||||
* @param signature ASN.1 encoded signature.
|
||||
* @param pub The public key bytes to use.
|
||||
*/
|
||||
public static boolean verify(byte[] data, ECDSASignature signature, byte[] pub) {
|
||||
if (Secp256k1Context.isEnabled()) {
|
||||
try {
|
||||
return NativeSecp256k1.verify(data, signature.encodeToDER(), pub);
|
||||
} catch (NativeSecp256k1Util.AssertFailException e) {
|
||||
log.error("Caught AssertFailException inside secp256k1", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ECDSASigner signer = new ECDSASigner();
|
||||
ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE);
|
||||
signer.init(false, params);
|
||||
@ -651,14 +621,6 @@ public class ECKey implements EncryptableItem {
|
||||
* @throws SignatureDecodeException if the signature is unparseable in some way.
|
||||
*/
|
||||
public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws SignatureDecodeException {
|
||||
if (Secp256k1Context.isEnabled()) {
|
||||
try {
|
||||
return NativeSecp256k1.verify(data, signature, pub);
|
||||
} catch (NativeSecp256k1Util.AssertFailException e) {
|
||||
log.error("Caught AssertFailException inside secp256k1", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return verify(data, ECDSASignature.decodeFromDER(signature), pub);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user