diff --git a/README.md b/README.md index b35a508..3a20f25 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,218 @@ -# libzksnark -a zksnark jni library +# zksnark-java-sdk -# Pull source +A Java JNI wrapper for ZK-SNARK cryptographic functions, providing Sapling protocol support for the TRON blockchain. + +## Overview + +This library enables Java applications to perform ZK-SNARK operations including: +- Sapling spend and output proof generation +- Proof verification +- ZIP32 hierarchical key derivation +- Note encryption/decryption using ChaCha20-Poly1305 +- Blake2b hashing with salt and personalization + +## Requirements + +| Tool | Version | Notes | +|------|---------|-------| +| cmake | >= 3.10.2 | CMake 3.x recommended | +| Rust (cargo) | >= 1.50.0 | Rust 2018 edition | +| libtool | >= 2.4.0 | GNU libtool | +| automake | >= 1.13 | GNU automake | +| Maven | >= 3.5.0 | Apache Maven | +| JDK | 8+ | JAVA_HOME must be set | +| Xcode Command Line Tools | Latest | macOS only | + +## Installation + +### Clone the Repository + +```bash +# Clone with submodules +git clone git@github.com:tronprotocol/zksnark-java-sdk.git --recursive + +# Or initialize submodules after cloning +git clone git@github.com:tronprotocol/zksnark-java-sdk.git +cd zksnark-java-sdk +git submodule update --init --recursive ``` -$ git clone git@github.com:tronprotocol/zksnark-java-sdk.git --recursive + +### Build the Native Library + +**Linux / macOS (Intel):** + +```bash +cd cpp && mkdir build && cd build +cmake .. +make -j4 +make install ``` -OR + +**macOS (M1/Apple Silicon):** + +```bash +cd cpp && mkdir build && cd build +CC=cc cmake -DCMAKE_OSX_ARCHITECTURES=arm64 .. +make -j4 +make install ``` -$ git clone git@github.com:tronprotocol/zksnark-java-sdk.git -$ git submodule update --init --recursive + +### Build the Java Package + +Run this from the project root directory: + +```bash +mvn clean package ``` -# Required +This creates a JAR file with the native libraries bundled for the current platform. - cmake (version >= 3.10.2) +## Clean and Rebuild - cargo +### Clean Build Artifacts - libtool +```bash +# Clean CMake build +rm -rf cpp/build - automake +# Clean Rust build +rm -rf rust/librustzcash/target + +# Clean Java build +mvn clean +``` - mvn +## Usage - jdk8(need JAVA_HOME set) +### Initialize ZK-SNARK Parameters -# for m1 -```shell - cd cpp && mkdir build && cd build - CC=cc cmake .. - make +Before using any ZK-SNARK functions, initialize the Sapling parameters: + +```java +import org.tron.common.zksnark.LibrustzcashWrapper; +import org.tron.common.util.Utils; + +LibrustzcashWrapper.getInstance().librustzcashInitZksnarkParams( + Utils.getParamsFile("sapling-spend.params"), + "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c", + Utils.getParamsFile("sapling-output.params"), + "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028" +); ``` + +### Key Derivation (ZIP32) + +```java +import org.tron.common.zksnark.LibrustzcashWrapper; + +// Derive master xsk from seed +byte[] seed = new byte[32]; // your seed +byte[] xskMaster = new byte[160]; +LibrustzcashWrapper.getInstance().librustzcashZip32XskMaster(seed, seed.length, xskMaster); + +// Derive child xsk at index i +byte[] xskChild = new byte[160]; +LibrustzcashWrapper.getInstance().librustzcashZip32XskDerive(xskMaster, i, xskChild); + +// Derive address from xfvk +byte[] xfvk = new byte[160]; +byte[] index = new byte[11]; +byte[] jRet = new byte[11]; +byte[] addr = new byte[43]; +boolean success = LibrustzcashWrapper.getInstance() + .librustzcashZip32XfvkAddress(xfvk, index, jRet, addr); +``` + +### Generate Sapling Spend Proof + +```java +import org.tron.common.zksnark.LibrustzcashWrapper; + +// Initialize proving context +long ctx = LibrustzcashWrapper.getInstance().librustzcashSaplingProvingCtxInit(); + +// Generate spend proof +byte[] ak = new byte[32]; +byte[] nsk = new byte[32]; +byte[] diversifier = new byte[11]; +byte[] rcm = new byte[32]; +byte[] ar = new byte[32]; +long value = 1000000L; +byte[] anchor = new byte[32]; +byte[] witness = new byte[1065]; // Merkle path +byte[] cv = new byte[32]; +byte[] rk = new byte[32]; +byte[] zkproof = new byte[192]; + +boolean result = LibrustzcashWrapper.getInstance().librustzcashSaplingSpendProof( + ctx, ak, nsk, diversifier, rcm, ar, value, anchor, witness, cv, rk, zkproof +); + +// Clean up +LibrustzcashWrapper.getInstance().librustzcashSaplingProvingCtxFree(ctx); +``` + +### Verify Sapling Proofs + +```java +import org.tron.common.zksnark.LibrustzcashWrapper; + +// Initialize verification context +long ctx = LibrustzcashWrapper.getInstance().librustzcashSaplingVerificationCtxInit(); + +// Verify spend +boolean spendValid = LibrustzcashWrapper.getInstance().librustzcashSaplingCheckSpend( + ctx, cv, anchor, nullifier, rk, zkproof, spendAuthSig, sighashValue +); + +// Verify output +boolean outputValid = LibrustzcashWrapper.getInstance().librustzcashSaplingCheckOutput( + ctx, cv, cm, ephemeralKey, zkproof +); + +// Final binding check +boolean valid = LibrustzcashWrapper.getInstance().librustzcashSaplingFinalCheck( + ctx, valueBalance, bindingSig, sighashValue +); + +// Clean up +LibrustzcashWrapper.getInstance().librustzcashSaplingVerificationCtxFree(ctx); +``` + +## Running Tests + +Run this from the project root directory: + +```bash +mvn test +``` + +Tests cover: +- Key derivation (ask→ak, nsk→nk, ivk derivation) +- Proof generation and verification +- Note encryption/decryption +- Merkle tree operations + +## Project Structure + +```text +zksnark-java-sdk/ +├── src/main/java/ # Java JNI wrappers +│ └── org/tron/common/ +│ ├── zksnark/ # Librustzcash, Libsodium, Wrapper classes +│ └── util/ # Utils (library loading) +├── src/main/resources/ +│ └── META-INF/native/ # Native libraries (osx64/, linux64/) +├── cpp/ # C++ JNI implementation +├── rust/librustzcash/ # Rust ZK-SNARK library (submodule) +└── pom.xml # Maven build configuration +``` + +## License + +Apache License 2.0 + +## Resources + +- [Zcash Sapling Protocol](https://zips.z.cash/protocol/protocol.pdf) +- [ZIP32 - Hierarchical Key Derivation](https://zips.z.cash/zip-0032) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 13c4e3a..898640c 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -6,6 +6,15 @@ set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set(CMAKE_BUILD_TYPE Release) SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -DNDEBUG") + +# macOS specific: Add libc++ include path for Clang +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + execute_process(COMMAND xcrun --show-sdk-path OUTPUT_VARIABLE CMAKE_OSX_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE) + include_directories("${CMAKE_OSX_SYSROOT}/usr/include/c++/v1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++") +endif() + find_package( Threads ) find_package(Java REQUIRED) # find_package(JNI REQUIRED) @@ -36,6 +45,44 @@ include_directories("${CMAKE_BINARY_DIR}") include_directories("${CMAKE_BINARY_DIR}/include") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../rust/librustzcash/librustzcash/include") +set(RUST_BUILD_TARGET "$ENV{RUST_BUILD_TARGET}") +if(NOT RUST_BUILD_TARGET) + if(APPLE) + if(CMAKE_OSX_ARCHITECTURES) + set(RUST_TARGET_ARCH "${CMAKE_OSX_ARCHITECTURES}") + else() + set(RUST_TARGET_ARCH "${CMAKE_SYSTEM_PROCESSOR}") + endif() + + if(RUST_TARGET_ARCH MATCHES ";") + message(FATAL_ERROR "Universal macOS builds are not supported. Set CMAKE_OSX_ARCHITECTURES to a single architecture or provide RUST_BUILD_TARGET.") + endif() + + if(RUST_TARGET_ARCH STREQUAL "arm64" OR RUST_TARGET_ARCH STREQUAL "aarch64") + set(RUST_BUILD_TARGET "aarch64-apple-darwin") + elseif(RUST_TARGET_ARCH STREQUAL "x86_64") + set(RUST_BUILD_TARGET "x86_64-apple-darwin") + else() + message(FATAL_ERROR "Unsupported macOS architecture '${RUST_TARGET_ARCH}'. Set RUST_BUILD_TARGET explicitly.") + endif() + elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$") + set(RUST_BUILD_TARGET "aarch64-unknown-linux-gnu") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$") + set(RUST_BUILD_TARGET "x86_64-unknown-linux-gnu") + endif() + endif() +endif() + +set(RUST_BUILD_COMMAND cargo build --package librustzcash --release) +set(RUST_LIBRARY_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../rust/librustzcash/target/release/librustzcash.a") +if(RUST_BUILD_TARGET) + list(APPEND RUST_BUILD_COMMAND --target ${RUST_BUILD_TARGET}) + set(RUST_LIBRARY_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../rust/librustzcash/target/${RUST_BUILD_TARGET}/release/librustzcash.a") +endif() + +message(STATUS "Using Rust target: ${RUST_BUILD_TARGET}") + add_custom_command( OUTPUT "${zksnark_jni_include}" COMMAND ${Java_JAVAC_EXECUTABLE} -verbose @@ -63,10 +110,7 @@ ExternalProject_Add( librustzcash DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" - BUILD_COMMAND cargo build - # COMMAND cargo build - --package librustzcash - --release + BUILD_COMMAND ${RUST_BUILD_COMMAND} BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../rust/librustzcash" INSTALL_COMMAND "" LOG_BUILD OFF) @@ -101,19 +145,42 @@ ADD_LIBRARY(zksnarkjni target_link_libraries(zksnarkjni ${CMAKE_THREAD_LIBS_INIT} - "${CMAKE_CURRENT_SOURCE_DIR}/../rust/librustzcash/target/release/librustzcash.a" + "${RUST_LIBRARY_PATH}" ${NACL_DIR}/src/libsodium/src/libsodium/.libs/libsodium.a ) add_dependencies(zksnarkjni rust) add_dependencies(zksnarkjni libsodium) -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - SET_TARGET_PROPERTIES( zksnarkjni PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,--wrap=memcpy" ) -endif() - -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - INSTALL(TARGETS zksnarkjni LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../src/main/resources/native-package/linux) +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + SET_TARGET_PROPERTIES( zksnarkjni PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,--wrap=memcpy -s" ) + # Linux: support both x86_64 and aarch64 + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + INSTALL(TARGETS zksnarkjni LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../src/main/resources/META-INF/native/linux64/aarch64) + else() + INSTALL(TARGETS zksnarkjni LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../src/main/resources/META-INF/native/linux64) + endif() +elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") + # macOS: support both x86_64 and arm64 + SET_TARGET_PROPERTIES(zksnarkjni PROPERTIES SUFFIX ".jnilib") + + # Create architecture-specific directories + if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") + set(MACOS_NATIVE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../src/main/resources/META-INF/native/osx64/aarch64") + else() + set(MACOS_NATIVE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../src/main/resources/META-INF/native/osx64") + endif() + + INSTALL(TARGETS zksnarkjni LIBRARY DESTINATION ${MACOS_NATIVE_DESTINATION}) + INSTALL(CODE + "execute_process( + COMMAND /usr/bin/codesign --force --sign - \"${MACOS_NATIVE_DESTINATION}/libzksnarkjni.jnilib\" + RESULT_VARIABLE codesign_result + ) + if(NOT codesign_result EQUAL 0) + message(FATAL_ERROR \"codesign failed with exit code \${codesign_result}: ${MACOS_NATIVE_DESTINATION}/libzksnarkjni.jnilib\") + endif()" + ) else() - INSTALL(TARGETS zksnarkjni LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../src/main/resources/native-package/macos) + message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}. Only Linux and macOS are supported.") endif() diff --git a/cpp/src/LibrustzcashJNIImpl.cpp b/cpp/src/LibrustzcashJNIImpl.cpp index 269a12b..bd31b22 100644 --- a/cpp/src/LibrustzcashJNIImpl.cpp +++ b/cpp/src/LibrustzcashJNIImpl.cpp @@ -4,14 +4,10 @@ #include "org_tron_common_zksnark_Librustzcash_LibrustzcashJNI.h" #include "librustzcash.h" -#include +#include jboolean bool2jboolean(bool b) { - if (b) { - return JNI_TRUE; - } else { - return JNI_FALSE; - } + return b ? JNI_TRUE : JNI_FALSE; } /* @@ -25,19 +21,24 @@ jboolean bool2jboolean(bool b) { */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashInitZksnarkParams (JNIEnv * env, jobject, jstring spend_path, jstring spend_hash, jstring output_path, jstring output_hash) { - const codeunit* sp = (const codeunit*) env->GetStringUTFChars(spend_path, nullptr); - const char* sh = (const char*) env->GetStringUTFChars(spend_hash, nullptr); - const codeunit* op = (const codeunit*) env->GetStringUTFChars(output_path, nullptr); - const char* oh = (const char*) env->GetStringUTFChars(output_hash, nullptr); - if (sp == NULL || sh == NULL || op == NULL || oh == NULL) + const char* sp = env->GetStringUTFChars(spend_path, nullptr); + const char* sh = env->GetStringUTFChars(spend_hash, nullptr); + const char* op = env->GetStringUTFChars(output_path, nullptr); + const char* oh = env->GetStringUTFChars(output_hash, nullptr); + if (sp == nullptr || sh == nullptr || op == nullptr || oh == nullptr) { + if (sp != nullptr) env->ReleaseStringUTFChars(spend_path, sp); + if (sh != nullptr) env->ReleaseStringUTFChars(spend_hash, sh); + if (op != nullptr) env->ReleaseStringUTFChars(output_path, op); + if (oh != nullptr) env->ReleaseStringUTFChars(output_hash, oh); return; } - librustzcash_init_zksnark_params(sp, (size_t) env->GetStringLength(spend_path), sh, op, - (size_t) env->GetStringLength(output_path), oh); - env->ReleaseStringUTFChars(spend_path, (const char*)sp); + librustzcash_init_zksnark_params( + reinterpret_cast(sp), std::strlen(sp), sh, + reinterpret_cast(op), std::strlen(op), oh); + env->ReleaseStringUTFChars(spend_path, sp); env->ReleaseStringUTFChars(spend_hash, sh); - env->ReleaseStringUTFChars(output_path, (const char* )op); + env->ReleaseStringUTFChars(output_path, op); env->ReleaseStringUTFChars(output_hash, oh); } @@ -48,20 +49,17 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashZip32XskMaster (JNIEnv * env, jobject, jbyteArray seed, jint seedlen, jbyteArray xsk_master) { -// void librustzcash_zip32_xsk_master( -// const unsigned char *seed, -// size_t seedlen, -// unsigned char *xsk_master -// ); - const unsigned char * s = reinterpret_cast(env->GetByteArrayElements(seed, nullptr)); - unsigned char * x = reinterpret_cast(env->GetByteArrayElements(xsk_master, nullptr)); - if (s == NULL || x == NULL) + const jbyte* s = env->GetByteArrayElements(seed, nullptr); + jbyte* x = env->GetByteArrayElements(xsk_master, nullptr); + if (s == nullptr || x == nullptr) { + if (s != nullptr) env->ReleaseByteArrayElements(seed, const_cast(s), JNI_ABORT); + if (x != nullptr) env->ReleaseByteArrayElements(xsk_master, x, JNI_ABORT); return; } - librustzcash_zip32_xsk_master(s, (size_t) seedlen, x); - env->ReleaseByteArrayElements(seed, (jbyte*)s, 0); - env->ReleaseByteArrayElements(xsk_master, (jbyte*)x, 0); + librustzcash_zip32_xsk_master(reinterpret_cast(s), static_cast(seedlen), reinterpret_cast(x)); + env->ReleaseByteArrayElements(seed, const_cast(s), JNI_ABORT); + env->ReleaseByteArrayElements(xsk_master, x, 0); } /* @@ -71,20 +69,17 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashZip32XskDerive (JNIEnv * env, jobject, jbyteArray xsk_parent, jint i, jbyteArray xsk_i) { -// void librustzcash_zip32_xsk_derive( -// const unsigned char *xsk_parent, -// uint32_t i, -// unsigned char *xsk_i -// ); - const unsigned char * xp = reinterpret_cast(env->GetByteArrayElements(xsk_parent, nullptr)); - unsigned char * xi = reinterpret_cast(env->GetByteArrayElements(xsk_i, nullptr)); - if (xp == NULL || xi == NULL) + const jbyte* xp = env->GetByteArrayElements(xsk_parent, nullptr); + jbyte* xi = env->GetByteArrayElements(xsk_i, nullptr); + if (xp == nullptr || xi == nullptr) { + if (xp != nullptr) env->ReleaseByteArrayElements(xsk_parent, const_cast(xp), JNI_ABORT); + if (xi != nullptr) env->ReleaseByteArrayElements(xsk_i, xi, JNI_ABORT); return; } - librustzcash_zip32_xsk_derive(xp, (uint32_t) i, xi); - env->ReleaseByteArrayElements(xsk_parent, (jbyte*)xp, 0); - env->ReleaseByteArrayElements(xsk_i, (jbyte*)xi, 0); + librustzcash_zip32_xsk_derive(reinterpret_cast(xp), static_cast(i), reinterpret_cast(xi)); + env->ReleaseByteArrayElements(xsk_parent, const_cast(xp), JNI_ABORT); + env->ReleaseByteArrayElements(xsk_i, xi, 0); } /* @@ -94,25 +89,27 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashZip32XfvkAddress (JNIEnv * env, jobject, jbyteArray xfvk, jbyteArray j, jbyteArray j_ret, jbyteArray addr_ret) { -// bool librustzcash_zip32_xfvk_address( -// const unsigned char *xfvk, -// const unsigned char *j, -// unsigned char *j_ret, -// unsigned char *addr_ret -// ); - const unsigned char * x = (const unsigned char *) env->GetByteArrayElements(xfvk, nullptr); - const unsigned char * jPoint = (const unsigned char *) env->GetByteArrayElements(j, nullptr); - unsigned char * jr = (unsigned char *) env->GetByteArrayElements(j_ret, nullptr); - unsigned char * a = (unsigned char *) env->GetByteArrayElements(addr_ret, nullptr); - if (x == NULL || jPoint == NULL || jr == NULL || a == NULL) + const jbyte* x = env->GetByteArrayElements(xfvk, nullptr); + const jbyte* jPoint = env->GetByteArrayElements(j, nullptr); + jbyte* jr = env->GetByteArrayElements(j_ret, nullptr); + jbyte* a = env->GetByteArrayElements(addr_ret, nullptr); + if (x == nullptr || jPoint == nullptr || jr == nullptr || a == nullptr) { + if (x != nullptr) env->ReleaseByteArrayElements(xfvk, const_cast(x), JNI_ABORT); + if (jPoint != nullptr) env->ReleaseByteArrayElements(j, const_cast(jPoint), JNI_ABORT); + if (jr != nullptr) env->ReleaseByteArrayElements(j_ret, jr, JNI_ABORT); + if (a != nullptr) env->ReleaseByteArrayElements(addr_ret, a, JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_zip32_xfvk_address(x, jPoint, jr, a)); - env->ReleaseByteArrayElements(xfvk, (jbyte*)x, 0); - env->ReleaseByteArrayElements(j, (jbyte*)jPoint, 0); - env->ReleaseByteArrayElements(j_ret, (jbyte*)jr, 0); - env->ReleaseByteArrayElements(addr_ret, (jbyte*)a, 0); + jboolean jb = bool2jboolean(librustzcash_zip32_xfvk_address( + reinterpret_cast(x), + reinterpret_cast(jPoint), + reinterpret_cast(jr), + reinterpret_cast(a))); + env->ReleaseByteArrayElements(xfvk, const_cast(x), JNI_ABORT); + env->ReleaseByteArrayElements(j, const_cast(jPoint), JNI_ABORT); + env->ReleaseByteArrayElements(j_ret, jr, 0); + env->ReleaseByteArrayElements(addr_ret, a, 0); return jb; } @@ -123,17 +120,17 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashAskToAk (JNIEnv * env, jobject, jbyteArray ask, jbyteArray result) { -// void librustzcash_ask_to_ak(const unsigned char *ask, unsigned char *result); - - const unsigned char * a = (const unsigned char *) env->GetByteArrayElements(ask, nullptr); - unsigned char * r = (unsigned char *) env-> GetByteArrayElements(result, nullptr); - if (a == NULL || r == NULL) + const jbyte* a = env->GetByteArrayElements(ask, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (a == nullptr || r == nullptr) { + if (a != nullptr) env->ReleaseByteArrayElements(ask, const_cast(a), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); return; } - librustzcash_ask_to_ak(a,r); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(ask,(jbyte*)a, 0); + librustzcash_ask_to_ak(reinterpret_cast(a), reinterpret_cast(r)); + env->ReleaseByteArrayElements(ask, const_cast(a), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); } /* @@ -143,35 +140,37 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingComputeNf (JNIEnv * env, jobject, jbyteArray diversifier, jbyteArray pk_d, jlong value, jbyteArray r, jbyteArray ak, jbyteArray nk, jlong position, jbyteArray result) { -// bool librustzcash_sapling_compute_nf( -// const unsigned char *diversifier, -// const unsigned char *pk_d, -// const uint64_t value, -// const unsigned char *r, -// const unsigned char *ak, -// const unsigned char *nk, -// const uint64_t position, -// unsigned char *result -// ); - - const unsigned char * d = (const unsigned char *) env->GetByteArrayElements(diversifier, nullptr); - const unsigned char * p = (const unsigned char *) env->GetByteArrayElements(pk_d, nullptr); - const unsigned char * rPoint = (const unsigned char *) env->GetByteArrayElements(r, nullptr); - const unsigned char * a = (const unsigned char *) env->GetByteArrayElements(ak, nullptr); - const unsigned char * n = (const unsigned char *) env->GetByteArrayElements(nk, nullptr); - unsigned char * rs = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (d == NULL || p == NULL || rPoint == NULL || a == NULL || n == NULL || rs == NULL) + const jbyte* d = env->GetByteArrayElements(diversifier, nullptr); + const jbyte* p = env->GetByteArrayElements(pk_d, nullptr); + const jbyte* rPoint = env->GetByteArrayElements(r, nullptr); + const jbyte* a = env->GetByteArrayElements(ak, nullptr); + const jbyte* n = env->GetByteArrayElements(nk, nullptr); + jbyte* rs = env->GetByteArrayElements(result, nullptr); + if (d == nullptr || p == nullptr || rPoint == nullptr || a == nullptr || n == nullptr || rs == nullptr) { + if (d != nullptr) env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + if (p != nullptr) env->ReleaseByteArrayElements(pk_d, const_cast(p), JNI_ABORT); + if (rPoint != nullptr) env->ReleaseByteArrayElements(r, const_cast(rPoint), JNI_ABORT); + if (a != nullptr) env->ReleaseByteArrayElements(ak, const_cast(a), JNI_ABORT); + if (n != nullptr) env->ReleaseByteArrayElements(nk, const_cast(n), JNI_ABORT); + if (rs != nullptr) env->ReleaseByteArrayElements(result, rs, JNI_ABORT); return; } - librustzcash_sapling_compute_nf(d,p,static_cast((int64_t) value), - rPoint,a,n,static_cast((int64_t) position),rs); - env->ReleaseByteArrayElements(result,(jbyte*)rs,0); - env->ReleaseByteArrayElements(diversifier,(jbyte*)d,0); - env->ReleaseByteArrayElements(pk_d,(jbyte*)p,0); - env->ReleaseByteArrayElements(r,(jbyte*)rPoint,0); - env->ReleaseByteArrayElements(ak,(jbyte*)a,0); - env->ReleaseByteArrayElements(nk,(jbyte*)n,0); + librustzcash_sapling_compute_nf( + reinterpret_cast(d), + reinterpret_cast(p), + static_cast(value), + reinterpret_cast(rPoint), + reinterpret_cast(a), + reinterpret_cast(n), + static_cast(position), + reinterpret_cast(rs)); + env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + env->ReleaseByteArrayElements(pk_d, const_cast(p), JNI_ABORT); + env->ReleaseByteArrayElements(r, const_cast(rPoint), JNI_ABORT); + env->ReleaseByteArrayElements(ak, const_cast(a), JNI_ABORT); + env->ReleaseByteArrayElements(nk, const_cast(n), JNI_ABORT); + env->ReleaseByteArrayElements(result, rs, 0); } /* @@ -181,17 +180,17 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashNskToNk (JNIEnv * env, jobject, jbyteArray nsk, jbyteArray result) { -// void librustzcash_nsk_to_nk(const unsigned char *nsk, unsigned char *result); - - const unsigned char * n = (const unsigned char *) env->GetByteArrayElements(nsk, nullptr); - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (r == NULL || n == NULL) + const jbyte* n = env->GetByteArrayElements(nsk, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (r == nullptr || n == nullptr) { + if (n != nullptr) env->ReleaseByteArrayElements(nsk, const_cast(n), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); return; } - librustzcash_nsk_to_nk(n,r); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(nsk,(jbyte*)n,0); + librustzcash_nsk_to_nk(reinterpret_cast(n), reinterpret_cast(r)); + env->ReleaseByteArrayElements(nsk, const_cast(n), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); } /* @@ -201,17 +200,13 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingGenerateR (JNIEnv * env, jobject, jbyteArray result) { -// void librustzcash_sapling_generate_r( -// unsigned char *result -// ); - - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (r == NULL) + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (r == nullptr) { return; } - librustzcash_sapling_generate_r(r); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); + librustzcash_sapling_generate_r(reinterpret_cast(r)); + env->ReleaseByteArrayElements(result, r, 0); } /* @@ -221,23 +216,23 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingKaDerivepublic (JNIEnv * env, jobject, jbyteArray diversifier, jbyteArray esk, jbyteArray result) { -// bool librustzcash_sapling_ka_derivepublic( -// const unsigned char *diversifier, -// const unsigned char *esk, -// unsigned char *result -// ); - - const unsigned char * d = (const unsigned char *) env->GetByteArrayElements(diversifier, nullptr); - const unsigned char * e = (const unsigned char *) env->GetByteArrayElements(esk, nullptr); - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (d == NULL || e == NULL || r == NULL) + const jbyte* d = env->GetByteArrayElements(diversifier, nullptr); + const jbyte* e = env->GetByteArrayElements(esk, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (d == nullptr || e == nullptr || r == nullptr) { + if (d != nullptr) env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + if (e != nullptr) env->ReleaseByteArrayElements(esk, const_cast(e), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_ka_derivepublic(d,e,r)); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(diversifier,(jbyte*)d,0); - env->ReleaseByteArrayElements(esk,(jbyte*)e,0); + jboolean jb = bool2jboolean(librustzcash_sapling_ka_derivepublic( + reinterpret_cast(d), + reinterpret_cast(e), + reinterpret_cast(r))); + env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + env->ReleaseByteArrayElements(esk, const_cast(e), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); return jb; } @@ -248,19 +243,23 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashCrhIvk (JNIEnv *env, jobject, jbyteArray ak, jbyteArray nk, jbyteArray result) { -// void librustzcash_crh_ivk(const unsigned char *ak, const unsigned char *nk, unsigned char *result); - - const unsigned char * a = (const unsigned char *) env->GetByteArrayElements(ak, nullptr); - const unsigned char * n = (const unsigned char *) env->GetByteArrayElements(nk, nullptr); - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (r == NULL || a == NULL || n == NULL) + const jbyte* a = env->GetByteArrayElements(ak, nullptr); + const jbyte* n = env->GetByteArrayElements(nk, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (r == nullptr || a == nullptr || n == nullptr) { + if (a != nullptr) env->ReleaseByteArrayElements(ak, const_cast(a), JNI_ABORT); + if (n != nullptr) env->ReleaseByteArrayElements(nk, const_cast(n), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); return; } - librustzcash_crh_ivk(a,n,r); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(ak,(jbyte*)a,0); - env->ReleaseByteArrayElements(nk,(jbyte*)n,0); + librustzcash_crh_ivk( + reinterpret_cast(a), + reinterpret_cast(n), + reinterpret_cast(r)); + env->ReleaseByteArrayElements(ak, const_cast(a), JNI_ABORT); + env->ReleaseByteArrayElements(nk, const_cast(n), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); } /* @@ -274,19 +273,24 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingKaAgree (JNIEnv * env, jobject, jbyteArray p, jbyteArray sk, jbyteArray result) { - - const unsigned char * pPoint = reinterpret_cast(env->GetByteArrayElements(p, nullptr)); - const unsigned char * skPoint = reinterpret_cast(env->GetByteArrayElements(sk, nullptr)); - unsigned char * r = reinterpret_cast(env->GetByteArrayElements(result, nullptr)); - if (r == NULL || pPoint == NULL || skPoint == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_sapling_ka_agree(pPoint,skPoint,r)); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(p,(jbyte*)pPoint,0); - env->ReleaseByteArrayElements(sk,(jbyte*)skPoint,0); - return jb; + const jbyte* pPoint = env->GetByteArrayElements(p, nullptr); + const jbyte* skPoint = env->GetByteArrayElements(sk, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (r == nullptr || pPoint == nullptr || skPoint == nullptr) + { + if (pPoint != nullptr) env->ReleaseByteArrayElements(p, const_cast(pPoint), JNI_ABORT); + if (skPoint != nullptr) env->ReleaseByteArrayElements(sk, const_cast(skPoint), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_sapling_ka_agree( + reinterpret_cast(pPoint), + reinterpret_cast(skPoint), + reinterpret_cast(r))); + env->ReleaseByteArrayElements(p, const_cast(pPoint), JNI_ABORT); + env->ReleaseByteArrayElements(sk, const_cast(skPoint), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); + return jb; } /* @@ -296,14 +300,14 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashCheckDiversifier (JNIEnv * env, jobject, jbyteArray diversifier) { - const unsigned char * d = reinterpret_cast(env->GetByteArrayElements(diversifier, nullptr)); - if (d == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_check_diversifier(d)); - env->ReleaseByteArrayElements(diversifier,(jbyte*)d,0); - return jb; + const jbyte* d = env->GetByteArrayElements(diversifier, nullptr); + if (d == nullptr) + { + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_check_diversifier(reinterpret_cast(d))); + env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + return jb; } /* @@ -313,19 +317,24 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashIvkToPkd (JNIEnv * env, jobject, jbyteArray ivk, jbyteArray diversifier, jbyteArray result) { - - const unsigned char * i = reinterpret_cast(env->GetByteArrayElements(ivk, nullptr)); - const unsigned char * d = reinterpret_cast(env->GetByteArrayElements(diversifier, nullptr)); - unsigned char * r = reinterpret_cast(env->GetByteArrayElements(result, nullptr)); - if (r == NULL || i == NULL || d == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_ivk_to_pkd(i,d,r)); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(ivk,(jbyte*)i,0); - env->ReleaseByteArrayElements(diversifier,(jbyte*)d,0); - return jb; + const jbyte* i = env->GetByteArrayElements(ivk, nullptr); + const jbyte* d = env->GetByteArrayElements(diversifier, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (r == nullptr || i == nullptr || d == nullptr) + { + if (i != nullptr) env->ReleaseByteArrayElements(ivk, const_cast(i), JNI_ABORT); + if (d != nullptr) env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_ivk_to_pkd( + reinterpret_cast(i), + reinterpret_cast(d), + reinterpret_cast(r))); + env->ReleaseByteArrayElements(ivk, const_cast(i), JNI_ABORT); + env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); + return jb; } /* @@ -335,21 +344,29 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingComputeCm (JNIEnv * env, jobject, jbyteArray diversifier, jbyteArray pk_d, jlong value, jbyteArray r, jbyteArray result) { - - const unsigned char * d = reinterpret_cast(env->GetByteArrayElements(diversifier, nullptr)); - const unsigned char * p = reinterpret_cast(env->GetByteArrayElements(pk_d, nullptr)); - const unsigned char * rPonit = reinterpret_cast(env->GetByteArrayElements(r, nullptr)); - unsigned char * rs = reinterpret_cast(env->GetByteArrayElements(result, nullptr)); - if (rs == NULL || d == NULL || p == NULL || rPonit == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_sapling_compute_cm(d,p,(const uint64_t) value,rPonit,rs)); - env->ReleaseByteArrayElements(result,(jbyte*)rs,0); - env->ReleaseByteArrayElements(diversifier,(jbyte*)d,0); - env->ReleaseByteArrayElements(pk_d,(jbyte*)p,0); - env->ReleaseByteArrayElements(r,(jbyte*)rPonit,0); - return jb; + const jbyte* d = env->GetByteArrayElements(diversifier, nullptr); + const jbyte* p = env->GetByteArrayElements(pk_d, nullptr); + const jbyte* rPoint = env->GetByteArrayElements(r, nullptr); + jbyte* rs = env->GetByteArrayElements(result, nullptr); + if (rs == nullptr || d == nullptr || p == nullptr || rPoint == nullptr) + { + if (d != nullptr) env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + if (p != nullptr) env->ReleaseByteArrayElements(pk_d, const_cast(p), JNI_ABORT); + if (rPoint != nullptr) env->ReleaseByteArrayElements(r, const_cast(rPoint), JNI_ABORT); + if (rs != nullptr) env->ReleaseByteArrayElements(result, rs, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_sapling_compute_cm( + reinterpret_cast(d), + reinterpret_cast(p), + static_cast(value), + reinterpret_cast(rPoint), + reinterpret_cast(rs))); + env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + env->ReleaseByteArrayElements(pk_d, const_cast(p), JNI_ABORT); + env->ReleaseByteArrayElements(r, const_cast(rPoint), JNI_ABORT); + env->ReleaseByteArrayElements(result, rs, 0); + return jb; } /* @@ -359,7 +376,7 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jlong JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingProvingCtxInit (JNIEnv *, jobject) { - return (jlong) librustzcash_sapling_proving_ctx_init(); + return reinterpret_cast(librustzcash_sapling_proving_ctx_init()); } /* @@ -368,37 +385,81 @@ JNIEXPORT jlong JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzc * Signature: (J[B[B[B[B[BJ[B[B[B[B[B)Z */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingSpendProof - (JNIEnv * env, jobject, jlong ctx, jbyteArray ak, jbyteArray nsk, jbyteArray diversifier, jbyteArray rcm,jbyteArray ar, + (JNIEnv * env, jobject, jlong ctx, jbyteArray ak, jbyteArray nsk, jbyteArray diversifier, jbyteArray rcm, jbyteArray ar, jlong value, jbyteArray anchor, jbyteArray witness, jbyteArray cv, jbyteArray rk, jbyteArray zkproof) { + // Validate ctx handle + if (ctx == 0) { + return JNI_FALSE; + } - const unsigned char * akPoint = reinterpret_cast(env->GetByteArrayElements(ak, nullptr)); - const unsigned char * nskPoint = reinterpret_cast(env->GetByteArrayElements(nsk, nullptr)); - const unsigned char * dPoint = reinterpret_cast(env->GetByteArrayElements(diversifier, nullptr)); - const unsigned char * rcmPoint = reinterpret_cast(env->GetByteArrayElements(rcm, nullptr)); - const unsigned char * arPoint = reinterpret_cast(env->GetByteArrayElements(ar, nullptr)); - const unsigned char * anchorPoint = reinterpret_cast(env->GetByteArrayElements(anchor, nullptr)); - const unsigned char * wPoint = reinterpret_cast(env->GetByteArrayElements(witness, nullptr)); - unsigned char * cvPoint = reinterpret_cast(env->GetByteArrayElements(cv, nullptr)); - unsigned char * rkPoint = reinterpret_cast(env->GetByteArrayElements(rk, nullptr)); - unsigned char * zPoint = reinterpret_cast(env->GetByteArrayElements(zkproof, nullptr)); - if (akPoint == NULL || nskPoint == NULL || dPoint == NULL || rcmPoint == NULL || arPoint == NULL || anchorPoint == NULL - || wPoint == NULL || cvPoint == NULL || rkPoint == NULL || zPoint == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_sapling_spend_proof((void *)ctx,akPoint,nskPoint,dPoint,rcmPoint,arPoint, - (const uint64_t) value,anchorPoint,wPoint,cvPoint,rkPoint,zPoint)); - env->ReleaseByteArrayElements(ak,(jbyte*)akPoint,0); - env->ReleaseByteArrayElements(nsk,(jbyte*)nskPoint,0); - env->ReleaseByteArrayElements(diversifier,(jbyte*)dPoint,0); - env->ReleaseByteArrayElements(rcm,(jbyte*)rcmPoint,0); - env->ReleaseByteArrayElements(ar,(jbyte*)arPoint,0); - env->ReleaseByteArrayElements(anchor,(jbyte*)anchorPoint,0); - env->ReleaseByteArrayElements(witness,(jbyte*)wPoint,0); - env->ReleaseByteArrayElements(cv,(jbyte*)cvPoint,0); - env->ReleaseByteArrayElements(rk,(jbyte*)rkPoint,0); - env->ReleaseByteArrayElements(zkproof,(jbyte*)zPoint,0); - return jb; + // Validate array lengths before accessing elements + jsize witness_len = env->GetArrayLength(witness); + if (witness_len < 1065) { + return JNI_FALSE; + } + jsize cv_len = env->GetArrayLength(cv); + if (cv_len < 32) { + return JNI_FALSE; + } + jsize rk_len = env->GetArrayLength(rk); + if (rk_len < 32) { + return JNI_FALSE; + } + jsize zkproof_len = env->GetArrayLength(zkproof); + if (zkproof_len < 192) { + return JNI_FALSE; + } + + const jbyte* akPoint = env->GetByteArrayElements(ak, nullptr); + const jbyte* nskPoint = env->GetByteArrayElements(nsk, nullptr); + const jbyte* dPoint = env->GetByteArrayElements(diversifier, nullptr); + const jbyte* rcmPoint = env->GetByteArrayElements(rcm, nullptr); + const jbyte* arPoint = env->GetByteArrayElements(ar, nullptr); + const jbyte* anchorPoint = env->GetByteArrayElements(anchor, nullptr); + const jbyte* wPoint = env->GetByteArrayElements(witness, nullptr); + jbyte* cvPoint = env->GetByteArrayElements(cv, nullptr); + jbyte* rkPoint = env->GetByteArrayElements(rk, nullptr); + jbyte* zPoint = env->GetByteArrayElements(zkproof, nullptr); + if (akPoint == nullptr || nskPoint == nullptr || dPoint == nullptr || rcmPoint == nullptr || + arPoint == nullptr || anchorPoint == nullptr || wPoint == nullptr || + cvPoint == nullptr || rkPoint == nullptr || zPoint == nullptr) + { + if (akPoint != nullptr) env->ReleaseByteArrayElements(ak, const_cast(akPoint), JNI_ABORT); + if (nskPoint != nullptr) env->ReleaseByteArrayElements(nsk, const_cast(nskPoint), JNI_ABORT); + if (dPoint != nullptr) env->ReleaseByteArrayElements(diversifier, const_cast(dPoint), JNI_ABORT); + if (rcmPoint != nullptr) env->ReleaseByteArrayElements(rcm, const_cast(rcmPoint), JNI_ABORT); + if (arPoint != nullptr) env->ReleaseByteArrayElements(ar, const_cast(arPoint), JNI_ABORT); + if (anchorPoint != nullptr) env->ReleaseByteArrayElements(anchor, const_cast(anchorPoint), JNI_ABORT); + if (wPoint != nullptr) env->ReleaseByteArrayElements(witness, const_cast(wPoint), JNI_ABORT); + if (cvPoint != nullptr) env->ReleaseByteArrayElements(cv, cvPoint, JNI_ABORT); + if (rkPoint != nullptr) env->ReleaseByteArrayElements(rk, rkPoint, JNI_ABORT); + if (zPoint != nullptr) env->ReleaseByteArrayElements(zkproof, zPoint, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_sapling_spend_proof( + reinterpret_cast(ctx), + reinterpret_cast(akPoint), + reinterpret_cast(nskPoint), + reinterpret_cast(dPoint), + reinterpret_cast(rcmPoint), + reinterpret_cast(arPoint), + static_cast(value), + reinterpret_cast(anchorPoint), + reinterpret_cast(wPoint), + reinterpret_cast(cvPoint), + reinterpret_cast(rkPoint), + reinterpret_cast(zPoint))); + env->ReleaseByteArrayElements(ak, const_cast(akPoint), JNI_ABORT); + env->ReleaseByteArrayElements(nsk, const_cast(nskPoint), JNI_ABORT); + env->ReleaseByteArrayElements(diversifier, const_cast(dPoint), JNI_ABORT); + env->ReleaseByteArrayElements(rcm, const_cast(rcmPoint), JNI_ABORT); + env->ReleaseByteArrayElements(ar, const_cast(arPoint), JNI_ABORT); + env->ReleaseByteArrayElements(anchor, const_cast(anchorPoint), JNI_ABORT); + env->ReleaseByteArrayElements(witness, const_cast(wPoint), JNI_ABORT); + env->ReleaseByteArrayElements(cv, cvPoint, 0); + env->ReleaseByteArrayElements(rk, rkPoint, 0); + env->ReleaseByteArrayElements(zkproof, zPoint, 0); + return jb; } /* @@ -408,24 +469,53 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingOutputProof (JNIEnv * env, jobject, jlong ctx, jbyteArray esk, jbyteArray diversifier, jbyteArray pk_d, jbyteArray rcm, jlong value, jbyteArray cv, jbyteArray zkproof) { - const unsigned char * e = reinterpret_cast(env->GetByteArrayElements(esk, nullptr)); - const unsigned char * d = reinterpret_cast(env->GetByteArrayElements(diversifier, nullptr)); - const unsigned char * p = reinterpret_cast(env->GetByteArrayElements(pk_d, nullptr)); - const unsigned char * r = reinterpret_cast(env->GetByteArrayElements(rcm, nullptr)); - unsigned char * c = reinterpret_cast(env->GetByteArrayElements(cv, nullptr)); - unsigned char * z = reinterpret_cast(env->GetByteArrayElements(zkproof, nullptr)); - if (e == NULL || d == NULL || p == NULL || r == NULL || c == NULL || z == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_sapling_output_proof((void *)ctx,e,d,p,r,(const uint64_t) value,c,z)); - env->ReleaseByteArrayElements(esk,(jbyte*)e,0); - env->ReleaseByteArrayElements(diversifier,(jbyte*)d,0); - env->ReleaseByteArrayElements(pk_d,(jbyte*)p,0); - env->ReleaseByteArrayElements(rcm,(jbyte*)r,0); - env->ReleaseByteArrayElements(cv,(jbyte*)c,0); - env->ReleaseByteArrayElements(zkproof,(jbyte*)z,0); - return jb; + // Validate ctx handle + if (ctx == 0) { + return JNI_FALSE; + } + + // Validate array lengths before accessing elements + jsize cv_len = env->GetArrayLength(cv); + if (cv_len < 32) { + return JNI_FALSE; + } + jsize zkproof_len = env->GetArrayLength(zkproof); + if (zkproof_len < 192) { + return JNI_FALSE; + } + + const jbyte* e = env->GetByteArrayElements(esk, nullptr); + const jbyte* d = env->GetByteArrayElements(diversifier, nullptr); + const jbyte* p = env->GetByteArrayElements(pk_d, nullptr); + const jbyte* r = env->GetByteArrayElements(rcm, nullptr); + jbyte* c = env->GetByteArrayElements(cv, nullptr); + jbyte* z = env->GetByteArrayElements(zkproof, nullptr); + if (e == nullptr || d == nullptr || p == nullptr || r == nullptr || c == nullptr || z == nullptr) + { + if (e != nullptr) env->ReleaseByteArrayElements(esk, const_cast(e), JNI_ABORT); + if (d != nullptr) env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + if (p != nullptr) env->ReleaseByteArrayElements(pk_d, const_cast(p), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(rcm, const_cast(r), JNI_ABORT); + if (c != nullptr) env->ReleaseByteArrayElements(cv, c, JNI_ABORT); + if (z != nullptr) env->ReleaseByteArrayElements(zkproof, z, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_sapling_output_proof( + reinterpret_cast(ctx), + reinterpret_cast(e), + reinterpret_cast(d), + reinterpret_cast(p), + reinterpret_cast(r), + static_cast(value), + reinterpret_cast(c), + reinterpret_cast(z))); + env->ReleaseByteArrayElements(esk, const_cast(e), JNI_ABORT); + env->ReleaseByteArrayElements(diversifier, const_cast(d), JNI_ABORT); + env->ReleaseByteArrayElements(pk_d, const_cast(p), JNI_ABORT); + env->ReleaseByteArrayElements(rcm, const_cast(r), JNI_ABORT); + env->ReleaseByteArrayElements(cv, c, 0); + env->ReleaseByteArrayElements(zkproof, z, 0); + return jb; } /* @@ -435,21 +525,28 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingSpendSig (JNIEnv * env, jobject, jbyteArray ask, jbyteArray ar, jbyteArray sighash, jbyteArray result) { - - const unsigned char * askPoint = reinterpret_cast(env->GetByteArrayElements(ask, nullptr)); - const unsigned char * arPoint = reinterpret_cast(env->GetByteArrayElements(ar, nullptr)); - const unsigned char * s = reinterpret_cast(env->GetByteArrayElements(sighash, nullptr)); - unsigned char * r = reinterpret_cast(env->GetByteArrayElements(result, nullptr)); - if (askPoint == NULL || arPoint == NULL || s == NULL || r == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_sapling_spend_sig(askPoint,arPoint,s,r)); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(ask,(jbyte*)askPoint,0); - env->ReleaseByteArrayElements(ar,(jbyte*)arPoint,0); - env->ReleaseByteArrayElements(sighash,(jbyte*)s,0); - return jb; + const jbyte* askPoint = env->GetByteArrayElements(ask, nullptr); + const jbyte* arPoint = env->GetByteArrayElements(ar, nullptr); + const jbyte* s = env->GetByteArrayElements(sighash, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (askPoint == nullptr || arPoint == nullptr || s == nullptr || r == nullptr) + { + if (askPoint != nullptr) env->ReleaseByteArrayElements(ask, const_cast(askPoint), JNI_ABORT); + if (arPoint != nullptr) env->ReleaseByteArrayElements(ar, const_cast(arPoint), JNI_ABORT); + if (s != nullptr) env->ReleaseByteArrayElements(sighash, const_cast(s), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_sapling_spend_sig( + reinterpret_cast(askPoint), + reinterpret_cast(arPoint), + reinterpret_cast(s), + reinterpret_cast(r))); + env->ReleaseByteArrayElements(ask, const_cast(askPoint), JNI_ABORT); + env->ReleaseByteArrayElements(ar, const_cast(arPoint), JNI_ABORT); + env->ReleaseByteArrayElements(sighash, const_cast(s), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); + return jb; } /* @@ -459,17 +556,27 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingBindingSig (JNIEnv * env, jobject, jlong ctx, jlong valueBalance, jbyteArray sighash, jbyteArray result) { + // Validate ctx handle + if (ctx == 0) { + return JNI_FALSE; + } - const unsigned char * s = reinterpret_cast(env->GetByteArrayElements(sighash, nullptr)); - unsigned char * r = reinterpret_cast(env->GetByteArrayElements(result, nullptr)); - if (s == NULL || r == NULL) - { - return JNI_FALSE; - } - jboolean jb = bool2jboolean(librustzcash_sapling_binding_sig((void *)ctx,(int64_t) valueBalance,s,r)); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(sighash,(jbyte*)s,0); - return jb; + const jbyte* s = env->GetByteArrayElements(sighash, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (s == nullptr || r == nullptr) + { + if (s != nullptr) env->ReleaseByteArrayElements(sighash, const_cast(s), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); + return JNI_FALSE; + } + jboolean jb = bool2jboolean(librustzcash_sapling_binding_sig( + reinterpret_cast(ctx), + static_cast(valueBalance), + reinterpret_cast(s), + reinterpret_cast(r))); + env->ReleaseByteArrayElements(sighash, const_cast(s), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); + return jb; } /* @@ -479,7 +586,10 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingProvingCtxFree (JNIEnv *, jobject, jlong ctx) { - librustzcash_sapling_proving_ctx_free((void *)ctx); + if (ctx == 0) { + return; + } + librustzcash_sapling_proving_ctx_free(reinterpret_cast(ctx)); } /* @@ -493,8 +603,7 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT jlong JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingVerificationCtxInit (JNIEnv *, jobject) { -// void * librustzcash_sapling_verification_ctx_init(); - return (jlong) librustzcash_sapling_verification_ctx_init(); + return reinterpret_cast(librustzcash_sapling_verification_ctx_init()); } /* @@ -504,35 +613,45 @@ JNIEXPORT jlong JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzc */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingCheckSpend (JNIEnv * env, jobject, jlong ctx, jbyteArray cv, jbyteArray anchor, jbyteArray nullifier, jbyteArray rk, jbyteArray zkproof, jbyteArray spendAuthSig, jbyteArray sighashValue) { -// bool librustzcash_sapling_check_spend( -// void *ctx, -// const unsigned char *cv, -// const unsigned char *anchor, -// const unsigned char *nullifier, -// const unsigned char *rk, -// const unsigned char *zkproof, -// const unsigned char *spendAuthSig, -// const unsigned char *sighashValue -// ); - const unsigned char * c = (const unsigned char *) env->GetByteArrayElements(cv, nullptr); - const unsigned char * a = (const unsigned char *) env->GetByteArrayElements(anchor, nullptr); - const unsigned char * n = (const unsigned char *) env->GetByteArrayElements(nullifier, nullptr); - const unsigned char * r = (const unsigned char *) env->GetByteArrayElements(rk, nullptr); - const unsigned char * z = (const unsigned char *) env->GetByteArrayElements(zkproof, nullptr); - const unsigned char * sp = (const unsigned char *) env->GetByteArrayElements(spendAuthSig, nullptr); - const unsigned char * si = (const unsigned char *) env->GetByteArrayElements(sighashValue, nullptr); - if (c == NULL || a == NULL || n == NULL || r == NULL || z == NULL || sp == NULL || si == NULL) + // Validate ctx handle + if (ctx == 0) { + return JNI_FALSE; + } + + const jbyte* c = env->GetByteArrayElements(cv, nullptr); + const jbyte* a = env->GetByteArrayElements(anchor, nullptr); + const jbyte* n = env->GetByteArrayElements(nullifier, nullptr); + const jbyte* r = env->GetByteArrayElements(rk, nullptr); + const jbyte* z = env->GetByteArrayElements(zkproof, nullptr); + const jbyte* sp = env->GetByteArrayElements(spendAuthSig, nullptr); + const jbyte* si = env->GetByteArrayElements(sighashValue, nullptr); + if (c == nullptr || a == nullptr || n == nullptr || r == nullptr || z == nullptr || sp == nullptr || si == nullptr) { + if (c != nullptr) env->ReleaseByteArrayElements(cv, const_cast(c), JNI_ABORT); + if (a != nullptr) env->ReleaseByteArrayElements(anchor, const_cast(a), JNI_ABORT); + if (n != nullptr) env->ReleaseByteArrayElements(nullifier, const_cast(n), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(rk, const_cast(r), JNI_ABORT); + if (z != nullptr) env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); + if (sp != nullptr) env->ReleaseByteArrayElements(spendAuthSig, const_cast(sp), JNI_ABORT); + if (si != nullptr) env->ReleaseByteArrayElements(sighashValue, const_cast(si), JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_check_spend((void *) ctx,c,a,n,r,z,sp,si)); - env->ReleaseByteArrayElements(cv,(jbyte*)c,0); - env->ReleaseByteArrayElements(anchor,(jbyte*)a,0); - env->ReleaseByteArrayElements(nullifier,(jbyte*)n,0); - env->ReleaseByteArrayElements(rk,(jbyte*)r,0); - env->ReleaseByteArrayElements(zkproof,(jbyte*)z,0); - env->ReleaseByteArrayElements(spendAuthSig,(jbyte*)sp,0); - env->ReleaseByteArrayElements(sighashValue,(jbyte*)si,0); + jboolean jb = bool2jboolean(librustzcash_sapling_check_spend( + reinterpret_cast(ctx), + reinterpret_cast(c), + reinterpret_cast(a), + reinterpret_cast(n), + reinterpret_cast(r), + reinterpret_cast(z), + reinterpret_cast(sp), + reinterpret_cast(si))); + env->ReleaseByteArrayElements(cv, const_cast(c), JNI_ABORT); + env->ReleaseByteArrayElements(anchor, const_cast(a), JNI_ABORT); + env->ReleaseByteArrayElements(nullifier, const_cast(n), JNI_ABORT); + env->ReleaseByteArrayElements(rk, const_cast(r), JNI_ABORT); + env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); + env->ReleaseByteArrayElements(spendAuthSig, const_cast(sp), JNI_ABORT); + env->ReleaseByteArrayElements(sighashValue, const_cast(si), JNI_ABORT); return jb; } @@ -543,26 +662,33 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingCheckOutput (JNIEnv *env, jobject, jlong ctx, jbyteArray cv, jbyteArray cm, jbyteArray ephemeralKey, jbyteArray zkproof) { -// bool librustzcash_sapling_check_output( -// void *ctx, -// const unsigned char *cv, -// const unsigned char *cm, -// const unsigned char *ephemeralKey, -// const unsigned char *zkproof -// ); - const unsigned char * cvPoint = (const unsigned char *) env->GetByteArrayElements(cv, nullptr); - const unsigned char * cmPoint = (const unsigned char *) env->GetByteArrayElements(cm, nullptr); - const unsigned char * e = (const unsigned char *) env->GetByteArrayElements(ephemeralKey, nullptr); - const unsigned char * z = (const unsigned char *) env->GetByteArrayElements(zkproof, nullptr); - if (cvPoint == NULL || cmPoint == NULL || e == NULL || z == NULL) + // Validate ctx handle + if (ctx == 0) { + return JNI_FALSE; + } + + const jbyte* cvPoint = env->GetByteArrayElements(cv, nullptr); + const jbyte* cmPoint = env->GetByteArrayElements(cm, nullptr); + const jbyte* e = env->GetByteArrayElements(ephemeralKey, nullptr); + const jbyte* z = env->GetByteArrayElements(zkproof, nullptr); + if (cvPoint == nullptr || cmPoint == nullptr || e == nullptr || z == nullptr) { + if (cvPoint != nullptr) env->ReleaseByteArrayElements(cv, const_cast(cvPoint), JNI_ABORT); + if (cmPoint != nullptr) env->ReleaseByteArrayElements(cm, const_cast(cmPoint), JNI_ABORT); + if (e != nullptr) env->ReleaseByteArrayElements(ephemeralKey, const_cast(e), JNI_ABORT); + if (z != nullptr) env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_check_output((void *) ctx,cvPoint,cmPoint,e,z)); - env->ReleaseByteArrayElements(cv,(jbyte*)cvPoint,0); - env->ReleaseByteArrayElements(cm,(jbyte*)cmPoint,0); - env->ReleaseByteArrayElements(ephemeralKey,(jbyte*)e,0); - env->ReleaseByteArrayElements(zkproof,(jbyte*)z,0); + jboolean jb = bool2jboolean(librustzcash_sapling_check_output( + reinterpret_cast(ctx), + reinterpret_cast(cvPoint), + reinterpret_cast(cmPoint), + reinterpret_cast(e), + reinterpret_cast(z))); + env->ReleaseByteArrayElements(cv, const_cast(cvPoint), JNI_ABORT); + env->ReleaseByteArrayElements(cm, const_cast(cmPoint), JNI_ABORT); + env->ReleaseByteArrayElements(ephemeralKey, const_cast(e), JNI_ABORT); + env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); return jb; } @@ -573,21 +699,26 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingFinalCheck (JNIEnv * env, jobject, jlong ctx, jlong valueBalance, jbyteArray bindingSig, jbyteArray sighashValue) { -// bool librustzcash_sapling_final_check( -// void *ctx, -// int64_t valueBalance, -// const unsigned char *bindingSig, -// const unsigned char *sighashValue -// ); - const unsigned char * b = (const unsigned char *) env->GetByteArrayElements(bindingSig, nullptr); - const unsigned char * s = (const unsigned char *) env->GetByteArrayElements(sighashValue, nullptr); - if (b == NULL || s == NULL) + // Validate ctx handle + if (ctx == 0) { + return JNI_FALSE; + } + + const jbyte* b = env->GetByteArrayElements(bindingSig, nullptr); + const jbyte* s = env->GetByteArrayElements(sighashValue, nullptr); + if (b == nullptr || s == nullptr) { + if (b != nullptr) env->ReleaseByteArrayElements(bindingSig, const_cast(b), JNI_ABORT); + if (s != nullptr) env->ReleaseByteArrayElements(sighashValue, const_cast(s), JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_final_check((void *) ctx,(int64_t) valueBalance,b,s)); - env->ReleaseByteArrayElements(bindingSig,(jbyte*)b,0); - env->ReleaseByteArrayElements(sighashValue,(jbyte*)s,0); + jboolean jb = bool2jboolean(librustzcash_sapling_final_check( + reinterpret_cast(ctx), + static_cast(valueBalance), + reinterpret_cast(b), + reinterpret_cast(s))); + env->ReleaseByteArrayElements(bindingSig, const_cast(b), JNI_ABORT); + env->ReleaseByteArrayElements(sighashValue, const_cast(s), JNI_ABORT); return jb; } @@ -598,34 +729,39 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingCheckSpendNew (JNIEnv * env, jobject, jbyteArray cv, jbyteArray anchor, jbyteArray nullifier, jbyteArray rk, jbyteArray zkproof, jbyteArray spendAuthSig, jbyteArray sighashValue) { -// bool librustzcash_sapling_check_spend_new( -// const unsigned char *cv, -// const unsigned char *anchor, -// const unsigned char *nullifier, -// const unsigned char *rk, -// const unsigned char *zkproof, -// const unsigned char *spendAuthSig, -// const unsigned char *sighashValue -// ); - const unsigned char * c = (const unsigned char *) env->GetByteArrayElements(cv, nullptr); - const unsigned char * a = (const unsigned char *) env->GetByteArrayElements(anchor, nullptr); - const unsigned char * n = (const unsigned char *) env->GetByteArrayElements(nullifier, nullptr); - const unsigned char * r = (const unsigned char *) env->GetByteArrayElements(rk, nullptr); - const unsigned char * z = (const unsigned char *) env->GetByteArrayElements(zkproof, nullptr); - const unsigned char * sp = (const unsigned char *) env->GetByteArrayElements(spendAuthSig, nullptr); - const unsigned char * si = (const unsigned char *) env->GetByteArrayElements(sighashValue, nullptr); - if (c == NULL || a == NULL || n == NULL || r == NULL || z == NULL || sp == NULL || si == NULL) + const jbyte* c = env->GetByteArrayElements(cv, nullptr); + const jbyte* a = env->GetByteArrayElements(anchor, nullptr); + const jbyte* n = env->GetByteArrayElements(nullifier, nullptr); + const jbyte* r = env->GetByteArrayElements(rk, nullptr); + const jbyte* z = env->GetByteArrayElements(zkproof, nullptr); + const jbyte* sp = env->GetByteArrayElements(spendAuthSig, nullptr); + const jbyte* si = env->GetByteArrayElements(sighashValue, nullptr); + if (c == nullptr || a == nullptr || n == nullptr || r == nullptr || z == nullptr || sp == nullptr || si == nullptr) { + if (c != nullptr) env->ReleaseByteArrayElements(cv, const_cast(c), JNI_ABORT); + if (a != nullptr) env->ReleaseByteArrayElements(anchor, const_cast(a), JNI_ABORT); + if (n != nullptr) env->ReleaseByteArrayElements(nullifier, const_cast(n), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(rk, const_cast(r), JNI_ABORT); + if (z != nullptr) env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); + if (sp != nullptr) env->ReleaseByteArrayElements(spendAuthSig, const_cast(sp), JNI_ABORT); + if (si != nullptr) env->ReleaseByteArrayElements(sighashValue, const_cast(si), JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_check_spend_new(c,a,n,r,z,sp,si)); - env->ReleaseByteArrayElements(cv,(jbyte*)c,0); - env->ReleaseByteArrayElements(anchor,(jbyte*)a,0); - env->ReleaseByteArrayElements(nullifier,(jbyte*)n,0); - env->ReleaseByteArrayElements(rk,(jbyte*)r,0); - env->ReleaseByteArrayElements(zkproof,(jbyte*)z,0); - env->ReleaseByteArrayElements(spendAuthSig,(jbyte*)sp,0); - env->ReleaseByteArrayElements(sighashValue,(jbyte*)si,0); + jboolean jb = bool2jboolean(librustzcash_sapling_check_spend_new( + reinterpret_cast(c), + reinterpret_cast(a), + reinterpret_cast(n), + reinterpret_cast(r), + reinterpret_cast(z), + reinterpret_cast(sp), + reinterpret_cast(si))); + env->ReleaseByteArrayElements(cv, const_cast(c), JNI_ABORT); + env->ReleaseByteArrayElements(anchor, const_cast(a), JNI_ABORT); + env->ReleaseByteArrayElements(nullifier, const_cast(n), JNI_ABORT); + env->ReleaseByteArrayElements(rk, const_cast(r), JNI_ABORT); + env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); + env->ReleaseByteArrayElements(spendAuthSig, const_cast(sp), JNI_ABORT); + env->ReleaseByteArrayElements(sighashValue, const_cast(si), JNI_ABORT); return jb; } @@ -636,25 +772,27 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingCheckOutputNew (JNIEnv *env, jobject, jbyteArray cv, jbyteArray cm, jbyteArray ephemeralKey, jbyteArray zkproof) { -// bool librustzcash_sapling_check_output_new( -// const unsigned char *cv, -// const unsigned char *cm, -// const unsigned char *ephemeralKey, -// const unsigned char *zkproof -// ); - const unsigned char * cvPoint = (const unsigned char *) env->GetByteArrayElements(cv, nullptr); - const unsigned char * cmPoint = (const unsigned char *) env->GetByteArrayElements(cm, nullptr); - const unsigned char * e = (const unsigned char *) env->GetByteArrayElements(ephemeralKey, nullptr); - const unsigned char * z = (const unsigned char *) env->GetByteArrayElements(zkproof, nullptr); - if (cvPoint == NULL || cmPoint == NULL || e == NULL || z == NULL) + const jbyte* cvPoint = env->GetByteArrayElements(cv, nullptr); + const jbyte* cmPoint = env->GetByteArrayElements(cm, nullptr); + const jbyte* e = env->GetByteArrayElements(ephemeralKey, nullptr); + const jbyte* z = env->GetByteArrayElements(zkproof, nullptr); + if (cvPoint == nullptr || cmPoint == nullptr || e == nullptr || z == nullptr) { + if (cvPoint != nullptr) env->ReleaseByteArrayElements(cv, const_cast(cvPoint), JNI_ABORT); + if (cmPoint != nullptr) env->ReleaseByteArrayElements(cm, const_cast(cmPoint), JNI_ABORT); + if (e != nullptr) env->ReleaseByteArrayElements(ephemeralKey, const_cast(e), JNI_ABORT); + if (z != nullptr) env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_check_output_new(cvPoint,cmPoint,e,z)); - env->ReleaseByteArrayElements(cv,(jbyte*)cvPoint,0); - env->ReleaseByteArrayElements(cm,(jbyte*)cmPoint,0); - env->ReleaseByteArrayElements(ephemeralKey,(jbyte*)e,0); - env->ReleaseByteArrayElements(zkproof,(jbyte*)z,0); + jboolean jb = bool2jboolean(librustzcash_sapling_check_output_new( + reinterpret_cast(cvPoint), + reinterpret_cast(cmPoint), + reinterpret_cast(e), + reinterpret_cast(z))); + env->ReleaseByteArrayElements(cv, const_cast(cvPoint), JNI_ABORT); + env->ReleaseByteArrayElements(cm, const_cast(cmPoint), JNI_ABORT); + env->ReleaseByteArrayElements(ephemeralKey, const_cast(e), JNI_ABORT); + env->ReleaseByteArrayElements(zkproof, const_cast(z), JNI_ABORT); return jb; } @@ -665,30 +803,31 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus */ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingFinalCheckNew (JNIEnv * env, jobject, jlong valueBalance, jbyteArray bindingSig, jbyteArray sighashValue, jbyteArray spendCv, jint spendCvLen, jbyteArray outputCv, jint outputCvLen) { -// bool librustzcash_sapling_final_check_new( -// int64_t valueBalance, -// const unsigned char *bindingSig, -// const unsigned char *sighashValue, -// const unsigned char *spendCv, -// size_t spendCvLen, -// const unsigned char *outputCv, -// size_t outputCvLen, - -// ); - const unsigned char * b = (const unsigned char *) env->GetByteArrayElements(bindingSig, nullptr); - const unsigned char * s = (const unsigned char *) env->GetByteArrayElements(sighashValue, nullptr); - const unsigned char * scv = (const unsigned char *) env->GetByteArrayElements(spendCv, nullptr); - const unsigned char * ocv = (const unsigned char *) env->GetByteArrayElements(outputCv, nullptr); - - if (b == NULL || s == NULL || scv == NULL || ocv == NULL) + const jbyte* b = env->GetByteArrayElements(bindingSig, nullptr); + const jbyte* s = env->GetByteArrayElements(sighashValue, nullptr); + const jbyte* scv = env->GetByteArrayElements(spendCv, nullptr); + const jbyte* ocv = env->GetByteArrayElements(outputCv, nullptr); + + if (b == nullptr || s == nullptr || scv == nullptr || ocv == nullptr) { + if (b != nullptr) env->ReleaseByteArrayElements(bindingSig, const_cast(b), JNI_ABORT); + if (s != nullptr) env->ReleaseByteArrayElements(sighashValue, const_cast(s), JNI_ABORT); + if (scv != nullptr) env->ReleaseByteArrayElements(spendCv, const_cast(scv), JNI_ABORT); + if (ocv != nullptr) env->ReleaseByteArrayElements(outputCv, const_cast(ocv), JNI_ABORT); return JNI_FALSE; } - jboolean jb = bool2jboolean(librustzcash_sapling_final_check_new((int64_t) valueBalance,b,s,scv,(size_t) spendCvLen,ocv,(size_t) outputCvLen)); - env->ReleaseByteArrayElements(bindingSig,(jbyte*)b,0); - env->ReleaseByteArrayElements(sighashValue,(jbyte*)s,0); - env->ReleaseByteArrayElements(spendCv,(jbyte*)scv,0); - env->ReleaseByteArrayElements(outputCv,(jbyte*)ocv,0); + jboolean jb = bool2jboolean(librustzcash_sapling_final_check_new( + static_cast(valueBalance), + reinterpret_cast(b), + reinterpret_cast(s), + reinterpret_cast(scv), + static_cast(spendCvLen), + reinterpret_cast(ocv), + static_cast(outputCvLen))); + env->ReleaseByteArrayElements(bindingSig, const_cast(b), JNI_ABORT); + env->ReleaseByteArrayElements(sighashValue, const_cast(s), JNI_ABORT); + env->ReleaseByteArrayElements(spendCv, const_cast(scv), JNI_ABORT); + env->ReleaseByteArrayElements(outputCv, const_cast(ocv), JNI_ABORT); return jb; } @@ -701,7 +840,10 @@ JNIEXPORT jboolean JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librus JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashSaplingVerificationCtxFree (JNIEnv *, jobject, jlong ctx) { // void librustzcash_sapling_verification_ctx_free(void *); - librustzcash_sapling_verification_ctx_free((void *) ctx); + if (ctx == 0) { + return; + } + librustzcash_sapling_verification_ctx_free(reinterpret_cast(ctx)); } /* @@ -711,23 +853,24 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashMerkleHash (JNIEnv *env, jobject, jint depth, jbyteArray a, jbyteArray b, jbyteArray result) { -// void librustzcash_merkle_hash( -// size_t depth, -// const unsigned char *a, -// const unsigned char *b, -// unsigned char *result -// ); - const unsigned char * aPoint = (const unsigned char *) env->GetByteArrayElements(a, nullptr); - const unsigned char * bPoint = (const unsigned char *) env->GetByteArrayElements(b, nullptr); - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (aPoint == NULL || bPoint == NULL || r == NULL) + const jbyte* aPoint = env->GetByteArrayElements(a, nullptr); + const jbyte* bPoint = env->GetByteArrayElements(b, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (aPoint == nullptr || bPoint == nullptr || r == nullptr) { + if (aPoint != nullptr) env->ReleaseByteArrayElements(a, const_cast(aPoint), JNI_ABORT); + if (bPoint != nullptr) env->ReleaseByteArrayElements(b, const_cast(bPoint), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); return; } - librustzcash_merkle_hash((size_t) depth,aPoint,bPoint,r); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(a,(jbyte*)aPoint,0); - env->ReleaseByteArrayElements(b,(jbyte*)bPoint,0); + librustzcash_merkle_hash( + static_cast(depth), + reinterpret_cast(aPoint), + reinterpret_cast(bPoint), + reinterpret_cast(r)); + env->ReleaseByteArrayElements(a, const_cast(aPoint), JNI_ABORT); + env->ReleaseByteArrayElements(b, const_cast(bPoint), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); } /* @@ -737,17 +880,13 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashTreeUncommitted (JNIEnv *env, jobject, jbyteArray result) { -// void librustzcash_tree_uncommitted( -// unsigned char *result -// ); - - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - if (r == NULL) + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (r == nullptr) { return; } - librustzcash_tree_uncommitted(r); - env->ReleaseByteArrayElements(result,(jbyte*)r,0); + librustzcash_tree_uncommitted(reinterpret_cast(r)); + env->ReleaseByteArrayElements(result, r, 0); } /* @@ -757,15 +896,17 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024Librustzca */ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Librustzcash_00024LibrustzcashJNI_librustzcashToScalar (JNIEnv *env, jobject, jbyteArray input, jbyteArray result) { -// void librustzcash_to_scalar(const unsigned char *input, unsigned char *result); - - const unsigned char * i = (const unsigned char *) env->GetByteArrayElements(input, nullptr); - unsigned char * r = (unsigned char *) env->GetByteArrayElements(result, nullptr); - librustzcash_to_scalar(i,r); - if (r == NULL || i == NULL) + const jbyte* i = env->GetByteArrayElements(input, nullptr); + jbyte* r = env->GetByteArrayElements(result, nullptr); + if (i == nullptr || r == nullptr) { + if (i != nullptr) env->ReleaseByteArrayElements(input, const_cast(i), JNI_ABORT); + if (r != nullptr) env->ReleaseByteArrayElements(result, r, JNI_ABORT); return; } - env->ReleaseByteArrayElements(result,(jbyte*)r,0); - env->ReleaseByteArrayElements(input,(jbyte*)i,0); + librustzcash_to_scalar( + reinterpret_cast(i), + reinterpret_cast(r)); + env->ReleaseByteArrayElements(input, const_cast(i), JNI_ABORT); + env->ReleaseByteArrayElements(result, r, 0); } diff --git a/cpp/src/LibsodiumJNIImpl.cpp b/cpp/src/LibsodiumJNIImpl.cpp index 48cc6de..e236824 100644 --- a/cpp/src/LibsodiumJNIImpl.cpp +++ b/cpp/src/LibsodiumJNIImpl.cpp @@ -4,21 +4,22 @@ #include "org_tron_common_zksnark_Libsodium_LibsodiumJNI.h" #include "sodium.h" -#include +#include +#include JNIEXPORT jlong JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1generichash_1blake2b_1state_1init (JNIEnv *, jobject) { - crypto_generichash_blake2b_state* state_p = new crypto_generichash_blake2b_state(); + crypto_generichash_blake2b_state* state_p = new (std::nothrow) crypto_generichash_blake2b_state(); if (!state_p) { return 0; } - return (jlong) state_p; + return reinterpret_cast(state_p); } JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1generichash_1blake2b_1state_1free (JNIEnv *, jobject, jlong state) { - crypto_generichash_blake2b_state* state_p = (crypto_generichash_blake2b_state*) state; + auto* state_p = reinterpret_cast(state); if (state_p) { delete state_p; } @@ -26,184 +27,291 @@ JNIEXPORT void JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_ JNIEXPORT jint JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1generichash_1blake2b_1init_1salt_1personal (JNIEnv *env, jobject, jlong state, jbyteArray key, jint keylen, jint outlen, jbyteArray salt, jbyteArray personal) { -// int crypto_generichash_blake2b_init_salt_personal(crypto_generichash_blake2b_state *state, -// const unsigned char *key, -// const size_t keylen, const size_t outlen, -// const unsigned char *salt, -// const unsigned char *personal); - auto key_p = key ? (const unsigned char *) env->GetByteArrayElements(key, nullptr) : nullptr; - auto salt_p = salt ? (const unsigned char *) env->GetByteArrayElements(salt, nullptr) : nullptr; - auto personal_p = personal ? (const unsigned char *) env->GetByteArrayElements(personal, nullptr) : nullptr; - - auto ret = (jint) crypto_generichash_blake2b_init_salt_personal( - (crypto_generichash_blake2b_state *) state, - key_p, - (const size_t) keylen, - (const size_t) outlen, - salt_p, - personal_p - ); - - if (key) env->ReleaseByteArrayElements(key, (jbyte *)key_p, 0); - if (salt) env->ReleaseByteArrayElements(salt, (jbyte *)salt_p, 0); - if (personal) env->ReleaseByteArrayElements(personal, (jbyte *)personal_p, 0); + auto* state_p = reinterpret_cast(state); + if (state_p == nullptr) { + return -1; + } + const jbyte* key_p = key ? env->GetByteArrayElements(key, nullptr) : nullptr; + const jbyte* salt_p = salt ? env->GetByteArrayElements(salt, nullptr) : nullptr; + const jbyte* personal_p = personal ? env->GetByteArrayElements(personal, nullptr) : nullptr; + + if (key && key_p == nullptr) { + return -1; + } + if (salt && salt_p == nullptr) { + if (key) env->ReleaseByteArrayElements(key, const_cast(key_p), JNI_ABORT); + return -1; + } + if (personal && personal_p == nullptr) { + if (key) env->ReleaseByteArrayElements(key, const_cast(key_p), JNI_ABORT); + if (salt) env->ReleaseByteArrayElements(salt, const_cast(salt_p), JNI_ABORT); + return -1; + } + + auto ret = static_cast(crypto_generichash_blake2b_init_salt_personal( + state_p, + reinterpret_cast(key_p), + static_cast(keylen), + static_cast(outlen), + reinterpret_cast(salt_p), + reinterpret_cast(personal_p) + )); + + if (key) env->ReleaseByteArrayElements(key, const_cast(key_p), JNI_ABORT); + if (salt) env->ReleaseByteArrayElements(salt, const_cast(salt_p), JNI_ABORT); + if (personal) env->ReleaseByteArrayElements(personal, const_cast(personal_p), JNI_ABORT); return ret; } JNIEXPORT jint JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1generichash_1blake2b_1update (JNIEnv *env, jobject, jlong state, jbyteArray in, jlong inlen) { -// int crypto_generichash_blake2b_update(crypto_generichash_blake2b_state *state, -// const unsigned char *in, -// unsigned long long inlen); - auto in_p = in ? (const unsigned char *) env->GetByteArrayElements(in, nullptr) : nullptr; - auto ret = (jint) crypto_generichash_blake2b_update( - (crypto_generichash_blake2b_state *) state, - in_p, - (unsigned long long) inlen - ); - - if (in) env->ReleaseByteArrayElements(in, (jbyte *)in_p, 0); + auto* state_p = reinterpret_cast(state); + if (state_p == nullptr) { + return -1; + } + const jbyte* in_p = in ? env->GetByteArrayElements(in, nullptr) : nullptr; + + if (in && in_p == nullptr) { + return -1; + } + + auto ret = static_cast(crypto_generichash_blake2b_update( + state_p, + reinterpret_cast(in_p), + static_cast(inlen) + )); + + if (in) env->ReleaseByteArrayElements(in, const_cast(in_p), JNI_ABORT); return ret; } JNIEXPORT jint JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1generichash_1blake2b_1final (JNIEnv *env, jobject, jlong state, jbyteArray out, jint outlen) { -// int crypto_generichash_blake2b_final(crypto_generichash_blake2b_state *state, -// unsigned char *out, -// const size_t outlen); + auto* state_p = reinterpret_cast(state); + if (state_p == nullptr) { + return -1; + } + jbyte* out_p = out ? env->GetByteArrayElements(out, nullptr) : nullptr; - auto out_p = out ? (unsigned char *) env->GetByteArrayElements(out, nullptr) : nullptr; + if (out && out_p == nullptr) { + return -1; + } - auto ret = (jint) crypto_generichash_blake2b_final( - (crypto_generichash_blake2b_state *) state, - out_p, - (const size_t) outlen - ); + auto ret = static_cast(crypto_generichash_blake2b_final( + state_p, + reinterpret_cast(out_p), + static_cast(outlen) + )); - if (out) env->ReleaseByteArrayElements(out, (jbyte *)out_p, 0); + if (out) env->ReleaseByteArrayElements(out, out_p, 0); return ret; } JNIEXPORT jint JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1generichash_1blake2b_1salt_1personal (JNIEnv *env, jobject, jbyteArray out, jint outlen, jbyteArray in, jlong inlen, jbyteArray key, jint keylen, jbyteArray salt, jbyteArray personal) { -// int crypto_generichash_blake2b_salt_personal(unsigned char *out, size_t outlen, -// const unsigned char *in, -// unsigned long long inlen, -// const unsigned char *key, -// size_t keylen, -// const unsigned char *salt, -// const unsigned char *personal); - - auto out_p = out ? (unsigned char *) env->GetByteArrayElements(out, nullptr) : nullptr; - auto in_p = in ? (const unsigned char *) env->GetByteArrayElements(in, nullptr) : nullptr; - auto key_p = key ? (const unsigned char *) env->GetByteArrayElements(key, nullptr) : nullptr; - auto salt_p = salt ? (const unsigned char *) env->GetByteArrayElements(salt, nullptr) : nullptr; - auto personal_p = personal ? (const unsigned char *) env->GetByteArrayElements(personal, nullptr) : nullptr; - - auto ret = (jint) crypto_generichash_blake2b_salt_personal( - out_p, - (size_t) outlen, - in_p, - (unsigned long long) inlen, - key_p, - (size_t) keylen, - salt_p, - personal_p - ); - - if (out) env->ReleaseByteArrayElements(out, (jbyte *)out_p, 0); - if (in) env->ReleaseByteArrayElements(in, (jbyte *)in_p, 0); - if (key) env->ReleaseByteArrayElements(key, (jbyte *)key_p, 0); - if (salt) env->ReleaseByteArrayElements(salt, (jbyte *)salt_p, 0); - if (personal) env->ReleaseByteArrayElements(personal, (jbyte *)personal_p, 0); + jbyte* out_p = out ? env->GetByteArrayElements(out, nullptr) : nullptr; + const jbyte* in_p = in ? env->GetByteArrayElements(in, nullptr) : nullptr; + const jbyte* key_p = key ? env->GetByteArrayElements(key, nullptr) : nullptr; + const jbyte* salt_p = salt ? env->GetByteArrayElements(salt, nullptr) : nullptr; + const jbyte* personal_p = personal ? env->GetByteArrayElements(personal, nullptr) : nullptr; + + if (out && out_p == nullptr) { + return -1; + } + if (in && in_p == nullptr) { + if (out) env->ReleaseByteArrayElements(out, out_p, JNI_ABORT); + return -1; + } + if (key && key_p == nullptr) { + if (out) env->ReleaseByteArrayElements(out, out_p, JNI_ABORT); + if (in) env->ReleaseByteArrayElements(in, const_cast(in_p), JNI_ABORT); + return -1; + } + if (salt && salt_p == nullptr) { + if (out) env->ReleaseByteArrayElements(out, out_p, JNI_ABORT); + if (in) env->ReleaseByteArrayElements(in, const_cast(in_p), JNI_ABORT); + if (key) env->ReleaseByteArrayElements(key, const_cast(key_p), JNI_ABORT); + return -1; + } + if (personal && personal_p == nullptr) { + if (out) env->ReleaseByteArrayElements(out, out_p, JNI_ABORT); + if (in) env->ReleaseByteArrayElements(in, const_cast(in_p), JNI_ABORT); + if (key) env->ReleaseByteArrayElements(key, const_cast(key_p), JNI_ABORT); + if (salt) env->ReleaseByteArrayElements(salt, const_cast(salt_p), JNI_ABORT); + return -1; + } + + auto ret = static_cast(crypto_generichash_blake2b_salt_personal( + reinterpret_cast(out_p), + static_cast(outlen), + reinterpret_cast(in_p), + static_cast(inlen), + reinterpret_cast(key_p), + static_cast(keylen), + reinterpret_cast(salt_p), + reinterpret_cast(personal_p) + )); + + if (out) env->ReleaseByteArrayElements(out, out_p, 0); + if (in) env->ReleaseByteArrayElements(in, const_cast(in_p), JNI_ABORT); + if (key) env->ReleaseByteArrayElements(key, const_cast(key_p), JNI_ABORT); + if (salt) env->ReleaseByteArrayElements(salt, const_cast(salt_p), JNI_ABORT); + if (personal) env->ReleaseByteArrayElements(personal, const_cast(personal_p), JNI_ABORT); return ret; } JNIEXPORT jint JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1aead_1chacha20poly1305_1ietf_1decrypt (JNIEnv *env, jobject, jbyteArray m, jlongArray mlen_p, jbyteArray nsec, jbyteArray c, jlong clen, jbyteArray ad, jlong adlen, jbyteArray npub, jbyteArray k) { -// int crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m, -// unsigned long long *mlen_p, -// unsigned char *nsec, -// const unsigned char *c, -// unsigned long long clen, -// const unsigned char *ad, -// unsigned long long adlen, -// const unsigned char *npub, -// const unsigned char *k) - auto m_p = m ? (unsigned char *) env->GetByteArrayElements(m, nullptr) : nullptr; - auto mlen_p_p = mlen_p ? (unsigned long long*) env->GetLongArrayElements(mlen_p, nullptr) : nullptr; - auto nsec_p =nsec ? (unsigned char *) env->GetByteArrayElements(nsec, nullptr) : nullptr; - auto c_p = c ? (const unsigned char *) env->GetByteArrayElements(c, nullptr) : nullptr; - auto ad_p = ad ? (const unsigned char *) env->GetByteArrayElements(ad, nullptr) : nullptr; - auto npub_p =npub ? (const unsigned char *) env->GetByteArrayElements(npub, nullptr) : nullptr; - auto k_p = k ? (const unsigned char *) env->GetByteArrayElements(k, nullptr) : nullptr; - - auto ret = (jint) crypto_aead_chacha20poly1305_ietf_decrypt( - m_p, - mlen_p_p, - nsec_p, - c_p, - (unsigned long long) clen, - ad_p, - (unsigned long long) adlen, - npub_p, - k_p - ); - - if (m) env->ReleaseByteArrayElements(m, (jbyte *)m_p, 0); - if (mlen_p) env->ReleaseLongArrayElements(mlen_p, (jlong *)mlen_p_p, 0); - if (nsec) env->ReleaseByteArrayElements(nsec, (jbyte *)nsec_p, 0); - if (c) env->ReleaseByteArrayElements(c, (jbyte *)c_p, 0); - if (ad) env->ReleaseByteArrayElements(ad, (jbyte *)ad_p, 0); - if (npub) env->ReleaseByteArrayElements(npub, (jbyte *)npub_p, 0); - if (k) env->ReleaseByteArrayElements(k, (jbyte *)k_p, 0); + jbyte* m_p = m ? env->GetByteArrayElements(m, nullptr) : nullptr; + jlong* mlen_p_p = mlen_p ? env->GetLongArrayElements(mlen_p, nullptr) : nullptr; + jbyte* nsec_p = nsec ? env->GetByteArrayElements(nsec, nullptr) : nullptr; + const jbyte* c_p = c ? env->GetByteArrayElements(c, nullptr) : nullptr; + const jbyte* ad_p = ad ? env->GetByteArrayElements(ad, nullptr) : nullptr; + const jbyte* npub_p = npub ? env->GetByteArrayElements(npub, nullptr) : nullptr; + const jbyte* k_p = k ? env->GetByteArrayElements(k, nullptr) : nullptr; + + if (m && m_p == nullptr) { + return -1; + } + if (mlen_p && mlen_p_p == nullptr) { + if (m) env->ReleaseByteArrayElements(m, m_p, JNI_ABORT); + return -1; + } + if (nsec && nsec_p == nullptr) { + if (m) env->ReleaseByteArrayElements(m, m_p, JNI_ABORT); + if (mlen_p) env->ReleaseLongArrayElements(mlen_p, mlen_p_p, JNI_ABORT); + return -1; + } + if (c && c_p == nullptr) { + if (m) env->ReleaseByteArrayElements(m, m_p, JNI_ABORT); + if (mlen_p) env->ReleaseLongArrayElements(mlen_p, mlen_p_p, JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, nsec_p, JNI_ABORT); + return -1; + } + if (ad && ad_p == nullptr) { + if (m) env->ReleaseByteArrayElements(m, m_p, JNI_ABORT); + if (mlen_p) env->ReleaseLongArrayElements(mlen_p, mlen_p_p, JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, nsec_p, JNI_ABORT); + if (c) env->ReleaseByteArrayElements(c, const_cast(c_p), JNI_ABORT); + return -1; + } + if (npub && npub_p == nullptr) { + if (m) env->ReleaseByteArrayElements(m, m_p, JNI_ABORT); + if (mlen_p) env->ReleaseLongArrayElements(mlen_p, mlen_p_p, JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, nsec_p, JNI_ABORT); + if (c) env->ReleaseByteArrayElements(c, const_cast(c_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + return -1; + } + if (k && k_p == nullptr) { + if (m) env->ReleaseByteArrayElements(m, m_p, JNI_ABORT); + if (mlen_p) env->ReleaseLongArrayElements(mlen_p, mlen_p_p, JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, nsec_p, JNI_ABORT); + if (c) env->ReleaseByteArrayElements(c, const_cast(c_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + if (npub) env->ReleaseByteArrayElements(npub, const_cast(npub_p), JNI_ABORT); + return -1; + } + + auto ret = static_cast(crypto_aead_chacha20poly1305_ietf_decrypt( + reinterpret_cast(m_p), + reinterpret_cast(mlen_p_p), + reinterpret_cast(nsec_p), + reinterpret_cast(c_p), + static_cast(clen), + reinterpret_cast(ad_p), + static_cast(adlen), + reinterpret_cast(npub_p), + reinterpret_cast(k_p) + )); + + if (m) env->ReleaseByteArrayElements(m, m_p, 0); + if (mlen_p) env->ReleaseLongArrayElements(mlen_p, mlen_p_p, 0); + if (nsec) env->ReleaseByteArrayElements(nsec, nsec_p, 0); + if (c) env->ReleaseByteArrayElements(c, const_cast(c_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + if (npub) env->ReleaseByteArrayElements(npub, const_cast(npub_p), JNI_ABORT); + if (k) env->ReleaseByteArrayElements(k, const_cast(k_p), JNI_ABORT); return ret; } JNIEXPORT jint JNICALL Java_org_tron_common_zksnark_Libsodium_00024LibsodiumJNI_crypto_1aead_1chacha20poly1305_1ietf_1encrypt (JNIEnv *env, jobject, jbyteArray c, jlongArray clen_p, jbyteArray m, jlong mlen, jbyteArray ad, jlong adlen, jbyteArray nsec, jbyteArray npub, jbyteArray k) { -// int crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c, -// unsigned long long *clen_p, -// const unsigned char *m, -// unsigned long long mlen, -// const unsigned char *ad, -// unsigned long long adlen, -// const unsigned char *nsec, -// const unsigned char *npub, -// const unsigned char *k); - - auto c_p = c ? (unsigned char *) env->GetByteArrayElements(c, nullptr) : nullptr; - auto clen_p_p = clen_p ? (unsigned long long*) env->GetLongArrayElements(clen_p, nullptr) : nullptr; - auto m_p = m ? (const unsigned char *) env->GetByteArrayElements(m, nullptr) : nullptr; - auto ad_p = ad ? (const unsigned char *) env->GetByteArrayElements(ad, nullptr) : nullptr; - auto nsec_p = nsec ? (const unsigned char *) env->GetByteArrayElements(nsec, nullptr) : nullptr; - auto npub_p = npub ? (const unsigned char *) env->GetByteArrayElements(npub, nullptr) : nullptr; - auto k_p = k ? (const unsigned char *) env->GetByteArrayElements(k, nullptr) : nullptr; - - auto ret = (jint) crypto_aead_chacha20poly1305_ietf_encrypt( - c_p, - clen_p_p, - m_p, - (unsigned long long) mlen, - ad_p, - (unsigned long long) adlen, - nsec_p, - npub_p, - k_p - ); - - if (c) env->ReleaseByteArrayElements(c, (jbyte *)c_p, 0); - if (clen_p) env->ReleaseLongArrayElements(clen_p, (jlong *)clen_p_p, 0); - if (m) env->ReleaseByteArrayElements(m, (jbyte *) m_p, 0); - if (ad) env->ReleaseByteArrayElements(ad, (jbyte *) ad_p, 0); - if (nsec) env->ReleaseByteArrayElements(nsec, (jbyte *) nsec_p, 0); - if (npub) env->ReleaseByteArrayElements(npub, (jbyte *) npub_p, 0); - if (k) env->ReleaseByteArrayElements(k, (jbyte *) k_p, 0); + jbyte* c_p = c ? env->GetByteArrayElements(c, nullptr) : nullptr; + jlong* clen_p_p = clen_p ? env->GetLongArrayElements(clen_p, nullptr) : nullptr; + const jbyte* m_p = m ? env->GetByteArrayElements(m, nullptr) : nullptr; + const jbyte* ad_p = ad ? env->GetByteArrayElements(ad, nullptr) : nullptr; + const jbyte* nsec_p = nsec ? env->GetByteArrayElements(nsec, nullptr) : nullptr; + const jbyte* npub_p = npub ? env->GetByteArrayElements(npub, nullptr) : nullptr; + const jbyte* k_p = k ? env->GetByteArrayElements(k, nullptr) : nullptr; + + if (c && c_p == nullptr) { + return -1; + } + if (clen_p && clen_p_p == nullptr) { + if (c) env->ReleaseByteArrayElements(c, c_p, JNI_ABORT); + return -1; + } + if (m && m_p == nullptr) { + if (c) env->ReleaseByteArrayElements(c, c_p, JNI_ABORT); + if (clen_p) env->ReleaseLongArrayElements(clen_p, clen_p_p, JNI_ABORT); + return -1; + } + if (ad && ad_p == nullptr) { + if (c) env->ReleaseByteArrayElements(c, c_p, JNI_ABORT); + if (clen_p) env->ReleaseLongArrayElements(clen_p, clen_p_p, JNI_ABORT); + if (m) env->ReleaseByteArrayElements(m, const_cast(m_p), JNI_ABORT); + return -1; + } + if (nsec && nsec_p == nullptr) { + if (c) env->ReleaseByteArrayElements(c, c_p, JNI_ABORT); + if (clen_p) env->ReleaseLongArrayElements(clen_p, clen_p_p, JNI_ABORT); + if (m) env->ReleaseByteArrayElements(m, const_cast(m_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + return -1; + } + if (npub && npub_p == nullptr) { + if (c) env->ReleaseByteArrayElements(c, c_p, JNI_ABORT); + if (clen_p) env->ReleaseLongArrayElements(clen_p, clen_p_p, JNI_ABORT); + if (m) env->ReleaseByteArrayElements(m, const_cast(m_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, const_cast(nsec_p), JNI_ABORT); + return -1; + } + if (k && k_p == nullptr) { + if (c) env->ReleaseByteArrayElements(c, c_p, JNI_ABORT); + if (clen_p) env->ReleaseLongArrayElements(clen_p, clen_p_p, JNI_ABORT); + if (m) env->ReleaseByteArrayElements(m, const_cast(m_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, const_cast(nsec_p), JNI_ABORT); + if (npub) env->ReleaseByteArrayElements(npub, const_cast(npub_p), JNI_ABORT); + return -1; + } + + auto ret = static_cast(crypto_aead_chacha20poly1305_ietf_encrypt( + reinterpret_cast(c_p), + reinterpret_cast(clen_p_p), + reinterpret_cast(m_p), + static_cast(mlen), + reinterpret_cast(ad_p), + static_cast(adlen), + reinterpret_cast(nsec_p), + reinterpret_cast(npub_p), + reinterpret_cast(k_p) + )); + + if (c) env->ReleaseByteArrayElements(c, c_p, 0); + if (clen_p) env->ReleaseLongArrayElements(clen_p, clen_p_p, 0); + if (m) env->ReleaseByteArrayElements(m, const_cast(m_p), JNI_ABORT); + if (ad) env->ReleaseByteArrayElements(ad, const_cast(ad_p), JNI_ABORT); + if (nsec) env->ReleaseByteArrayElements(nsec, const_cast(nsec_p), JNI_ABORT); + if (npub) env->ReleaseByteArrayElements(npub, const_cast(npub_p), JNI_ABORT); + if (k) env->ReleaseByteArrayElements(k, const_cast(k_p), JNI_ABORT); return ret; } diff --git a/src/main/resources/META-INF/native/linux64/libzksnarkjni.so b/src/main/resources/META-INF/native/linux64/libzksnarkjni.so old mode 100755 new mode 100644 index 117ea46..cb7e789 Binary files a/src/main/resources/META-INF/native/linux64/libzksnarkjni.so and b/src/main/resources/META-INF/native/linux64/libzksnarkjni.so differ diff --git a/src/main/resources/META-INF/native/osx64/aarch64/libzksnarkjni.jnilib b/src/main/resources/META-INF/native/osx64/aarch64/libzksnarkjni.jnilib index 1300365..1058cd0 100755 Binary files a/src/main/resources/META-INF/native/osx64/aarch64/libzksnarkjni.jnilib and b/src/main/resources/META-INF/native/osx64/aarch64/libzksnarkjni.jnilib differ diff --git a/src/main/resources/META-INF/native/osx64/libzksnarkjni.jnilib b/src/main/resources/META-INF/native/osx64/libzksnarkjni.jnilib index 6743bc8..31bcfae 100755 Binary files a/src/main/resources/META-INF/native/osx64/libzksnarkjni.jnilib and b/src/main/resources/META-INF/native/osx64/libzksnarkjni.jnilib differ diff --git a/src/test/java/org/tron/common/zksnark/HexBin.java b/src/test/java/org/tron/common/zksnark/HexBin.java new file mode 100644 index 0000000..b2fa98e --- /dev/null +++ b/src/test/java/org/tron/common/zksnark/HexBin.java @@ -0,0 +1,23 @@ +package org.tron.common.zksnark; + +final class HexBin { + private HexBin() { + } + + static byte[] decode(String hex) { + if (hex == null || (hex.length() & 1) != 0) { + throw new IllegalArgumentException("Hex string must have even length"); + } + + byte[] out = new byte[hex.length() / 2]; + for (int i = 0; i < hex.length(); i += 2) { + int high = Character.digit(hex.charAt(i), 16); + int low = Character.digit(hex.charAt(i + 1), 16); + if (high < 0 || low < 0) { + throw new IllegalArgumentException("Invalid hex string"); + } + out[i / 2] = (byte) ((high << 4) + low); + } + return out; + } +} diff --git a/src/test/java/org/tron/common/zksnark/LibrustzcashTest.java b/src/test/java/org/tron/common/zksnark/LibrustzcashTest.java index 4031a33..d2b061d 100644 --- a/src/test/java/org/tron/common/zksnark/LibrustzcashTest.java +++ b/src/test/java/org/tron/common/zksnark/LibrustzcashTest.java @@ -1,6 +1,5 @@ package org.tron.common.zksnark; -import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin; import java.util.Arrays; import java.util.Random; import org.junit.Assert; diff --git a/src/test/java/org/tron/common/zksnark/LibsodiumTest.java b/src/test/java/org/tron/common/zksnark/LibsodiumTest.java index af3aa17..5183e74 100644 --- a/src/test/java/org/tron/common/zksnark/LibsodiumTest.java +++ b/src/test/java/org/tron/common/zksnark/LibsodiumTest.java @@ -1,6 +1,5 @@ package org.tron.common.zksnark; -import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test;