84973d3 Merge #454: Remove residual parts from the schnorr expirement. 5e95bf2 Remove residual parts from the schnorr expirement. cbc20b8 Merge #452: Minor optimizations to _scalar_inverse to save 4M 4cc8f52 Merge #437: Unroll secp256k1_fe_(get|set)_b32 to make them much faster. 465159c Further shorten the addition chain for scalar inversion. a2b6b19 Fix benchmark print_number infinite loop. 8b7680a Unroll secp256k1_fe_(get|set)_b32 for 10x26. aa84990 Unroll secp256k1_fe_(get|set)_b32 for 5x52. cf12fa1 Minor optimizations to _scalar_inverse to save 4M 1199492 Merge #408: Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` 6af0871 Merge #441: secp256k1_context_randomize: document. ab31a52 Merge #444: test: Use checked_alloc eda5c1a Merge #449: Remove executable bit from secp256k1.c 51b77ae Remove executable bit from secp256k1.c 5eb030c test: Use checked_alloc 72d952c FIXUP: Missing "is" 70ff29b secp256k1_context_randomize: document. 9d560f9 Merge #428: Exhaustive recovery 8e48aa6 Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` 2cee5fd exhaustive tests: add recovery module 8225239 Merge #433: Make the libcrypto detection fail the newer API. 12de863 Make the libcrypto detection fail the newer API. 678b0e5 exhaustive tests: remove erroneous comment from ecdsa_sig_sign 2928420 Merge #427: Remove Schnorr from travis as well 03ff8c2 group_impl.h: remove unused `secp256k1_ge_set_infinity` function a724d72 configure: add --enable-coverage to set options for coverage analysis b595163 recovery: add tests to cover API misusage 8eecc4a Remove Schnorr from travis as well 6f8ae2f ecdh: test NULL-checking of arguments 25e3cfb ecdsa_impl: replace scalar if-checks with VERIFY_CHECKs in ecdsa_sig_sign a8abae7 Merge #310: Add exhaustive test for group functions on a low-order subgroup b4ceedf Add exhaustive test for verification 83836a9 Add exhaustive tests for group arithmetic, signing, and ecmult on a small group 20b8877 Add exhaustive test for group functions on a low-order subgroup 80773a6 Merge #425: Remove Schnorr experiment e06e878 Remove Schnorr experiment 04c8ef3 Merge #407: Modify parameter order of internal functions to match API parameter order 6e06696 Merge #411: Remove guarantees about memcmp-ability 40c8d7e Merge #421: Update scalar_4x64_impl.h a922365 Merge #422: Restructure nonce clearing 3769783 Restructure nonce clearing 0f9e69d Restructure nonce clearing 9d67afa Update scalar_4x64_impl.h 7d15cd7 Merge #413: fix auto-enabled static precompuatation 00c5d2e fix auto-enabled static precompuatation 91219a1 Remove guarantees about memcmp-ability 7a49cac Merge #410: Add string.h include to ecmult_impl 0bbd5d4 Add string.h include to ecmult_impl 353c1bf Fix secp256k1_ge_set_table_gej_var parameter order 541b783 Fix secp256k1_ge_set_all_gej_var parameter order 7d893f4 Fix secp256k1_fe_inv_all_var parameter order c5b32e1 Merge #405: Make secp256k1_fe_sqrt constant time 926836a Make secp256k1_fe_sqrt constant time e2a8e92 Merge #404: Replace 3M + 4S doubling formula with 2M + 5S one 8ec49d8 Add note about 2M + 5S doubling formula 5a91bd7 Merge #400: A couple minor cleanups ac01378 build: add -DSECP256K1_BUILD to benchmark_internal build flags a6c6f99 Remove a bunch of unused stdlib #includes 65285a6 Merge #403: configure: add flag to disable OpenSSL tests a9b2a5d configure: add flag to disable OpenSSL tests b340123 Merge #402: Add support for testing quadratic residues e6e9805 Add function for testing quadratic residue field/group elements. efd953a Add Jacobi symbol test via GMP fa36a0d Merge #401: ecmult_const: unify endomorphism and non-endomorphism skew cases c6191fd ecmult_const: unify endomorphism and non-endomorphism skew cases 0b3e618 Merge #378: .gitignore build-aux cleanup 6042217 Merge #384: JNI: align shared files copyright/comments to bitcoinj's 24ad20f Merge #399: build: verify that the native compiler works for static precomp b3be852 Merge #398: Test whether ECDH and Schnorr are enabled for JNI aa0b1fd build: verify that the native compiler works for static precomp eee808d Test whether ECDH and Schnorr are enabled for JNI 7b0fb18 Merge #366: ARM assembly implementation of field_10x26 inner (rebase of #173) 001f176 ARM assembly implementation of field_10x26 inner 0172be9 Merge #397: Small fixes for sha256 3f8b78e Fix undefs in hash_impl.h 2ab4695 Fix state size in sha256 struct 6875b01 Merge #386: Add some missing `VERIFY_CHECK(ctx != NULL)` 2c52b5d Merge #389: Cast pointers through uintptr_t under JNI 43097a4 Merge #390: Update bitcoin-core GitHub links 31c9c12 Merge #391: JNI: Only call ecdsa_verify if its inputs parsed correctly 1cb2302 Merge #392: Add testcase which hits additional branch in secp256k1_scalar_sqr d2ee340 Merge #388: bench_ecdh: fix call to secp256k1_context_create 093a497 Add testcase which hits additional branch in secp256k1_scalar_sqr a40c701 JNI: Only call ecdsa_verify if its inputs parsed correctly faa2a11 Update bitcoin-core GitHub links 47b9e78 Cast pointers through uintptr_t under JNI f36f9c6 bench_ecdh: fix call to secp256k1_context_create bcc4881 Add some missing `VERIFY_CHECK(ctx != NULL)` for functions that use `ARG_CHECK` 6ceea2c align shared files copyright/comments to bitcoinj's 70141a8 Update .gitignore 7b549b1 Merge #373: build: fix x86_64 asm detection for some compilers bc7c93c Merge #374: Add note about y=0 being possible on one of the sextic twists e457018 Merge #364: JNI rebased 86e2d07 JNI library: cleanup, removed unimplemented code 3093576a JNI library bd2895f Merge pull request #371 e72e93a Add note about y=0 being possible on one of the sextic twists 3f8fdfb build: fix x86_64 asm detection for some compilers e5a9047 [Trivial] Remove double semicolons c18b869 Merge pull request #360 3026daa Merge pull request #302 03d4611 Add sage verification script for the group laws a965937 Merge pull request #361 83221ec Add experimental features to configure 5d4c5a3 Prevent damage_array in the signature test from going out of bounds. 419bf7f Merge pull request #356 6c527ec Merge pull request #357 445f7f1 Fix for Windows compile issue 03d84a4 Benchmark against OpenSSL verification 2bfb82b Merge pull request #351 06aeea5 Turn secp256k1_ec_pubkey_serialize outlen to in/out 970164d Merge pull request #348 6466625 Improvements for coordinate decompression e2100ad Merge pull request #347 8e48787 Change secp256k1_ec_pubkey_combine's count argument to size_t. c69dea0 Clear output in more cases for pubkey_combine, adds tests. 269d422 Comment copyediting. b4d17da Merge pull request #344 4709265 Merge pull request #345 26abce7 Adds 32 static test vectors for scalar mul, sqr, inv. 5b71a3f Better error case handling for pubkey_create & pubkey_serialize, more tests. 3b7bc69 Merge pull request #343 eed87af Change contrib/laxder from headers-only to files compilable as standalone C d7eb1ae Merge pull request #342 7914a6e Make lax_der_privatekey_parsing.h not depend on internal code 73f64ff Merge pull request #339 9234391 Overhaul flags handling 1a36898 Make flags more explicit, add runtime checks. 1a3e03a Merge pull request #340 96be204 Add additional tests for eckey and arg-checks. bb5aa4d Make the tweak function zeroize-output-on-fail behavior consistent. 4a243da Move secp256k1_ec_privkey_import/export to contrib. 1b3efc1 Move secp256k1_ecdsa_sig_recover into the recovery module. e3cd679 Eliminate all side-effects from VERIFY_CHECK() usage. b30fc85 Avoid nonce_function_rfc6979 algo16 argument emulation. 70d4640 Make secp256k1_ec_pubkey_create skip processing invalid secret keys. 6c476a8 Minor comment improvements. 131afe5 Merge pull request #334 0c6ab2f Introduce explicit lower-S normalization fea19e7 Add contrib/lax_der_parsing.h 3bb9c44 Rewrite ECDSA signature parsing code fa57f1b Use secp256k1_rand_int and secp256k1_rand_bits more 49b3749 Add new tests for the extra testrand functions f684d7d Faster secp256k1_rand_int implementation 251b1a6 Improve testrand: add extra random functions 31994c8 Merge pull request #338 f79aa88 Bugfix: swap arguments to noncefp c98df26 Merge pull request #319 67f7da4 Extensive interface and operations tests for secp256k1_ec_pubkey_parse. ee2cb40 Add ARG_CHECKs to secp256k1_ec_pubkey_parse/secp256k1_ec_pubkey_serialize 7450ef1 Merge pull request #328 68a3c76 Merge pull request #329 98135ee Merge pull request #332 37100d7 improve ECDH header-doc b13d749 Fix couple of typos in API comments 7c823e3 travis: fixup module configs cc3141a Merge pull request #325 ee58fae Merge pull request #326 213aa67 Do not force benchmarks to be statically linked. 338fc8b Add API exports to secp256k1_nonce_function_default and secp256k1_nonce_function_rfc6979. 52fd03f Merge pull request #320 9f6993f Remove some dead code. 357f8cd Merge pull request #314 118cd82 Use explicit symbol visibility. 4e64608 Include public module headers when compiling modules. 1f41437 Merge pull request #316 fe0d463 Merge pull request #317 cfe0ed9 Fix miscellaneous style nits that irritate overactive static analysis. 2b199de Use the explicit NULL macro for pointer comparisons. 9e90516 Merge pull request #294 dd891e0 Get rid of _t as it is POSIX reserved 201819b Merge pull request #313 912f203 Eliminate a few unbraced statements that crept into the code. eeab823 Merge pull request #299 486b9bb Use a flags bitfield for compressed option to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export 05732c5 Callback data: Accept pointers to either const or non-const data 1973c73 Bugfix: Reinitialise buffer lengths that have been used as outputs 788038d Use size_t for lengths (at least in external API) c9d7c2a secp256k1_context_set_{error,illegal}_callback: Restore default handler by passing NULL as function argument 9aac008 secp256k1_context_destroy: Allow NULL argument as a no-op 64b730b secp256k1_context_create: Use unsigned type for flags bitfield cb04ab5 Merge pull request #309 a551669 Merge pull request #295 81e45ff Update group_impl.h 85e3a2c Merge pull request #112 b2eb63b Merge pull request #293 dc0ce9f [API BREAK] Change argument order to out/outin/in 6d947ca Merge pull request #298 c822693 Merge pull request #301 6d04350 Merge pull request #303 7ab311c Merge pull request #304 5fb3229 Fixes a bug where bench_sign would fail due to passing in too small a buffer. 263dcbc remove unused assignment b183b41 bugfix: "ARG_CHECK(ctx != NULL)" makes no sense 6da1446 build: fix parallel build 5eb4356 Merge pull request #291 c996d53 Print success 9f443be Move pubkey recovery code to separate module d49abbd Separate ECDSA recovery tests 439d34a Separate recoverable and normal signatures a7b046e Merge pull request #289 f66907f Improve/reformat API documentation secp256k1.h 2f77487 Add context building benchmarks cc623d5 Merge pull request #287 de7e398 small typo fix 9d96e36 Merge pull request #280 432e1ce Merge pull request #283 14727fd Use correct name in gitignore 356b0e9 Actually test static precomputation in Travis ff3a5df Merge pull request #284 2587208 Merge pull request #212 a5a66c7 Add support for custom EC-Schnorr-SHA256 signatures d84a378 Merge pull request #252 72ae443 Improve perf. of cmov-based table lookup 92e53fc Implement endomorphism optimization for secp256k1_ecmult_const ed35d43 Make `secp256k1_scalar_add_bit` conditional; make `secp256k1_scalar_split_lambda_var` constant time 91c0ce9 Add benchmarks for ECDH and const-time multiplication 0739bbb Add ECDH module which works by hashing the output of ecmult_const 4401500 Add constant-time multiply `secp256k1_ecmult_const` for ECDH e4ce393 build: fix hard-coded usage of "gen_context" b8e39ac build: don't use BUILT_SOURCES for the static context header baa75da tests: add a couple tests ae4f0c6 Merge pull request #278 995c548 Introduce callback functions for dealing with errors. c333074 Merge pull request #282 18c329c Remove the internal secp256k1_ecdsa_sig_t type 74a2acd Add a secp256k1_ecdsa_signature_t type 23cfa91 Introduce secp256k1_pubkey_t type 4c63780 Merge pull request #269 3e6f1e2 Change rfc6979 implementation to be a generic PRNG ed5334a Update configure.ac to make it build on OpenBSD 1b68366 Merge pull request #274 a83bb48 Make ecmult static precomputation default 166b32f Merge pull request #276 c37812f Add gen_context src/ecmult_static_context.h to CLEANFILES to fix distclean. 125c15d Merge pull request #275 76f6769 Fix build with static ecmult altroot and make dist. 5133f78 Merge pull request #254 b0a60e6 Merge pull request #258 733c1e6 Add travis build to test the static context. fbecc38 Add ability to use a statically generated ecmult context. 4fb174d Merge pull request #263 4ab8990 Merge pull request #270 bdf0e0c Merge pull request #271 31d0c1f Merge pull request #273 eb2c8ff Add missing casts to SECP256K1_FE_CONST_INNER 55399c2 Further performance improvements to _ecmult_wnaf 99fd963 Add secp256k1_ec_pubkey_compress(), with test similar to the related decompress() function. 145cc6e Improve performance of _ecmult_wnaf 36b305a Verify the result of GMP modular inverse using non-GMP code 0cbc860 Merge pull request #266 06ff7fe Merge pull request #267 5a43124 Save 1 _fe_negate since s1 == -s2 a5d796e Update code comments 3f3964e Add specific VERIFY tests for _fe_cmov 7d054cd Refactor to save a _fe_negate b28d02a Refactor to remove a local var 55e7fc3 Perf. improvement in _gej_add_ge a0601cd Fix VERIFY calculations in _fe_cmov methods 17f7148 Merge pull request #261 7657420 Add tests for adding P+Q with P.x!=Q.x and P.y=-Q.y 8c5d5f7 tests: Add failing unit test for #257 (bad addition formula) 5de4c5d gej_add_ge: fix degenerate case when computing P + (-lambda)P bcf2fcf gej_add_ge: rearrange algebra e2a07c7 Fix compilation with C++ 873a453 Merge pull request #250 91eb0da Merge pull request #247 210ffed Use separate in and out pointers in `secp256k1_ec_pubkey_decompress` a1d5ae1 Tiny optimization 729badf Merge pull request #210 2d5a186 Apply effective-affine trick to precomp 4f9791a Effective affine addition in EC multiplication 2b4cf41 Use pkg-config always when possible, with failover to manual checks for libcrypto git-subtree-dir: src/secp256k1 git-subtree-split: 84973d393ac240a90b2e1a6538c5368202bc2224
447 lines
15 KiB
Java
447 lines
15 KiB
Java
/*
|
|
* 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.nio.ByteBuffer;
|
|
import java.nio.ByteOrder;
|
|
|
|
import java.math.BigInteger;
|
|
import com.google.common.base.Preconditions;
|
|
import java.util.concurrent.locks.Lock;
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
import static org.bitcoin.NativeSecp256k1Util.*;
|
|
|
|
/**
|
|
* <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-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>
|
|
*/
|
|
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<ByteBuffer>();
|
|
/**
|
|
* 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
|
|
*/
|
|
public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
byteBuff.rewind();
|
|
byteBuff.put(data);
|
|
byteBuff.put(signature);
|
|
byteBuff.put(pub);
|
|
|
|
byte[][] retByteArray;
|
|
|
|
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 key Secret key, 32 bytes
|
|
*
|
|
* Return values
|
|
* @param sig byte array of signature
|
|
*/
|
|
public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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
|
|
*/
|
|
public static boolean secKeyVerify(byte[] seckey) {
|
|
Preconditions.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);
|
|
}
|
|
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 values
|
|
* @param pubkey ECDSA Public key, 33 or 65 bytes
|
|
*/
|
|
//TODO add a 'compressed' arg
|
|
public static byte[] computePubkey(byte[] seckey) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
|
|
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 seckey 32-byte seckey
|
|
*/
|
|
public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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 seckey 32-byte seckey
|
|
*/
|
|
public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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
|
|
*/
|
|
public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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
|
|
*/
|
|
public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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 exponentiaion
|
|
* @param pubkey byte array of public key used in exponentiaion
|
|
*/
|
|
public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
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
|
|
*/
|
|
public static synchronized boolean randomize(byte[] seed) throws AssertFailException{
|
|
Preconditions.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);
|
|
}
|
|
byteBuff.rewind();
|
|
byteBuff.put(seed);
|
|
|
|
w.lock();
|
|
try {
|
|
return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1;
|
|
} finally {
|
|
w.unlock();
|
|
}
|
|
}
|
|
|
|
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_ecdh(ByteBuffer byteBuff, long context, int inputLen);
|
|
|
|
}
|