Changeset View
Changeset View
Standalone View
Standalone View
src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java
Show First 20 Lines • Show All 409 Lines • ▼ Show 20 Lines | public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ | ||||
try { | try { | ||||
return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; | return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; | ||||
} finally { | } finally { | ||||
w.unlock(); | w.unlock(); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* libsecp256k1 Create a Schnorr signature. | |||||
* | |||||
* @param data Message hash, 32 bytes | |||||
* @param seckey Secret key, 32 bytes | |||||
* @return sig byte array of signature | |||||
*/ | |||||
public static byte[] schnorrSign(byte[] data, byte[] seckey) throws AssertFailException { | |||||
checkArgument(data.length == 32 && seckey.length <= 32); | |||||
ByteBuffer byteBuff = nativeECDSABuffer.get(); | |||||
if (byteBuff == null || byteBuff.capacity() < data.length + seckey.length) { | |||||
byteBuff = ByteBuffer.allocateDirect(32 + 32); | |||||
byteBuff.order(ByteOrder.nativeOrder()); | |||||
nativeECDSABuffer.set(byteBuff); | |||||
} | |||||
byteBuff.rewind(); | |||||
byteBuff.put(data); | |||||
byteBuff.put(seckey); | |||||
jasonbcox: Just from looking at this diff, it looks like`byteBuff` and `seckey` are not being explicitly… | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsCreated a task for this since it's not necessary to block this diff for it: https://reviews.bitcoinabc.org/T587 jasonbcox: Created a task for this since it's not necessary to block this diff for it: https://reviews. | |||||
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; | |||||
} | |||||
/** | |||||
* Verifies the given Schnorr signature in native code. | * Verifies the given Schnorr signature in native code. | ||||
* Calling when enabled == false is undefined (probably library not loaded) | * Calling when enabled == false is undefined (probably library not loaded) | ||||
* | * | ||||
* @param data The data which was signed, must be exactly 32 bytes | * @param data The data which was signed, must be exactly 32 bytes | ||||
* @param signature The signature is exactly 64 bytes | * @param signature The signature is exactly 64 bytes | ||||
* @param pub The public key which did the signing which is the same ECDSA | * @param pub The public key which did the signing which is the same ECDSA | ||||
*/ | */ | ||||
public static boolean schnorrVerify(byte[] data, byte[] signature, byte[] pub) { | public static boolean schnorrVerify(byte[] data, byte[] signature, byte[] pub) { | ||||
Show All 39 Lines | public class NativeSecp256k1 { | ||||
private static native int secp256k1_ec_seckey_verify(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_create(ByteBuffer byteBuff, long context); | ||||
private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); | private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); | ||||
private static native int secp256k1_schnorr_verify(ByteBuffer byteBuff, long context, int pubLen); | private static native int secp256k1_schnorr_verify(ByteBuffer byteBuff, long context, int pubLen); | ||||
private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context); | |||||
private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); | private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); | ||||
} | } |
Just from looking at this diff, it looks like`byteBuff` and seckey are not being explicitly cleaned up before this function exits. Given that Java's GC is "at will" the secret key could be floating around in memory.
If this memory is not being cleaned up somewhere, we may have to zero them out and clear them before exiting. The exact behavior may be impacted by my other question below about memory leaking. If a new object is NOT created, then we need to know the consequences of altering that memory.
Note that this issue may also impact other ECDSA functions in this file as well.