20import java.nio.ByteBuffer;
21import java.nio.ByteOrder;
23import java.math.BigInteger;
24import java.util.concurrent.locks.Lock;
25import java.util.concurrent.locks.ReentrantReadWriteLock;
26import static org.bitcoin.NativeSecp256k1Util.*;
41 private static final ReentrantReadWriteLock
rwl =
new ReentrantReadWriteLock();
42 private static final Lock
r =
rwl.readLock();
43 private static final Lock
w =
rwl.writeLock();
44 private static ThreadLocal<ByteBuffer>
nativeByteBuffer =
new ThreadLocal<ByteBuffer>();
53 public static boolean verify(
byte[] data,
byte[] signature,
byte[] pub) {
54 checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520);
57 if (byteBuff ==
null || byteBuff.capacity() < 520) {
58 byteBuff = ByteBuffer.allocateDirect(520);
59 byteBuff.order(ByteOrder.nativeOrder());
64 byteBuff.put(signature);
84 public static byte[]
sign(
byte[] data,
byte[] sec)
throws AssertFailException{
85 checkArgument(data.length == 32 && sec.length <= 32);
88 if (byteBuff ==
null || byteBuff.capacity() < 32 + 32) {
89 byteBuff = ByteBuffer.allocateDirect(32 + 32);
90 byteBuff.order(ByteOrder.nativeOrder());
97 byte[][] retByteArray;
106 byte[] sigArr = retByteArray[0];
107 int sigLen =
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue();
108 int retVal =
new BigInteger(
new byte[] { retByteArray[1][1] }).intValue();
110 assertEquals(sigArr.length, sigLen,
"Got bad signature length.");
112 return retVal == 0 ?
new byte[0] : sigArr;
121 checkArgument(seckey.length == 32);
124 if (byteBuff ==
null || byteBuff.capacity() < seckey.length) {
125 byteBuff = ByteBuffer.allocateDirect(seckey.length);
126 byteBuff.order(ByteOrder.nativeOrder());
130 byteBuff.put(seckey);
150 public static byte[]
computePubkey(
byte[] seckey)
throws AssertFailException{
151 checkArgument(seckey.length == 32);
154 if (byteBuff ==
null || byteBuff.capacity() < seckey.length) {
155 byteBuff = ByteBuffer.allocateDirect(seckey.length);
156 byteBuff.order(ByteOrder.nativeOrder());
160 byteBuff.put(seckey);
162 byte[][] retByteArray;
171 byte[] pubArr = retByteArray[0];
172 int pubLen =
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue();
173 int retVal =
new BigInteger(
new byte[] { retByteArray[1][1] }).intValue();
175 assertEquals(pubArr.length, pubLen,
"Got bad pubkey length.");
177 return retVal == 0 ?
new byte[0]: pubArr;
197 }
finally {
r.unlock(); }
206 public static byte[]
privKeyTweakMul(
byte[] privkey,
byte[] tweak)
throws AssertFailException{
207 checkArgument(privkey.length == 32);
210 if (byteBuff ==
null || byteBuff.capacity() < privkey.length + tweak.length) {
211 byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length);
212 byteBuff.order(ByteOrder.nativeOrder());
216 byteBuff.put(privkey);
219 byte[][] retByteArray;
227 byte[] privArr = retByteArray[0];
229 int privLen = (byte)
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
230 int retVal =
new BigInteger(
new byte[] { retByteArray[1][1] }).intValue();
232 assertEquals(privArr.length, privLen,
"Got bad pubkey length.");
234 assertEquals(retVal, 1,
"Failed return value check.");
245 public static byte[]
privKeyTweakAdd(
byte[] privkey,
byte[] tweak)
throws AssertFailException{
246 checkArgument(privkey.length == 32);
249 if (byteBuff ==
null || byteBuff.capacity() < privkey.length + tweak.length) {
250 byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length);
251 byteBuff.order(ByteOrder.nativeOrder());
255 byteBuff.put(privkey);
258 byte[][] retByteArray;
266 byte[] privArr = retByteArray[0];
268 int privLen = (byte)
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
269 int retVal =
new BigInteger(
new byte[] { retByteArray[1][1] }).intValue();
271 assertEquals(privArr.length, privLen,
"Got bad pubkey length.");
273 assertEquals(retVal, 1,
"Failed return value check.");
284 public static byte[]
pubKeyTweakAdd(
byte[] pubkey,
byte[] tweak)
throws AssertFailException{
285 checkArgument(pubkey.length == 33 || pubkey.length == 65);
288 if (byteBuff ==
null || byteBuff.capacity() < pubkey.length + tweak.length) {
289 byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length);
290 byteBuff.order(ByteOrder.nativeOrder());
294 byteBuff.put(pubkey);
297 byte[][] retByteArray;
305 byte[] pubArr = retByteArray[0];
307 int pubLen = (byte)
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
308 int retVal =
new BigInteger(
new byte[] { retByteArray[1][1] }).intValue();
310 assertEquals(pubArr.length, pubLen,
"Got bad pubkey length.");
312 assertEquals(retVal, 1,
"Failed return value check.");
323 public static byte[]
pubKeyTweakMul(
byte[] pubkey,
byte[] tweak)
throws AssertFailException{
324 checkArgument(pubkey.length == 33 || pubkey.length == 65);
327 if (byteBuff ==
null || byteBuff.capacity() < pubkey.length + tweak.length) {
328 byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length);
329 byteBuff.order(ByteOrder.nativeOrder());
333 byteBuff.put(pubkey);
336 byte[][] retByteArray;
344 byte[] pubArr = retByteArray[0];
346 int pubLen = (byte)
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
347 int retVal =
new BigInteger(
new byte[] { retByteArray[1][1] }).intValue();
349 assertEquals(pubArr.length, pubLen,
"Got bad pubkey length.");
351 assertEquals(retVal, 1,
"Failed return value check.");
362 public static byte[]
createECDHSecret(
byte[] seckey,
byte[] pubkey)
throws AssertFailException{
363 checkArgument(seckey.length <= 32 && pubkey.length <= 65);
366 if (byteBuff ==
null || byteBuff.capacity() < 32 + pubkey.length) {
367 byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length);
368 byteBuff.order(ByteOrder.nativeOrder());
372 byteBuff.put(seckey);
373 byteBuff.put(pubkey);
375 byte[][] retByteArray;
383 byte[] resArr = retByteArray[0];
384 int retVal =
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue();
386 assertEquals(resArr.length, 32,
"Got bad result length.");
387 assertEquals(retVal, 1,
"Failed return value check.");
397 public static synchronized boolean randomize(
byte[] seed)
throws AssertFailException{
398 checkArgument(seed.length == 32 || seed ==
null);
401 if (byteBuff ==
null || byteBuff.capacity() < seed.length) {
402 byteBuff = ByteBuffer.allocateDirect(seed.length);
403 byteBuff.order(ByteOrder.nativeOrder());
424 public static byte[]
schnorrSign(
byte[] data,
byte[] seckey)
throws AssertFailException {
425 checkArgument(data.length == 32 && seckey.length <= 32);
428 if (byteBuff ==
null || byteBuff.capacity() < data.length + seckey.length) {
429 byteBuff = ByteBuffer.allocateDirect(32 + 32);
430 byteBuff.order(ByteOrder.nativeOrder());
435 byteBuff.put(seckey);
437 byte[][] retByteArray;
446 byte[] sigArr = retByteArray[0];
447 int retVal =
new BigInteger(
new byte[] { retByteArray[1][0] }).intValue();
449 assertEquals(sigArr.length, 64,
"Got bad signature length.");
451 return retVal == 0 ?
new byte[0] : sigArr;
462 public static boolean schnorrVerify(
byte[] data,
byte[] signature,
byte[] pub) {
463 checkArgument(data.length == 32 && signature.length == 64 && (pub.length == 33 || pub.length == 65));
466 if (byteBuff ==
null || byteBuff.capacity() < 32 + 64 + pub.length) {
467 byteBuff = ByteBuffer.allocateDirect(32 + 64 + pub.length);
468 byteBuff.order(ByteOrder.nativeOrder());
473 byteBuff.put(signature);
512 private static native
byte[][]
secp256k1_ecdh(ByteBuffer byteBuff,
long context,
int inputLen);
static byte[] createECDHSecret(byte[] seckey, byte[] pubkey)
libsecp256k1 create ECDH secret - constant time ECDH calculation
static boolean schnorrVerify(byte[] data, byte[] signature, byte[] pub)
Verifies the given Schnorr signature in native code.
static native int secp256k1_schnorr_verify(ByteBuffer byteBuff, long context, int pubLen)
static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen)
static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak)
libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it
static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context)
static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak)
libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it
static ThreadLocal< ByteBuffer > nativeByteBuffer
static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context)
static final ReentrantReadWriteLock rwl
static native long secp256k1_ctx_clone(long context)
static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen)
static byte[] sign(byte[] data, byte[] sec)
libsecp256k1 Create an ECDSA signature.
static synchronized boolean randomize(byte[] seed)
libsecp256k1 randomize - updates the context randomization
static boolean verify(byte[] data, byte[] signature, byte[] pub)
Verifies the given secp256k1 signature in native code.
static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak)
libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it
static long cloneContext()
static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen)
static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak)
libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it
static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context)
static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context)
static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen)
static native void secp256k1_destroy_context(long context)
static byte[] schnorrSign(byte[] data, byte[] seckey)
libsecp256k1 Create a Schnorr signature.
static byte[] computePubkey(byte[] seckey)
libsecp256k1 Compute Pubkey - computes public key from secret key
static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen)
static synchronized void cleanup()
libsecp256k1 Cleanup - This destroys the secp256k1 context object This should be called at the end of...
static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context)
static boolean secKeyVerify(byte[] seckey)
libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid
static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context)
static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context)
This class holds the context reference used in native methods to handle ECDSA operations.