diff --git a/scripts/jshell/ecc-basics.jsh b/scripts/jshell/ecc-basics.jsh new file mode 100644 index 0000000..d479fbf --- /dev/null +++ b/scripts/jshell/ecc-basics.jsh @@ -0,0 +1,12 @@ +// ecc-basics.jsh + +IO.println("ECC Basics Demo") + +import module org.bitcoinj.secp + +var P = Secp256k1.P.toString(16) +var G = Secp256k1.G + +var secp = Secp256k1.get() +var priv = secp.ecPrivKeyCreate() +var pub = secp.ecPubKeyCreate(priv) diff --git a/scripts/jshell/ecdh.jsh b/scripts/jshell/ecdh.jsh new file mode 100644 index 0000000..e6dfcc4 --- /dev/null +++ b/scripts/jshell/ecdh.jsh @@ -0,0 +1,12 @@ +// schnorr.jsh + +IO.println("Elliptic Curve Diffie-Hellman Demo") + +import module org.bitcoinj.secp + +var secp = Secp256k1.get() +var alice = secp.ecKeyPairCreate() +var bob = secp.ecKeyPairCreate() +var secretA = secp.ecdh(bob.publicKey(), alice).get() +var secretB = secp.ecdh(alice.publicKey(), bob).get() +secretA.equals(secretB) diff --git a/scripts/jshell/ecdsa.jsh b/scripts/jshell/ecdsa.jsh new file mode 100644 index 0000000..6227ef7 --- /dev/null +++ b/scripts/jshell/ecdsa.jsh @@ -0,0 +1,17 @@ +// ecdsa.jsh + +IO.println("ECDSA Sign/Verify Demo") + +import module org.bitcoinj.secp + +byte[] sha256(String messageString) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + digest.update(messageString.getBytes()); + return digest.digest(); +} + +var secp = Secp256k1.get() +var alice = secp.ecKeyPairCreate() +var message = sha256("Hello Stanford!") +var signature = secp.ecdsaSign(message, alice).get() +var isValid = secp.ecdsaVerify(signature, message, alice.publicKey()).get() \ No newline at end of file diff --git a/scripts/jshell/providers.jsh b/scripts/jshell/providers.jsh new file mode 100644 index 0000000..9347474 --- /dev/null +++ b/scripts/jshell/providers.jsh @@ -0,0 +1,12 @@ +// providers.jsh + +IO.println("Providers Demo") + +import module org.bitcoinj.secp + +var providers = Secp256k1.all().toList() +var ids = Secp256k1.all().map(Secp256k1.Provider::id).toList() + +var libsecp = Secp256k1.get() +var bouncy = Secp256k1.getById("bouncy-castle") + diff --git a/scripts/jshell/schnorr.jsh b/scripts/jshell/schnorr.jsh new file mode 100644 index 0000000..09d9b5a --- /dev/null +++ b/scripts/jshell/schnorr.jsh @@ -0,0 +1,11 @@ +// schnorr.jsh + +IO.println("Schnorr Sign/Verify Demo") + +import module org.bitcoinj.secp + +var secp = Secp256k1.get() +var alice = secp.ecKeyPairCreate() +var taggedMessage = secp.taggedSha256("BitDevs Protocol", "Hello Stanford!") +var schnorrSig = secp.schnorrSigSign32(taggedMessage, alice) +var isValidSchnorr = secp.schnorrSigVerify(schnorrSig, taggedMessage, alice.publicKey()).get() \ No newline at end of file diff --git a/secp-examples-jshell/build.gradle b/secp-examples-jshell/build.gradle new file mode 100644 index 0000000..c69982b --- /dev/null +++ b/secp-examples-jshell/build.gradle @@ -0,0 +1,83 @@ +import org.codehaus.groovy.runtime.GStringImpl + +plugins { + id 'java' + id 'application' + id 'org.beryx.jlink' version '3.1.4-rc' +} + +ext.moduleName = 'org.bitcoinj.secp.jshell' +ext.libSecpDir = System.getenv("LIBSECP_DIR") +ext.javaHome = System.getenv("JAVA_HOME") + +dependencies { + implementation project(':secp-api') + implementation project(':secp-bouncy') + implementation project(':secp-ffm') +} + +tasks.withType(JavaCompile).configureEach { + // Override Default release version + options.release = 25 +} + +jar { + inputs.property("moduleName", moduleName) + manifest { + attributes 'Implementation-Title': 'Placeholder App for secp256k1-jdk JShell Example', + 'Main-Class': application.mainClass, + 'Implementation-Version': archiveVersion.get() + } +} + +application { + mainModule = 'org.bitcoinj.secp.jshell' + mainClass = 'org.bitcoinj.secp.jshell.Hello' + applicationName = 'hello' +} + +run { + jvmArgs += '--enable-native-access=org.bitcoinj.secp.ffm' +} + +jlink { + options = ['--add-modules', 'org.bitcoinj.secp.ffm', + '--add-modules', 'org.bitcoinj.secp.bouncy', '--ignore-signing-information', + '--add-modules', 'jdk.jshell'] + launcher { + name = application.applicationName + } +} + +tasks.register('copyNativeLibraries', Copy) { + dependsOn tasks.jlink + from(libSecpDir) { include 'libsecp256k1.*' } + into("${tasks.jlink.imageDir}/lib") +} + +tasks.register('copyJdkSource', Copy) { + dependsOn tasks.jlink + from { + def javaHome = System.getenv('JAVA_HOME') ?: System.getProperty('java.home') + file("$javaHome/lib/src.zip") + } + into("${tasks.jlink.imageDir}/lib") + finalizedBy(tasks.named('addJshellWrapper')) +} + +tasks.register('addJshellWrapper') { + dependsOn tasks.copyJdkSource + doLast { + def jshellScript = file("${tasks.jlink.imageDir}/bin/secp-shell") + jshellScript.text = """#!/bin/bash +DIR=\$(dirname "\$0") +"\$DIR/jshell" "\$@" +""" + jshellScript.setExecutable(true) + } +} + +tasks.jlink { + finalizedBy(tasks.copyNativeLibraries, tasks.copyJdkSource) // tasks.copyProjectJavadoc +} + diff --git a/secp-examples-jshell/src/main/java/module-info.java b/secp-examples-jshell/src/main/java/module-info.java new file mode 100644 index 0000000..3eb52df --- /dev/null +++ b/secp-examples-jshell/src/main/java/module-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2023-2025 secp256k1-jdk Developers. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * JShell Example. + */ +module org.bitcoinj.secp.jshell { + requires org.bitcoinj.secp; +} diff --git a/secp-examples-jshell/src/main/java/org/bitcoinj/secp/jshell/Hello.java b/secp-examples-jshell/src/main/java/org/bitcoinj/secp/jshell/Hello.java new file mode 100644 index 0000000..a340797 --- /dev/null +++ b/secp-examples-jshell/src/main/java/org/bitcoinj/secp/jshell/Hello.java @@ -0,0 +1,22 @@ +/* + * Copyright 2023-2025 secp256k1-jdk Developers. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.bitcoinj.secp.jshell; + +public class Hello { + void main() { + IO.println("Hello! Try running the `secp-shell` executable for JShell with secp256k1-jdk built-in."); + } +} diff --git a/secp-examples-jshell/src/main/java/org/bitcoinj/secp/jshell/package-info.java b/secp-examples-jshell/src/main/java/org/bitcoinj/secp/jshell/package-info.java new file mode 100644 index 0000000..3d17e27 --- /dev/null +++ b/secp-examples-jshell/src/main/java/org/bitcoinj/secp/jshell/package-info.java @@ -0,0 +1,17 @@ +/* + * Copyright 2023-2025 secp256k1-jdk Developers. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/// Contains a placeholder application for a custom JShell build. +package org.bitcoinj.secp.jshell; diff --git a/settings.gradle b/settings.gradle index 421d993..028c92c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,5 +7,6 @@ include 'secp-graalvm' // GraalVM Foreign Function Registration suppor include 'secp-bitcoinj' // bitcoinj integration utilities and tests (P2TR address generation, etc.) include 'secp-integration-test' // Integration tests of API implementations (ffm and bouncy) include 'secp-examples-java' // Java examples +include 'secp-examples-jshell' // jshell example include 'secp-examples-kotlin' // Kotlin examples