13 Commits

Author SHA1 Message Date
Fabrice Drouin
f5e1655ff0 Set version to 0.13.0 (#98) 2024-01-23 16:46:55 +01:00
Fabrice Drouin
8ba5d4652e Use kotlin 1.9 (#92)
Use kotlin 1.9
2024-01-23 15:44:06 +01:00
Fabrice Drouin
e94e41b896 Update secp256k1 to version 0.4.1 (#96)
Use secp256k1 0.4.1
2024-01-02 11:16:36 +01:00
Fabrice Drouin
1a4c8b37cb Release 0.12.0 (#95) 2023-12-13 16:40:32 +01:00
Fabrice Drouin
f242b4ffe8 Check arguments passed to secp256k1 methods (#94)
* Check arguments passed to secp256k1 methods

Illegal arguments will trigger an internal callback that prints to stderr and calls abort.
We already check arguments in our JNI and kotlin native code but had missed 2 checks (recid in ecdsaRecover, empty arrays in pubkeyCombine).

* Implement the same "tweak" checks in the native code and JNI code

The native code was missing checks on the "tweak" size (which must be 32 bytes)
2023-12-13 13:42:14 +01:00
Fabrice Drouin
161da89ee1 Set version to 0.11.0 (#86) 2023-09-28 09:50:24 +02:00
Fabrice Drouin
3706a546a2 Use secp256k1 0.4.0 (#85) 2023-09-18 14:05:36 +02:00
Fabrice Drouin
ffcaaf1b64 Set version to 0.10.1 (#84) 2023-06-28 13:03:19 +02:00
Fabrice Drouin
6ef94df247 Use secp256k1 0.3.2 (#83) 2023-06-28 10:43:05 +02:00
Fabrice Drouin
5169073a92 Update README.md 2023-05-15 11:15:30 +02:00
Fabrice Drouin
317e086cba Set version to 0.10.0 (#82) 2023-05-11 18:29:50 +02:00
Fabrice Drouin
7c7aabba80 Upgrade to Kotlin 1.8 (#81)
* Upgrade to Kotlin 1.8

* Update snapshot deployment script

Kotlin 1.8 creates a new metadata jar for ios modules.
2023-05-11 17:53:41 +02:00
Fabrice Drouin
b6823cbda6 Update CI build (#80) 2023-04-25 09:55:48 +02:00
15 changed files with 170 additions and 109 deletions

View File

@@ -33,7 +33,7 @@ jobs:
shell: bash shell: bash
run: | run: |
echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV
echo "ANDROID_NDK_VERSION=21.4.7075529" >> $GITHUB_ENV echo "ANDROID_NDK_VERSION=25.2.9519653" >> $GITHUB_ENV
- name: Cached Android NDK - name: Cached Android NDK
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
uses: actions/cache@v2 uses: actions/cache@v2
@@ -58,15 +58,11 @@ jobs:
base-devel base-devel
autotools autotools
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Setup Android - name: Setup Android
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
shell: bash shell: bash
run: | run: |
$ANDROID_HOME/tools/bin/sdkmanager "ndk;$ANDROID_NDK_VERSION" ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "ndk;$ANDROID_NDK_VERSION"
- name: Setup Android - name: Setup Android
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
shell: msys2 {0} shell: msys2 {0}
@@ -86,7 +82,7 @@ jobs:
- name: Check Linux - name: Check Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
shell: bash shell: bash
run: ./gradlew linuxTest run: ./gradlew linuxX64Test
- name: Check iOS - name: Check iOS
if: matrix.os == 'macOS-latest' if: matrix.os == 'macOS-latest'
shell: bash shell: bash
@@ -96,15 +92,14 @@ jobs:
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: 27 api-level: 27
emulator-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
ndk: ${{ env.ANDROID_NDK_VERSION }} ndk: ${{ env.ANDROID_NDK_VERSION }}
cmake: 3.10.2.4988404 cmake: 3.22.1
script: ./gradlew connectedCheck script: ./gradlew connectedCheck
- name: Publish Linux - name: Publish Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
shell: bash shell: bash
run: ./gradlew publishLinuxPublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal run: ./gradlew publishLinuxX64PublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal
- name: Publish Windows - name: Publish Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
shell: msys2 {0} shell: msys2 {0}

View File

@@ -42,7 +42,7 @@ jobs:
shell: bash shell: bash
run: | run: |
echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV
echo "ANDROID_NDK_VERSION=21.4.7075529" >> $GITHUB_ENV echo "ANDROID_NDK_VERSION=25.2.9519653" >> $GITHUB_ENV
- name: Cached Android NDK - name: Cached Android NDK
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
uses: actions/cache@v2 uses: actions/cache@v2
@@ -67,15 +67,11 @@ jobs:
base-devel base-devel
autotools autotools
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Setup Android - name: Setup Android
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
shell: bash shell: bash
run: | run: |
$ANDROID_HOME/tools/bin/sdkmanager "ndk;$ANDROID_NDK_VERSION" ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "ndk;$ANDROID_NDK_VERSION"
- name: Setup Android - name: Setup Android
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
shell: msys2 {0} shell: msys2 {0}
@@ -95,7 +91,7 @@ jobs:
- name: Check Linux - name: Check Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
shell: bash shell: bash
run: ./gradlew linuxTest run: ./gradlew linuxX64Test
- name: Check iOS - name: Check iOS
if: matrix.os == 'macOS-latest' if: matrix.os == 'macOS-latest'
shell: bash shell: bash
@@ -105,15 +101,14 @@ jobs:
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: 27 api-level: 27
-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
ndk: ${{ env.ANDROID_NDK_VERSION }} ndk: ${{ env.ANDROID_NDK_VERSION }}
cmake: 3.10.2.4988404 cmake: 3.22.1
script: ./gradlew connectedCheck script: ./gradlew connectedCheck
- name: Publish Linux - name: Publish Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
shell: bash shell: bash
run: ./gradlew publishLinuxPublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }} run: ./gradlew publishLinuxX64PublicationToMavenLocal :jni:jvm:linux:publishJvmPublicationToMavenLocal -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
- name: Publish Windows - name: Publish Windows
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
shell: msys2 {0} shell: msys2 {0}

View File

@@ -48,7 +48,7 @@ jobs:
shell: bash shell: bash
run: | run: |
echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV echo "ANDROID_HOME=$ANDROID_HOME" >> $GITHUB_ENV
echo "ANDROID_NDK_VERSION=21.4.7075529" >> $GITHUB_ENV echo "ANDROID_NDK_VERSION=25.2.9519653" >> $GITHUB_ENV
- name: Cached Android NDK - name: Cached Android NDK
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
uses: actions/cache@v2 uses: actions/cache@v2
@@ -73,15 +73,11 @@ jobs:
base-devel base-devel
autotools autotools
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Setup Android - name: Setup Android
if: matrix.os != 'windows-latest' if: matrix.os != 'windows-latest'
shell: bash shell: bash
run: | run: |
$ANDROID_HOME/tools/bin/sdkmanager "ndk;$ANDROID_NDK_VERSION" ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "ndk;$ANDROID_NDK_VERSION"
- name: Setup Android - name: Setup Android
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
shell: msys2 {0} shell: msys2 {0}
@@ -101,7 +97,7 @@ jobs:
- name: Check Linux - name: Check Linux
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
shell: bash shell: bash
run: ./gradlew linuxTest run: ./gradlew linuxX64Test
- name: Check iOS - name: Check iOS
if: matrix.os == 'macOS-latest' if: matrix.os == 'macOS-latest'
shell: bash shell: bash
@@ -111,8 +107,7 @@ jobs:
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: 27 api-level: 27
emulator-build: 7425822 # workaround to emulator bug: https://github.com/ReactiveCircus/android-emulator-runner/issues/160
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
ndk: ${{ env.ANDROID_NDK_VERSION }} ndk: ${{ env.ANDROID_NDK_VERSION }}
cmake: 3.10.2.4988404 cmake: 3.22.1
script: ./gradlew connectedCheck script: ./gradlew connectedCheck

View File

@@ -1,4 +1,4 @@
[![Kotlin](https://img.shields.io/badge/Kotlin-1.6.21-blue.svg?style=flat&logo=kotlin)](http://kotlinlang.org) [![Kotlin](https://img.shields.io/badge/Kotlin-1.8.21-blue.svg?style=flat&logo=kotlin)](http://kotlinlang.org)
[![Maven Central](https://img.shields.io/maven-central/v/fr.acinq.secp256k1/secp256k1-kmp)](https://search.maven.org/search?q=g:fr.acinq.secp256k1%20a:secp256k1-kmp*) [![Maven Central](https://img.shields.io/maven-central/v/fr.acinq.secp256k1/secp256k1-kmp)](https://search.maven.org/search?q=g:fr.acinq.secp256k1%20a:secp256k1-kmp*)
![Github Actions](https://github.com/ACINQ/secp256k1-kmp/actions/workflows/test.yml/badge.svg) ![Github Actions](https://github.com/ACINQ/secp256k1-kmp/actions/workflows/test.yml/badge.svg)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ACINQ/secp256k1-kmp/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ACINQ/secp256k1-kmp/blob/master/LICENSE)
@@ -58,9 +58,9 @@ Native targets include libsecp256k1, called through KMP's c-interop, simply add
The JVM library uses JNI bindings for libsecp256k1, which is much faster than BouncyCastle. It will extract and load native bindings for your operating system in a temporary directory. The JVM library uses JNI bindings for libsecp256k1, which is much faster than BouncyCastle. It will extract and load native bindings for your operating system in a temporary directory.
JNI libraries are included for: JNI libraries are included for:
- Linux 64 bits - Linux 64 bits (x86_64 and arm64)
- Windows 64 bits - Windows 64 bits (x86_64)
- Macos 64 bits - Macos 64 bits (x86_64 and arm64)
Along this library, you **must** specify which JNI native library to use in your dependency manager: Along this library, you **must** specify which JNI native library to use in your dependency manager:

View File

@@ -3,8 +3,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.dokka.Platform import org.jetbrains.dokka.Platform
plugins { plugins {
kotlin("multiplatform") version "1.6.21" kotlin("multiplatform") version "1.9.22"
id("org.jetbrains.dokka") version "1.6.21" id("org.jetbrains.dokka") version "1.9.10"
`maven-publish` `maven-publish`
} }
@@ -16,13 +16,13 @@ buildscript {
dependencies { dependencies {
classpath("com.android.tools.build:gradle:7.3.1") classpath("com.android.tools.build:gradle:7.3.1")
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.6.21") classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.9.10")
} }
} }
allprojects { allprojects {
group = "fr.acinq.secp256k1" group = "fr.acinq.secp256k1"
version = "0.9.0" version = "0.13.0"
repositories { repositories {
google() google()
@@ -52,20 +52,22 @@ kotlin {
} }
} }
val nativeMain by sourceSets.creating { dependsOn(commonMain) } val nativeMain by sourceSets.creating
linuxX64("linux") { linuxX64 {
secp256k1CInterop("host") secp256k1CInterop("host")
compilations["main"].defaultSourceSet.dependsOn(nativeMain)
// https://youtrack.jetbrains.com/issue/KT-39396
compilations["main"].kotlinOptions.freeCompilerArgs += listOf("-include-binary", "$rootDir/native/build/linux/libsecp256k1.a")
} }
ios { iosX64 {
secp256k1CInterop("ios")
}
iosArm64 {
secp256k1CInterop("ios")
}
iosSimulatorArm64 {
secp256k1CInterop("ios") secp256k1CInterop("ios")
compilations["main"].defaultSourceSet.dependsOn(nativeMain)
// https://youtrack.jetbrains.com/issue/KT-39396
compilations["main"].kotlinOptions.freeCompilerArgs += listOf("-include-binary", "$rootDir/native/build/ios/libsecp256k1.a")
} }
sourceSets.all { sourceSets.all {
@@ -80,9 +82,9 @@ allprojects {
val currentOs = OperatingSystem.current() val currentOs = OperatingSystem.current()
val targets = when { val targets = when {
currentOs.isLinux -> listOf() currentOs.isLinux -> listOf()
currentOs.isMacOsX -> listOf("linux") currentOs.isMacOsX -> listOf("linuxX64")
currentOs.isWindows -> listOf("linux") currentOs.isWindows -> listOf("linuxX64")
else -> listOf("linux") else -> listOf("linuxX64")
}.mapNotNull { kotlin.targets.findByName(it) as? KotlinNativeTarget } }.mapNotNull { kotlin.targets.findByName(it) as? KotlinNativeTarget }
configure(targets) { configure(targets) {
@@ -157,6 +159,7 @@ allprojects {
Platform.js -> "js" Platform.js -> "js"
Platform.native -> "native" Platform.native -> "native"
Platform.common -> "common" Platform.common -> "common"
Platform.wasm -> "wasm"
} }
displayName.set(platformName) displayName.set(platformName)

View File

@@ -6,11 +6,10 @@ import fr.acinq.secp256k1.NativeSecp256k1
import java.util.* import java.util.*
public object NativeSecp256k1AndroidLoader { public object NativeSecp256k1AndroidLoader {
@JvmStatic @JvmStatic
@Synchronized @Synchronized
@Throws(Exception::class) @Throws(Exception::class)
fun load(): Secp256k1 { public fun load(): Secp256k1 {
try { try {
System.loadLibrary("secp256k1-jni") System.loadLibrary("secp256k1-jni")
return NativeSecp256k1 return NativeSecp256k1
@@ -27,5 +26,4 @@ public object NativeSecp256k1AndroidLoader {
} }
} }
} }

View File

@@ -1,6 +1,9 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef WIN32
#define SECP256K1_STATIC // needed on windows when linking to a static version of secp256k1
#endif
#include "include/secp256k1.h" #include "include/secp256k1.h"
#include "include/secp256k1_ecdh.h" #include "include/secp256k1_ecdh.h"
#include "include/secp256k1_recovery.h" #include "include/secp256k1_recovery.h"
@@ -514,6 +517,7 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
if (jpubkeys == NULL) return NULL; if (jpubkeys == NULL) return NULL;
count = (*penv)->GetArrayLength(penv, jpubkeys); count = (*penv)->GetArrayLength(penv, jpubkeys);
CHECKRESULT(count < 1, "pubkey array cannot be empty")
pubkeys = calloc(count, sizeof(secp256k1_pubkey*)); pubkeys = calloc(count, sizeof(secp256k1_pubkey*));
for(i = 0; i < count; i++) { for(i = 0; i < count; i++) {
@@ -597,6 +601,7 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
if (jctx == 0) return NULL; if (jctx == 0) return NULL;
if (jsig == NULL) return NULL; if (jsig == NULL) return NULL;
if (jmsg == NULL) return NULL; if (jmsg == NULL) return NULL;
CHECKRESULT(recid < 0 || recid > 3, "invalid recovery id");
sigSize = (*penv)->GetArrayLength(penv, jsig); sigSize = (*penv)->GetArrayLength(penv, jsig);
int sigFormat = GetSignatureFormat(sigSize); int sigFormat = GetSignatureFormat(sigSize);

View File

@@ -9,7 +9,10 @@ cd secp256k1
sh xconfigure.sh --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no sh xconfigure.sh --enable-experimental --enable-module_ecdh --enable-module-recovery --enable-module-schnorrsig --enable-benchmark=no --enable-shared=no --enable-exhaustive-tests=no --enable-tests=no
mkdir -p ../build/ios mkdir -p ../build/ios
cp -v _build/universal/* ../build/ios/ cp -v _build/universal/ios/* ../build/ios/
mkdir -p ../build/iosSimulatorArm64
cp -v _build/universal/iosSimulatorArm64/* ../build/iosSimulatorArm64/
rm -rf _build rm -rf _build
make clean make clean

View File

@@ -69,9 +69,22 @@ HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=${MIN_IOS_VERSION} -isysro
CHOST="x86_64-apple-darwin" CHOST="x86_64-apple-darwin"
Build "$@" Build "$@"
## Build for iphone M1/M2/Mx simulators
SDK="iphonesimulator"
PLATFORM="arm64-sim"
PLATFORM_SIM_ARM=${PLATFORM}
ARCH_FLAGS="-arch arm64"
HOST_FLAGS="${ARCH_FLAGS} -mios-simulator-version-min=${MIN_IOS_VERSION} -isysroot $(xcrun --sdk ${SDK} --show-sdk-path)"
CHOST="arm-apple-darwin"
Build "$@"
# Create universal binary # Create universal binary
cd "${PLATFORMS}/${PLATFORM_ARM}/lib" cd "${PLATFORMS}/${PLATFORM_ARM}/lib"
LIB_NAME=`find . -iname *.a` LIB_NAME=`find . -iname *.a`
cd - cd -
mkdir -p "${UNIVERSAL}" &> /dev/null mkdir -p "${UNIVERSAL}/ios" &> /dev/null
lipo -create -output "${UNIVERSAL}/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ARM}/lib/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ISIM}/lib/${LIB_NAME}" mkdir -p "${UNIVERSAL}/iosSimulatorArm64" &> /dev/null
lipo -create -output "${UNIVERSAL}/ios/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ARM}/lib/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_ISIM}/lib/${LIB_NAME}"
# create a specific library for arm64 simulator: it cannot be included in the lib above which already contains an arm64 lib
lipo -create -output "${UNIVERSAL}/iosSimulatorArm64/${LIB_NAME}" "${PLATFORMS}/${PLATFORM_SIM_ARM}/lib/${LIB_NAME}"

View File

@@ -2,52 +2,64 @@
GROUP_ID=fr.acinq.secp256k1 GROUP_ID=fr.acinq.secp256k1
ARTIFACT_ID_BASE=secp256k1-kmp ARTIFACT_ID_BASE=secp256k1-kmp
VERSION=0.9.0-SNAPSHOT
if [[ -z "${VERSION}" ]]; then
echo "VERSION is not defined"
exit 1
fi
cd snapshot cd snapshot
pushd . pushd .
cd fr/acinq/secp256k1/secp256k1-kmp/$VERSION cd fr/acinq/secp256k1/secp256k1-kmp/$VERSION
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \ mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
-DpomFile=$ARTIFACT_ID_BASE-$VERSION.pom \ -DpomFile=$ARTIFACT_ID_BASE-$VERSION.pom \
-Dfile=$ARTIFACT_ID_BASE-$VERSION.jar \ -Dfile=$ARTIFACT_ID_BASE-$VERSION.jar \
-Dfiles=$ARTIFACT_ID_BASE-$VERSION.module,$ARTIFACT_ID_BASE-$VERSION-kotlin-tooling-metadata.json \ -Dfiles=$ARTIFACT_ID_BASE-$VERSION.module,$ARTIFACT_ID_BASE-$VERSION-kotlin-tooling-metadata.json \
-Dtypes=module,json \ -Dtypes=module,json \
-Dclassifiers=,kotlin-tooling-metadata \ -Dclassifiers=,kotlin-tooling-metadata \
-Dsources=$ARTIFACT_ID_BASE-$VERSION-sources.jar \ -Dsources=$ARTIFACT_ID_BASE-$VERSION-sources.jar \
-Djavadoc=$ARTIFACT_ID_BASE-$VERSION-javadoc.jar -Djavadoc=$ARTIFACT_ID_BASE-$VERSION-javadoc.jar
popd popd
pushd . pushd .
for i in iosarm64 iosx64 jni-android jni-common jni-jvm-darwin jni-jvm-extract jni-jvm-linux jni-jvm-mingw jni-jvm jvm linux for i in iosarm64 iossimulatorarm64 iosx64 jni-android jni-common jni-jvm-darwin jni-jvm-extract jni-jvm-linux jni-jvm-mingw jni-jvm jvm linuxx64; do
do cd fr/acinq/secp256k1/secp256k1-kmp-$i/$VERSION
cd fr/acinq/secp256k1/secp256k1-kmp-$i/$VERSION if [ $i == iosarm64 ] || [ $i == iossimulatorarm64 ] || [ $i == iosx64 ]; then
if [ $i == iosarm64 ] || [ $i == iosx64 ] || [ $i == linux ]; then mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \ -DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \ -Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \ -Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION-metadata.jar,$ARTIFACT_ID_BASE-$i-$VERSION.module,$ARTIFACT_ID_BASE-$i-$VERSION-cinterop-libsecp256k1.klib \
-Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION.module,$ARTIFACT_ID_BASE-$i-$VERSION-cinterop-libsecp256k1.klib \ -Dtypes=jar,module,klib \
-Dtypes=module,klib \ -Dclassifiers=metadata,,cinterop-libsecp256k1 \
-Dclassifiers=,cinterop-libsecp256k1 \ -Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \
-Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \ -Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar
-Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar elif [ $i == linuxx64 ]; then
elif [ $i == jni-android ]; then mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \ -DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \ -Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.klib \
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.aar \ -Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION.module,$ARTIFACT_ID_BASE-$i-$VERSION-cinterop-libsecp256k1.klib \
-Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION.module \ -Dtypes=module,klib \
-Dtypes=module \ -Dclassifiers=,cinterop-libsecp256k1 \
-Dclassifiers= \ -Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \
-Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \ -Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar
-Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar elif [ $i == jni-android ]; then
else mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \ -DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
-DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \ -Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.aar \
-Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.jar \ -Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION.module \
-Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION.module \ -Dtypes=module \
-Dtypes=module \ -Dclassifiers= \
-Dclassifiers= \ -Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \
-Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \ -Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar
-Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar else
fi mvn deploy:deploy-file -DrepositoryId=ossrh -Durl=https://oss.sonatype.org/content/repositories/snapshots/ \
popd -DpomFile=$ARTIFACT_ID_BASE-$i-$VERSION.pom \
pushd . -Dfile=$ARTIFACT_ID_BASE-$i-$VERSION.jar \
-Dfiles=$ARTIFACT_ID_BASE-$i-$VERSION.module \
-Dtypes=module \
-Dclassifiers= \
-Dsources=$ARTIFACT_ID_BASE-$i-$VERSION-sources.jar \
-Djavadoc=$ARTIFACT_ID_BASE-$i-$VERSION-javadoc.jar
fi
popd
pushd .
done done

View File

@@ -3,8 +3,12 @@ package = secp256k1
headers = secp256k1.h secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h headers = secp256k1.h secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h
headerFilter = secp256k1/** secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h secp256k1.h headerFilter = secp256k1/** secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h secp256k1.h
libraryPaths.linux = c/secp256k1/build/linux/ staticLibraries.linux = libsecp256k1.a
libraryPaths.linux = c/secp256k1/build/linux/ native/build/linux/ native/build/darwin/
linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib
libraryPaths.ios = c/secp256k1/build/ios/ /usr/local/lib staticLibraries.ios = libsecp256k1.a
libraryPaths.ios_x64 = c/secp256k1/build/ios/ /usr/local/lib native/build/ios/
libraryPaths.ios_arm64 = c/secp256k1/build/ios/ /usr/local/lib native/build/ios/
libraryPaths.ios_simulator_arm64 = c/secp256k1/build/ios/ /usr/local/lib native/build/iosSimulatorArm64/
linkerOpts.ios = -framework Security -framework Foundation linkerOpts.ios = -framework Security -framework Foundation

View File

@@ -4,7 +4,7 @@ import kotlinx.cinterop.*
import platform.posix.size_tVar import platform.posix.size_tVar
import secp256k1.* import secp256k1.*
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class, ExperimentalForeignApi::class)
public object Secp256k1Native : Secp256k1 { public object Secp256k1Native : Secp256k1 {
private val ctx: CPointer<secp256k1_context> by lazy { private val ctx: CPointer<secp256k1_context> by lazy {
@@ -125,6 +125,7 @@ public object Secp256k1Native : Secp256k1 {
public override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray { public override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
require(tweak.size == 32)
memScoped { memScoped {
val added = privkey.copyOf() val added = privkey.copyOf()
val natAdd = toNat(added) val natAdd = toNat(added)
@@ -136,6 +137,7 @@ public object Secp256k1Native : Secp256k1 {
public override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray { public override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
require(privkey.size == 32) require(privkey.size == 32)
require(tweak.size == 32)
memScoped { memScoped {
val multiplied = privkey.copyOf() val multiplied = privkey.copyOf()
val natMul = toNat(multiplied) val natMul = toNat(multiplied)
@@ -156,6 +158,7 @@ public object Secp256k1Native : Secp256k1 {
public override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray { public override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
require(tweak.size == 32)
memScoped { memScoped {
val nPubkey = allocPublicKey(pubkey) val nPubkey = allocPublicKey(pubkey)
val nTweak = toNat(tweak) val nTweak = toNat(tweak)
@@ -166,6 +169,7 @@ public object Secp256k1Native : Secp256k1 {
public override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray { public override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
require(pubkey.size == 33 || pubkey.size == 65) require(pubkey.size == 33 || pubkey.size == 65)
require(tweak.size == 32)
memScoped { memScoped {
val nPubkey = allocPublicKey(pubkey) val nPubkey = allocPublicKey(pubkey)
val nTweak = toNat(tweak) val nTweak = toNat(tweak)
@@ -175,6 +179,7 @@ public object Secp256k1Native : Secp256k1 {
} }
public override fun pubKeyCombine(pubkeys: Array<ByteArray>): ByteArray { public override fun pubKeyCombine(pubkeys: Array<ByteArray>): ByteArray {
require(pubkeys.isNotEmpty())
pubkeys.forEach { require(it.size == 33 || it.size == 65) } pubkeys.forEach { require(it.size == 33 || it.size == 65) }
memScoped { memScoped {
val nPubkeys = pubkeys.map { allocPublicKey(it).ptr } val nPubkeys = pubkeys.map { allocPublicKey(it).ptr }
@@ -199,6 +204,7 @@ public object Secp256k1Native : Secp256k1 {
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray { public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
require(sig.size == 64) require(sig.size == 64)
require(message.size == 32) require(message.size == 32)
require(recid in 0..3)
memScoped { memScoped {
val nSig = toNat(sig) val nSig = toNat(sig)
val rSig = alloc<secp256k1_ecdsa_recoverable_signature>() val rSig = alloc<secp256k1_ecdsa_recoverable_signature>()
@@ -232,7 +238,7 @@ public object Secp256k1Native : Secp256k1 {
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed") secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed")
val nData = toNat(data) val nData = toNat(data)
val nSig = toNat(signature) val nSig = toNat(signature)
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32, pubkey.ptr) == 1 return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32u, pubkey.ptr) == 1
} }
} }

View File

@@ -1,4 +1,3 @@
plugins { plugins {
kotlin("multiplatform") kotlin("multiplatform")
if (System.getProperty("includeAndroid")?.toBoolean() == true) { if (System.getProperty("includeAndroid")?.toBoolean() == true) {
@@ -36,14 +35,14 @@ kotlin {
} }
if (includeAndroid) { if (includeAndroid) {
android { androidTarget {
compilations.all { compilations.all {
kotlinOptions.jvmTarget = "1.8" kotlinOptions.jvmTarget = "1.8"
} }
sourceSets["androidMain"].dependencies { sourceSets["androidMain"].dependencies {
implementation(project(":jni:android")) implementation(project(":jni:android"))
} }
sourceSets["androidTest"].dependencies { sourceSets["androidUnitTest"].dependencies {
implementation(kotlin("test-junit")) implementation(kotlin("test-junit"))
implementation("androidx.test.ext:junit:1.1.2") implementation("androidx.test.ext:junit:1.1.2")
implementation("androidx.test.espresso:espresso-core:3.3.0") implementation("androidx.test.espresso:espresso-core:3.3.0")
@@ -51,17 +50,18 @@ kotlin {
} }
} }
linuxX64("linux") linuxX64()
iosX64()
ios() iosArm64()
iosSimulatorArm64()
} }
val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true val includeAndroid = System.getProperty("includeAndroid")?.toBoolean() ?: true
if (includeAndroid) { if (includeAndroid) {
extensions.configure<com.android.build.gradle.LibraryExtension>("android") { extensions.configure<com.android.build.gradle.LibraryExtension>("android") {
defaultConfig { defaultConfig {
compileSdkVersion(30) compileSdk = 30
minSdkVersion(21) minSdk = 21
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -352,6 +352,38 @@ class Secp256k1Test {
} }
} }
@Test
fun testInvalidArguments() {
assertFails {
Secp256k1.pubkeyCreate(ByteArray(32))
}
assertFails {
Secp256k1.pubkeyCreate(Hex.decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
}
assertFails {
Secp256k1.pubkeyParse(ByteArray(33))
}
assertFails {
Secp256k1.pubkeyParse(Hex.decode("03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
}
assertFails {
Secp256k1.pubKeyCombine(arrayOf())
}
assertFails {
Secp256k1.pubKeyCombine(arrayOf(ByteArray(0)))
}
assertFails {
Secp256k1.signSchnorr(ByteArray(0), Hex.decode("0101010101010101010101010101010101010101010101010101010101010101"), null)
}
assertFails {
Secp256k1.ecdsaRecover(
Hex.decode("01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"),
Hex.decode("0202020202020202020202020202020202020202020202020202020202020202"),
-1
)
}
}
@Test @Test
fun fuzzEcdsaSignVerify() { fun fuzzEcdsaSignVerify() {
val random = Random.Default val random = Random.Default