├── settings.gradle
├── img
└── java-logo.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── scripts
└── deploy-artifactory.sh
├── .idea
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
└── vcs.xml
├── eosiojavasoftkeysignatureprovider
├── src
│ ├── main
│ │ └── java
│ │ │ └── one
│ │ │ └── block
│ │ │ └── eosiosoftkeysignatureprovider
│ │ │ ├── package-info.java
│ │ │ ├── error
│ │ │ ├── package-info.java
│ │ │ ├── ImportKeyError.java
│ │ │ └── SoftKeySignatureErrorConstants.java
│ │ │ └── SoftKeySignatureProviderImpl.java
│ └── test
│ │ └── java
│ │ └── one
│ │ └── block
│ │ └── eosiojavasoftkeysignatureprovider
│ │ └── SoftKeySignatureProviderImplTest.java
└── build.gradle
├── LICENSE
├── .travis.yml
├── gradlew.bat
├── .gitignore
├── gradlew
├── README.md
└── CONTRIBUTING.md
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':eosiojavasoftkeysignatureprovider'
2 |
3 |
--------------------------------------------------------------------------------
/img/java-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-softkey-signature-provider/HEAD/img/java-logo.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EOSIO/eosio-java-softkey-signature-provider/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/scripts/deploy-artifactory.sh:
--------------------------------------------------------------------------------
1 | DEST_REPO=$1 && \
2 | echo "publishing to $DEST_REPO on Artifactory" && \
3 | ./gradlew clean artifactoryPublish -Partifactory_repo=$DEST_REPO
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/eosiojavasoftkeysignatureprovider/src/main/java/one/block/eosiosoftkeysignatureprovider/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Provides the implementation class that implements ISignatureProvider.
3 | */
4 | package one.block.eosiosoftkeysignatureprovider;
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Aug 21 09:21:31 EDT 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/eosiojavasoftkeysignatureprovider/src/main/java/one/block/eosiosoftkeysignatureprovider/error/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Provides the classes necessary to describe meaningful exceptions that occur during a
3 | * signature provider implementation. Individual error classes like {@link one.block.eosiosoftkeysignatureprovider.error.ImportKeyError}
4 | * and error messages defined in a constants file {@link one.block.eosiosoftkeysignatureprovider.error.SoftKeySignatureErrorConstants}
5 | * are included in this package.
6 | */
7 | package one.block.eosiosoftkeysignatureprovider.error;
--------------------------------------------------------------------------------
/eosiojavasoftkeysignatureprovider/src/main/java/one/block/eosiosoftkeysignatureprovider/error/ImportKeyError.java:
--------------------------------------------------------------------------------
1 | package one.block.eosiosoftkeysignatureprovider.error;
2 |
3 | import one.block.eosiojava.error.signatureProvider.SignatureProviderError;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | /**
7 | * Error class is used when there is an exception while attempting to import a key into the
8 | * signature provider.
9 | *
10 | */
11 | public class ImportKeyError extends SignatureProviderError {
12 | public ImportKeyError() {
13 | }
14 |
15 | public ImportKeyError(@NotNull String message) {
16 | super(message);
17 | }
18 |
19 | public ImportKeyError(@NotNull String message, @NotNull Exception exception) {
20 | super(message, exception);
21 | }
22 |
23 | public ImportKeyError(@NotNull Exception exception) {
24 | super(exception);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017-2019 block.one and its contributors. All rights reserved.
2 |
3 | The MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | env:
3 | global:
4 | - ARTIFACTORY_CONTEXT_URL=https://blockone.jfrog.io/blockone
5 | - ARTIFACTORY_REPO=android-libs-scratch-local
6 | - ARTIFACTORY_LIBS_PATH=https://blockone.jfrog.io/blockone/android-libs
7 | before_cache:
8 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
9 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
10 |
11 | before_install:
12 | - echo "artifactory_username=$ARTIFACTORY_USERNAME" > gradle.properties
13 | - echo "artifactory_password=$ARTIFACTORY_PASSWORD" >> gradle.properties
14 | - echo "artifactory_path_android_libraries=$ARTIFACTORY_LIBS_PATH" >> gradle.properties
15 | - echo "artifactory_contextURL=$ARTIFACTORY_CONTEXT_URL" >> gradle.properties
16 | - echo "artifactory_repo=$ARTIFACTORY_REPO" >> gradle.properties
17 |
18 | before_deploy:
19 | - echo "artifactory_username=$ARTIFACTORY_USERNAME" > gradle.properties
20 | - echo "artifactory_password=$ARTIFACTORY_PASSWORD" >> gradle.properties
21 | - echo "artifactory_path_android_libraries=$ARTIFACTORY_LIBS_PATH" >> gradle.properties
22 | - echo "artifactory_contextURL=$ARTIFACTORY_CONTEXT_URL" >> gradle.properties
23 | - echo "artifactory_repo=$ARTIFACTORY_REPO" >> gradle.properties
24 |
25 | deploy:
26 | - provider: script
27 | skip_cleanup: true
28 | script: "bash scripts/deploy-artifactory.sh 'android-libs-feature-local'"
29 | on:
30 | all_branches: true
31 | condition: ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} =~ ^feature\/.*$
32 | # develop deploys
33 | - provider: script
34 | skip_cleanup: true
35 | script: "bash scripts/deploy-artifactory.sh 'android-libs-dev-local'"
36 | on:
37 | branch:
38 | - develop
39 | # release branches and master
40 | - provider: script
41 | skip_cleanup: true
42 | script: "bash scripts/deploy-artifactory.sh 'android-libs-release-local'"
43 | on:
44 | all_branches: true
45 | condition: $TRAVIS_BRANCH == master || ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} =~ ^release\/.*$
46 | # tagged releases from master, go to distribution
47 | - provider: script
48 | skip_cleanup: true
49 | script: "bash scripts/deploy-artifactory.sh 'eosiojavasoftkeysignatureprovider-product-eosio-dist'"
50 | on:
51 | tags: true
52 | branch: master
53 |
54 | after_deploy:
55 | - echo "cleaning up properties"
56 | - rm gradle.properties
57 |
58 |
59 | cache:
60 | directories:
61 | - $HOME/.gradle/caches/
62 | - $HOME/.gradle/wrapper/
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 |
4 | # User-specific stuff
5 | .idea/**/aws.xml
6 | .idea/**/jarRepositories.xml
7 | .idea/**/workspace.xml
8 | .idea/**/tasks.xml
9 | .idea/**/usage.statistics.xml
10 | .idea/**/dictionaries
11 | .idea/**/shelf
12 | .idea/**/compiler.xml
13 | .idea/**/encodings.xml
14 | .idea/**/misc.xml
15 | .idea/**/vcs.xml
16 | local.properties
17 |
18 | # Generated files
19 | .idea/**/contentModel.xml
20 | .idea/**/caches/
21 | .idea/**/modules.xml
22 | .idea/**/runConfigurations.xml
23 |
24 | # Sensitive or high-churn files
25 | .idea/**/dataSources/
26 | .idea/**/dataSources.ids
27 | .idea/**/dataSources.local.xml
28 | .idea/**/sqlDataSources.xml
29 | .idea/**/dynamic.xml
30 | .idea/**/uiDesigner.xml
31 | .idea/**/dbnavigator.xml
32 |
33 | # Gradle
34 | .idea/**/gradle.xml
35 | .idea/**/libraries
36 |
37 | # Gradle and Maven with auto-import
38 | # When using Gradle or Maven with auto-import, you should exclude module files,
39 | # since they will be recreated, and may cause churn. Uncomment if using
40 | # auto-import.
41 | # .idea/modules.xml
42 | # .idea/*.iml
43 | # .idea/modules
44 | *.iml
45 |
46 | # CMake
47 | cmake-build-*/
48 |
49 | # Mongo Explorer plugin
50 | .idea/**/mongoSettings.xml
51 |
52 | # File-based project format
53 | *.iws
54 |
55 | # IntelliJ
56 | out/
57 |
58 | # mpeltonen/sbt-idea plugin
59 | .idea_modules/
60 |
61 | # JIRA plugin
62 | atlassian-ide-plugin.xml
63 |
64 | # Cursive Clojure plugin
65 | .idea/replstate.xml
66 |
67 | # Crashlytics plugin (for Android Studio and IntelliJ)
68 | com_crashlytics_export_strings.xml
69 | crashlytics.properties
70 | crashlytics-build.properties
71 | fabric.properties
72 |
73 | # Editor-based Rest Client
74 | .idea/httpRequests
75 |
76 | # Android studio 3.1+ serialized cache file
77 | .idea/caches/build_file_checksums.ser
78 |
79 | ### Java ###
80 | *.class
81 |
82 | # Mobile Tools for Java (J2ME)
83 | .mtj.tmp/
84 |
85 | # Package Files #
86 | *.war
87 | *.ear
88 |
89 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
90 | hs_err_pid*
91 |
92 | ### Gradle ###
93 | .gradle
94 | /build/
95 | /**/build/
96 |
97 | # Ignore Gradle GUI config
98 | gradle-app.setting
99 |
100 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
101 | !gradle-wrapper.jar
102 |
103 | # Cache of project
104 | .gradletasknamecache
105 |
106 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
107 | # gradle/wrapper/gradle-wrapper.properties
108 |
109 | gradle.properties
110 |
--------------------------------------------------------------------------------
/eosiojavasoftkeysignatureprovider/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | //Remove 'com.jfrog.artifactory' plugin if you are not using Artifactory
4 | id 'com.jfrog.artifactory' version '4.9.5'
5 | id 'maven-publish'
6 |
7 | }
8 |
9 | group 'one.block'
10 |
11 | repositories {
12 | //Remove maven{} block if you are not using Artifactory
13 | maven {
14 | credentials{
15 | username artifactory_username
16 | password artifactory_password
17 | }
18 | url artifactory_path_android_libraries
19 |
20 | }
21 |
22 | //Uncomment if you are not using Artifactory
23 | /*
24 | jcenter()
25 | mavenCentral()
26 | */
27 | }
28 |
29 | sourceCompatibility = 1.8
30 | targetCompatibility = 1.8
31 |
32 | dependencies {
33 | implementation 'one.block:eosiojava:1.0.0'
34 | testCompile group: 'junit', name: 'junit', version: '4.12'
35 | testCompile 'org.mockito:mockito-core:3.0.0'
36 | testCompile 'org.powermock:powermock-module-junit4:2.0.2'
37 | testCompile 'org.powermock:powermock-api-mockito2:2.0.2'
38 | }
39 |
40 | //Changes module cache control ---- Default is 24 hrs
41 | configurations.all {
42 | resolutionStrategy.cacheChangingModulesFor 1, 'seconds'
43 | }
44 |
45 | def libraryGroupId = 'one.block'
46 | def libraryArtifactId = 'eosiojavasoftkeysignatureprovider'
47 | def libraryVersion = '1.0.0'
48 |
49 | task sourcesJar(type: Jar, dependsOn: classes){
50 | classifier = 'sources'
51 | from sourceSets.main.allSource
52 | }
53 |
54 | javadoc.failOnError = false
55 | task javadocJar(type: Jar, dependsOn: javadoc){
56 | classifier = 'javadoc'
57 | from javadoc.destinationDir
58 | }
59 |
60 | artifacts {
61 | archives sourcesJar
62 | archives javadocJar
63 | }
64 |
65 | publishing {
66 | publications {
67 | jar(MavenPublication) {
68 | from components.java
69 |
70 | artifact sourcesJar {
71 | classifier "sources"
72 | }
73 |
74 | artifact javadocJar {
75 | classifier "javadoc"
76 | }
77 |
78 | groupId libraryGroupId
79 | version libraryVersion
80 | artifactId libraryArtifactId
81 |
82 | artifact("$buildDir/libs/${artifactId}.jar")
83 | }
84 | }
85 | }
86 |
87 | //Remove artifactory{} block if you are not using Artifactory
88 | artifactory {
89 | contextUrl = artifactory_contextURL
90 | publish {
91 | repository {
92 | repoKey = artifactory_repo
93 |
94 | username = artifactory_username
95 | password = artifactory_password
96 | }
97 | defaults {
98 | publications('jar')
99 | publishArtifacts = true
100 |
101 | properties = ['qa.level': 'basic', 'q.os': 'android', 'dev.team': 'core']
102 | publishPom = true
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/eosiojavasoftkeysignatureprovider/src/main/java/one/block/eosiosoftkeysignatureprovider/error/SoftKeySignatureErrorConstants.java:
--------------------------------------------------------------------------------
1 | package one.block.eosiosoftkeysignatureprovider.error;
2 |
3 | import one.block.eosiosoftkeysignatureprovider.SoftKeySignatureProviderImpl;
4 |
5 | /**
6 | * Error constants that pertain to the signing of transactions using the softkey signature provider
7 | * implementation {@link one.block.eosiosoftkeysignatureprovider.SoftKeySignatureProviderImpl}
8 | */
9 | public class SoftKeySignatureErrorConstants {
10 | /**
11 | * Unable to convert the provided key to PEM format. This probably indicates that the provided
12 | * key is not recognized or invalid.
13 | */
14 | public static final String IMPORT_KEY_CONVERT_TO_PEM_ERROR = "Can't convert %s to Pem format.";
15 | /**
16 | * No key information was provided.
17 | */
18 | public static final String IMPORT_KEY_INPUT_EMPTY_ERROR = "Input can't be empty!";
19 | /**
20 | * PEM conversion produced an empty string.
21 | */
22 | public static final String CONVERT_TO_PEM_EMPTY_ERROR = "Converting to pem was success but pem result is empty.";
23 | /**
24 | * The signable transaction preparation failed. There may have been a problem with the
25 | * provided serialized transaction.
26 | */
27 | public static final String SIGN_TRANS_PREPARE_SIGNABLE_TRANS_ERROR = "Error when trying to prepare signable transaction from serialized transaction %s";
28 | /**
29 | * The list of keys to be used for signing was empty.
30 | */
31 | public static final String SIGN_TRANS_EMPTY_KEY_LIST = "List of public keys to sign can't be empty!";
32 | /**
33 | * The provided chain id was empty.
34 | */
35 | public static final String SIGN_TRANS_EMPTY_CHAIN_ID = "Chain id can't be empty!";
36 | /**
37 | * The provided serialized transaction was empty.
38 | */
39 | public static final String SIGN_TRANS_EMPTY_TRANSACTION = "Serialized Transaction can't be empty.";
40 | /**
41 | * No keys have been imported into the signature provider for signing. A key is necessary to
42 | * sign a transaction.
43 | */
44 | public static final String SIGN_TRANS_NO_KEY_AVAILABLE = "No key available in signature provider! Make sure to call import key.";
45 | /**
46 | * A public key is derived from the private key imported for signing. The public keys needed to verify the transaction that come from
47 | * the chain are compared to the derived public key. If an unexpected exception happens during the matching process, this error message is thrown.
48 | */
49 | public static final String SIGN_TRANS_SEARCH_KEY_ERROR = "Error when trying to search for corresponding private key from input public key %s";
50 | /**
51 | * A public key is derived from the private key imported for signing. The public keys needed to verify the transaction that come from
52 | * the chain are compared to the derived public key. If there is not a match this error message is thrown.
53 | */
54 | public static final String SIGN_TRANS_KEY_NOT_FOUND = "Found no corresponding private key with input public key %s";
55 | /**
56 | * Encountered when the domain parameters for the key being used to sign the transaction are
57 | * unobtainable.
58 | */
59 | public static final String SIGN_TRANS_GET_CURVE_DOMAIN_ERROR = "Error when trying to get EC Curve domain of %s";
60 | /**
61 | * Describes a failure to format the signature that must accompany a signed transaction.
62 | */
63 | public static final String SIGN_TRANS_FORMAT_SIGNATURE_ERROR = "Error when trying to format signature.";
64 | /**
65 | * Key curve is not supported in key transformation on {@link SoftKeySignatureProviderImpl#getAvailableKeys()}
66 | */
67 | public static final String GET_KEYS_KEY_FORMAT_NOT_SUPPORTED = "Error on trying to transform key in getAvailableKey(): Algorithm is not supported!";
68 | }
69 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | # EOSIO SDK for Java: Softkey Signature Provider
3 |
4 | [](https://github.com/EOSIO/eosio-java-softkey-signature-provider/blob/master/LICENSE)
5 | 
6 | 
7 |
8 | Softkey Signature Provider is an example pluggable signature provider for [EOSIO SDK for Java](https://github.com/EOSIO/eosio-java). It allows for signing transactions using in-memory SECP256K1 and SECP256R1 keys.
9 |
10 | **Important:** Softkey Signature Provider stores keys in memory and is therefore not secure. It should only be used for development purposes. In production, we strongly recommend using a signature provider that interfaces with a KeyStore, authenticator or wallet.
11 |
12 | *All product and company names are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.*
13 |
14 | ## Contents
15 |
16 | - [Updates](#updates)
17 | - [About Signature Providers](#about-signature-providers)
18 | - [Prerequisites](#prerequisites)
19 | - [Installation](#installation)
20 | - [Basic Usage](#basic-usage)
21 | - [Android Example App](#android-example-app)
22 | - [Library Methods](#library-methods)
23 | - [Want to Help?](#want-to-help)
24 | - [License & Legal](#license)
25 |
26 | ## Updates
27 | - Version 1.0.0. This version consumes the new eosio-java library version 1.0.0.
28 | - Version 0.1.3. The version consumes the new eosio-java library version 0.1.2.
29 | - Version 0.1.2. The version includes updates on Mockito and Powermock dependencies to prevent the build error "Failed to transform...using Jetifier." that is occurring with new versions of AndroidX.
30 |
31 | # About Signature Providers
32 |
33 | The Signature Provider abstraction is arguably the most useful of all of the [EOSIO SDK for Java](https://github.com/EOSIO/eosio-java) providers. It is responsible for:
34 |
35 | * finding out what keys are available for signing (`getAvailableKeys`), and
36 | * requesting and obtaining transaction signatures with a subset of the available keys (`signTransaction`).
37 |
38 | By simply switching out the signature provider on a transaction, signature requests can be routed any number of ways. Need a signature from keys in the platform's Keychain or KeyStore? Configure the [TransactionSession](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionSession.java) with a conforming signature provider that exposes that functionality. Need signatures from a wallet on the user's device? A signature provider can do that too!
39 |
40 | All signature providers must conform to the [ISignatureProvider](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/interfaces/ISignatureProvider.java) Protocol.
41 |
42 | ### Prerequisites
43 |
44 | * Java JDK 1.8+ (1.7 source compatibility is targeted)
45 | * Gradle 4.10.1+
46 |
47 | Since EOSIO SDK for Java: Softkey Signature Provider is not an Android specific project, we recommend using IntelliJ if you are going to work on it. You can use Android Studio but be aware that some of the menu options under Build like `Rebuild Project` and `Clean Project` will not work correctly. You may still compile within Android Studio using `Make Project` under the Build menu, or by using Gradle from the command line.
48 |
49 | ## Installation
50 |
51 | This provider is intended to be used in conjunction with [EOSIO SDK for Java](https://github.com/EOSIO/eosio-java) as a provider plugin.
52 |
53 | To use Softkey Signature Provider with EOSIO SDK for Java in your app, add the following modules to your `build.gradle`:
54 |
55 | ```java
56 | implementation 'one.block:eosiojava:1.0.0'
57 | implementation 'one.block:eosiojavasoftkeysignatureprovider:1.0.0'
58 | ```
59 |
60 | If you are using Softkey Signature Provider, or any library that depends on it, in an Android application you must also add the following to your application's `build.gradle` file in the `android` section:
61 |
62 | ```groovy
63 | // Needed to get bitcoin-j to produce a valid apk for android.
64 | packagingOptions {
65 | exclude 'lib/x86_64/darwin/libscrypt.dylib'
66 | exclude 'lib/x86_64/freebsd/libscrypt.so'
67 | exclude 'lib/x86_64/linux/libscrypt.so'
68 | }
69 | ```
70 | The `build.gradle` files for the project currently include configurations for publishing the project to Artifactory. These should be removed if you are not planning to use Artifactory or you will encounter build errors. To do so, make the changes marked by comments throughout the files.
71 |
72 | Then refresh your gradle project. Then you're all set for the [Basic Usage](#basic-usage) example!
73 |
74 | ## Basic Usage
75 |
76 | Generally, signature providers are called by the [TransactionProcessor](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java) during signing. (See an [example here](https://github.com/EOSIO/eosio-java#basic-usage).) If you find, however, that you need to get available keys or request signing directly, this library can be invoked as follows:
77 |
78 | ```java
79 | SoftKeySignatureProviderImpl provider = new SoftKeySignatureProviderImpl();
80 | try {
81 | List availableKeys = provider.getAvailableKeys();
82 | } catch (GetAvailableKeysError getAvailableKeysError) {
83 | getAvailableKeysError.printStackTrace();
84 | }
85 | ```
86 |
87 | And to import a private key:
88 |
89 | ```java
90 | try {
91 | provider.importKey("Your eos format private key in SECP256K1 or SECP256R1 type");
92 | } catch (ImportKeyError importKeyError) {
93 | importKeyError.printStackTrace();
94 | }
95 | ```
96 |
97 | To sign an `EosioTransactionSignatureRequest`, you should first create it with your serialized transaction and list of public keys. EOSIO SDK for Java handles the creation of the object for you.
98 |
99 | Finally, call `signTransaction` to sign.
100 |
101 | ```java
102 | try {
103 | String serializedTransaction = "Your serialized transaction";
104 | List publicKeys = Arrays.asList("Your eos format public key in SECP256K1 or SECP256R1 type");
105 | EosioTransactionSignatureRequest request = new EosioTransactionSignatureRequest(serializedTransaction, publicKeys, chainId, null, false);
106 | EosioTransactionSignatureResponse response = provider.signTransaction(request);
107 | } catch (SignTransactionError signTransactionError) {
108 | signTransactionError.printStackTrace();
109 | }
110 | ```
111 |
112 | ## Android Example App
113 |
114 | If you'd like to see EOSIO SDK for Java: Softkey Signature Provider in action, check out our open source [Android Example App](https://github.com/EOSIO/eosio-java-android-example-app)--a working application that fetches an account's token balance and pushes a transfer action.
115 |
116 | ## Library Methods
117 |
118 | This library is an example implementation of [ISignatureProvider](https://github.com/EOSIO/eosio-java/blob/master/eosiojava/src/main/java/one/block/eosiojava/interfaces/ISignatureProvider.java). It implements the following protocol methods:
119 |
120 | * `signTransaction(EosioTransactionSignatureRequest eosioTransactionSignatureRequest)` signs a `Transaction`
121 | * `getAvailableKeys()` returns an array containing the public keys associated with the private keys that the object is initialized with
122 |
123 | Import a key by calling:
124 |
125 | * `importKey(String privateKey)`
126 |
127 | ## Want to help?
128 |
129 | Interested in contributing? That's awesome! Here are some [Contribution Guidelines](./CONTRIBUTING.md) and the [Code of Conduct](./CONTRIBUTING.md#conduct).
130 |
131 | ## License
132 |
133 | [MIT](./LICENSE)
134 |
135 | ## Important
136 |
137 | See LICENSE for copyright and license terms. Block.one makes its contribution on a voluntary basis as a member of the EOSIO community and is not responsible for ensuring the overall performance of the software or any related applications. We make no representation, warranty, guarantee or undertaking in respect of the software or any related documentation, whether expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall we be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or documentation or the use or other dealings in the software or documentation. Any test results or performance figures are indicative and will not reflect performance under all conditions. Any reference to any third party or third-party product, service or other resource is not an endorsement or recommendation by Block.one. We are not responsible, and disclaim any and all responsibility and liability, for your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so the information here may be out of date or inaccurate. Any person using or offering this software in connection with providing software, goods or services to third parties shall advise such third parties of these license terms, disclaimers and exclusions of liability. Block.one, EOSIO, EOSIO Labs, EOS, the heptahedron and associated logos are trademarks of Block.one.
138 |
139 | Wallets and related components are complex software that require the highest levels of security. If incorrectly built or used, they may compromise users’ private keys and digital assets. Wallet applications and related components should undergo thorough security evaluations before being used. Only experienced developers should work with this software.
140 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to EOSIO SDK for Java: Softkey Signature Provider
2 |
3 | Interested in contributing? That's awesome! Here are some guidelines to get started quickly and easily:
4 |
5 | - [Reporting An Issue](#reporting-an-issue)
6 | - [Bug Reports](#bug-reports)
7 | - [Feature Requests](#feature-requests)
8 | - [Change Requests](#change-requests)
9 | - [Working on Softkey Signature Provider](#working-on-softkey-signature-provider)
10 | - [Feature Branches](#feature-branches)
11 | - [Developing With Gradle Locally](#developing-with-gradle-locally)
12 | - [Submitting Pull Requests](#submitting-pull-requests)
13 | - [Testing and Quality Assurance](#testing-and-quality-assurance)
14 | - [Code Style and Linting](#code-style-and-linting)
15 | - [Conduct](#conduct)
16 | - [Contributor License & Acknowledgments](#contributor-license--acknowledgments)
17 | - [References](#references)
18 |
19 | ## Reporting An Issue
20 |
21 | If you're about to raise an issue because you think you've found a problem with Softkey Signature Provider, or you'd like to make a request for a new feature in the codebase, or any other reason… please read this first.
22 |
23 | The GitHub issue tracker is the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests), and [submitting pull requests](#submitting-pull-requests), but please respect the following restrictions:
24 |
25 | * Please **search for existing issues**. Help us keep duplicate issues to a minimum by checking to see if someone has already reported your problem or requested your idea.
26 |
27 | * Please **be civil**. Keep the discussion on topic and respect the opinions of others. See also our [Contributor Code of Conduct](#conduct).
28 |
29 | ### Bug Reports
30 |
31 | A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you!
32 |
33 | Guidelines for bug reports:
34 |
35 | 1. **Use the GitHub issue search** — check if the issue has already been
36 | reported.
37 |
38 | 1. **Check if the issue has been fixed** — look for [closed issues in the
39 | current milestone](/../../issues?q=is%3Aissue+is%3Aclosed) or try to reproduce it
40 | using the latest `develop` branch.
41 |
42 | A good bug report shouldn't leave others needing to chase you down for more information. Be sure to include the details of your environment and relevant tests that demonstrate the failure.
43 |
44 | [Report a bug](/../../issues/new?title=Bug%3A)
45 |
46 | ### Feature Requests
47 |
48 | Feature requests are welcome. Before you submit one be sure to have:
49 |
50 | 1. **Use the GitHub search** and check the feature hasn't already been requested.
51 | 1. Take a moment to think about whether your idea fits with the scope and aims of the project.
52 | 1. Remember, it's up to *you* to make a strong case to convince the project's leaders of the merits of this feature. Please provide as much detail and context as possible, this means explaining the use case and why it is likely to be common.
53 |
54 | ### Change Requests
55 |
56 | Change requests cover both architectural and functional changes to how Softkey Signature Provider works. If you have an idea for a new or different dependency, a refactor, or an improvement to a feature, etc - please be sure to:
57 |
58 | 1. **Use the GitHub search** and check someone else didn't get there first
59 | 1. Take a moment to think about the best way to make a case for, and explain what you're thinking. Are you sure this shouldn't really be
60 | a [bug report](#bug-reports) or a [feature request](#feature-requests)? Is it really one idea or is it many? What's the context? What problem are you solving? Why is what you are suggesting better than what's already there?
61 |
62 | ## Working on Softkey Signature Provider
63 |
64 | Code contributions are welcome and encouraged! If you are looking for a good place to start, check out the [good first issue](/../../labels/good%20first%20issue) label in GitHub issues.
65 |
66 | Also, please follow these guidelines when submitting code:
67 |
68 | ### Feature Branches
69 |
70 | To get it out of the way:
71 |
72 | - **[develop](/../../tree/develop)** is the development branch. All work on the next release happens here so you should generally branch off `develop`. Do **NOT** use this branch for a production site.
73 | - **[master](/../../tree/master)** contains the latest release of Softkey Signature Provider. This branch may be used in production. Do **NOT** use this branch to work on Softkey Signature Provider's source.
74 |
75 | ### Developing With Gradle Locally
76 |
77 | By default, libraries are installed from remote Maven repositories through Gradle. If, however, you wish to develop locally and you'd like to integrate with locally-cloned versions of EOSIO SDK for Java and/or other Providers, follow these instructions:
78 |
79 | 1. Clone this and other repos into the same directory, as siblings of one another.
80 | 1. Github repo of all libraries:
81 | * [EOSIO SDK for Java](https://github.com/EOSIO/eosio-java): The core EOSIO SDK for Java library
82 | * [RPC Provider](https://github.com/EOSIO/eosio-java-android-rpc-provider): The RPC provider implementation in the core library
83 | * [ABIEOS Serialization Provider](https://github.com/EOSIO/eosio-java-android-abieos-serialization-provider): A pluggable serialization provider for EOSIO SDK for Java using ABIEOS (for transaction and action conversion between JSON and binary data representations)
84 | * [Softkey Signature Provider](https://github.com/EOSIO/eosio-java-softkey-signature-provider): An example pluggable signature provider for EOSIO SDK for Java for signing transactions using in-memory keys (not for production use)
85 | 1. Import as a gradle project into your favorite IDE or build with gradle from the command line.
86 | 1. Develop!
87 |
88 | ### Submitting Pull Requests
89 |
90 | Pull requests are awesome. If you're looking to raise a PR for something which doesn't have an open issue, please think carefully about [raising an issue](#reporting-an-issue) which your PR can close, especially if you're fixing a bug. This makes it more likely that there will be enough information available for your PR to be properly tested and merged.
91 |
92 | ### Testing and Quality Assurance
93 |
94 | Never underestimate just how useful quality assurance is. If you're looking to get involved with the code base and don't know where to start, checking out and testing a pull request is one of the most useful things you could do.
95 |
96 | Essentially, [check out the latest develop branch](#working-on-softkey-signature-provider), take it for a spin, and if you find anything odd, please follow the [bug report guidelines](#bug-reports) and let us know!
97 |
98 | ### Code Style and Linting
99 |
100 | Softkey Signature Provider leverages [SonarLint](https://www.sonarlint.org/) for linting and the [Google Java Style Guide](https://github.com/google/styleguide) with tab size and indent set to 4, and continuation indent set to 8 for code format flagging. Once SonarLint is installed, linting warnings and errors will be flagged inline with squiggles. Automatic code formatting can be accomplished by downloading and importing the Google Java Style settings into your IDE.
101 |
102 | Please be sure to resolve any linting issues introduced by your contributions prior to requesting a review on your PR.
103 |
104 | ## Conduct
105 |
106 | While contributing, please be respectful and constructive, so that participation in our project is a positive experience for everyone.
107 |
108 | Examples of behavior that contributes to creating a positive environment include:
109 | - Using welcoming and inclusive language
110 | - Being respectful of differing viewpoints and experiences
111 | - Gracefully accepting constructive criticism
112 | - Focusing on what is best for the community
113 | - Showing empathy towards other community members
114 |
115 | Examples of unacceptable behavior include:
116 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
117 | - Trolling, insulting/derogatory comments, and personal or political attacks
118 | - Public or private harassment
119 | - Publishing others’ private information, such as a physical or electronic address, without explicit permission
120 | - Other conduct which could reasonably be considered inappropriate in a professional setting
121 |
122 | ## Contributor License & Acknowledgments
123 |
124 | Whenever you make a contribution to this project, you license your contribution under the same terms as set out in LICENSE, and you represent and warrant that you have the right to license your contribution under those terms. Whenever you make a contribution to this project, you also certify in the terms of the Developer’s Certificate of Origin set out below:
125 |
126 | ```
127 | Developer Certificate of Origin
128 | Version 1.1
129 |
130 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
131 | 1 Letterman Drive
132 | Suite D4700
133 | San Francisco, CA, 94129
134 |
135 | Everyone is permitted to copy and distribute verbatim copies of this
136 | license document, but changing it is not allowed.
137 |
138 |
139 | Developer's Certificate of Origin 1.1
140 |
141 | By making a contribution to this project, I certify that:
142 |
143 | (a) The contribution was created in whole or in part by me and I
144 | have the right to submit it under the open source license
145 | indicated in the file; or
146 |
147 | (b) The contribution is based upon previous work that, to the best
148 | of my knowledge, is covered under an appropriate open source
149 | license and I have the right under that license to submit that
150 | work with modifications, whether created in whole or in part
151 | by me, under the same open source license (unless I am
152 | permitted to submit under a different license), as indicated
153 | in the file; or
154 |
155 | (c) The contribution was provided directly to me by some other
156 | person who certified (a), (b) or (c) and I have not modified
157 | it.
158 |
159 | (d) I understand and agree that this project and the contribution
160 | are public and that a record of the contribution (including all
161 | personal information I submit with it, including my sign-off) is
162 | maintained indefinitely and may be redistributed consistent with
163 | this project or the open source license(s) involved.
164 | ```
165 |
166 | ## References
167 |
168 | * Overall CONTRIB adapted from https://github.com/mathjax/MathJax/blob/master/CONTRIBUTING.md
169 | * Conduct section adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
170 |
--------------------------------------------------------------------------------
/eosiojavasoftkeysignatureprovider/src/main/java/one/block/eosiosoftkeysignatureprovider/SoftKeySignatureProviderImpl.java:
--------------------------------------------------------------------------------
1 | package one.block.eosiosoftkeysignatureprovider;
2 |
3 |
4 | import one.block.eosiojava.enums.AlgorithmEmployed;
5 | import one.block.eosiojava.error.EosioError;
6 | import one.block.eosiojava.error.signatureProvider.GetAvailableKeysError;
7 | import one.block.eosiojava.error.signatureProvider.SignTransactionError;
8 | import one.block.eosiojava.error.utilities.EOSFormatterError;
9 | import one.block.eosiojava.error.utilities.EosFormatterSignatureIsNotCanonicalError;
10 | import one.block.eosiojava.error.utilities.PEMProcessorError;
11 | import one.block.eosiojava.interfaces.ISignatureProvider;
12 | import one.block.eosiojava.models.signatureProvider.EosioTransactionSignatureRequest;
13 | import one.block.eosiojava.models.signatureProvider.EosioTransactionSignatureResponse;
14 | import one.block.eosiojava.utilities.EOSFormatter;
15 | import one.block.eosiojava.utilities.PEMProcessor;
16 | import one.block.eosiosoftkeysignatureprovider.error.ImportKeyError;
17 | import one.block.eosiosoftkeysignatureprovider.error.SoftKeySignatureErrorConstants;
18 | import org.bitcoinj.core.Sha256Hash;
19 | import org.bouncycastle.crypto.params.ECDomainParameters;
20 | import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
21 | import org.bouncycastle.crypto.signers.ECDSASigner;
22 | import org.bouncycastle.util.encoders.Hex;
23 | import org.jetbrains.annotations.NotNull;
24 |
25 | import java.math.BigInteger;
26 | import java.util.ArrayList;
27 | import java.util.LinkedHashSet;
28 | import java.util.List;
29 | import java.util.Set;
30 |
31 | /**
32 | * Example signature provider implementation for EOSIO-java SDK that signs transactions using
33 | * an in-memory private key generated with the secp256r1, prime256v1, or secp256k1 algorithms. This
34 | * implementation is NOT secure and should only be used for educational purposes. It is NOT
35 | * advisable to store private keys outside of secure devices like TEE's and SE's.
36 | */
37 | public class SoftKeySignatureProviderImpl implements ISignatureProvider {
38 |
39 | /**
40 | * Keep a Set (Unique) of private keys in PEM format
41 | */
42 | private Set keys = new LinkedHashSet<>();
43 |
44 | /**
45 | * Maximum number of times the signature provider should try to create a canonical signature
46 | * for a secp256k1 generated key when the attempt fails.
47 | */
48 | private static final int MAX_NOT_CANONICAL_RE_SIGN = 100;
49 |
50 | /**
51 | * Index of R value in the signature result of softkey signing
52 | */
53 | private static final int R_INDEX = 0;
54 |
55 | /**
56 | * Index of S value in the signature result of softkey signing
57 | */
58 | private static final int S_INDEX = 1;
59 |
60 | /**
61 | * Signum to convert a negative value to a positive Big Integer
62 | */
63 | private static final int BIG_INTEGER_POSITIVE = 1;
64 |
65 | /**
66 | * Flag to indicate getAvailableKeys() should return keys generated with the secp256k1 algorithm in the legacy (prefaced with "EOS")
67 | */
68 | private static final boolean USING_K1_LEGACY_FORMAT = true;
69 |
70 | /**
71 | * Flag to indicate getAvailableKeys() should return keys generated with the secp256k1 algorithm in the new (prefaced with "PUB_K1_") formats
72 | */
73 | private static final boolean USING_K1_NON_LEGACY_FORMAT = false;
74 |
75 | /**
76 | * Flag to indicate whether getAvailableKeys() should return keys generated with the secp256k1 algorithm in the legacy (prefaced with "EOS") or new (prefaced with "PUB_K1_") formats.
77 | */
78 | private static final boolean DEFAULT_WHETHER_USING_K1_LEGACY_FORMAT = USING_K1_NON_LEGACY_FORMAT;
79 |
80 | /**
81 | * Import private key into softkey signature provider. Private key is stored in memory.
82 | * NOT RECOMMENDED for production use!!!!
83 | *
84 | * @param privateKey - Eos format private key
85 | * @throws ImportKeyError Exception that occurs while trying to import a key
86 | */
87 | public void importKey(@NotNull String privateKey) throws ImportKeyError {
88 | if (privateKey.isEmpty()) {
89 | throw new ImportKeyError(SoftKeySignatureErrorConstants.IMPORT_KEY_INPUT_EMPTY_ERROR);
90 | }
91 |
92 | String privateKeyPem;
93 |
94 | try {
95 | privateKeyPem = EOSFormatter.convertEOSPrivateKeyToPEMFormat(privateKey);
96 | } catch (EOSFormatterError eosFormatterError) {
97 | throw new ImportKeyError(String.format(SoftKeySignatureErrorConstants.IMPORT_KEY_CONVERT_TO_PEM_ERROR, privateKey), eosFormatterError);
98 | }
99 |
100 | if (privateKeyPem.isEmpty()) {
101 | throw new ImportKeyError(SoftKeySignatureErrorConstants.CONVERT_TO_PEM_EMPTY_ERROR);
102 | }
103 |
104 | this.keys.add(privateKeyPem);
105 | }
106 |
107 | @Override
108 | public @NotNull EosioTransactionSignatureResponse signTransaction(@NotNull EosioTransactionSignatureRequest eosioTransactionSignatureRequest) throws SignTransactionError {
109 |
110 | if (eosioTransactionSignatureRequest.getSigningPublicKeys().isEmpty()) {
111 | throw new SignTransactionError(SoftKeySignatureErrorConstants.SIGN_TRANS_EMPTY_KEY_LIST);
112 |
113 | }
114 |
115 | if (eosioTransactionSignatureRequest.getChainId().isEmpty()) {
116 | throw new SignTransactionError(SoftKeySignatureErrorConstants.SIGN_TRANS_EMPTY_CHAIN_ID);
117 | }
118 |
119 | if (eosioTransactionSignatureRequest.getSerializedTransaction().isEmpty()) {
120 | throw new SignTransactionError(SoftKeySignatureErrorConstants.SIGN_TRANS_EMPTY_TRANSACTION);
121 | }
122 |
123 | // Getting serializedTransaction and preparing signable transaction
124 | String serializedTransaction = eosioTransactionSignatureRequest.getSerializedTransaction();
125 |
126 | // This is the un-hashed message which is used to recover public key
127 | byte[] message;
128 |
129 | // This is the hashed message which is signed.
130 | byte[] hashedMessage;
131 |
132 | try {
133 | message = Hex.decode(EOSFormatter.prepareSerializedTransactionForSigning(serializedTransaction, eosioTransactionSignatureRequest.getChainId()).toUpperCase());
134 | hashedMessage = Sha256Hash.hash(message);
135 | } catch (EOSFormatterError eosFormatterError) {
136 | throw new SignTransactionError(String.format(SoftKeySignatureErrorConstants.SIGN_TRANS_PREPARE_SIGNABLE_TRANS_ERROR, serializedTransaction), eosFormatterError);
137 | }
138 |
139 | if (this.keys.isEmpty()) {
140 | throw new SignTransactionError(SoftKeySignatureErrorConstants.SIGN_TRANS_NO_KEY_AVAILABLE);
141 | }
142 |
143 | List signatures = new ArrayList<>();
144 |
145 | // Getting public key and search for the corresponding private key
146 | for (String inputPublicKey : eosioTransactionSignatureRequest.getSigningPublicKeys()) {
147 |
148 | BigInteger privateKeyBI = BigInteger.ZERO;
149 | AlgorithmEmployed curve = null;
150 |
151 | try {
152 | // Search for corresponding private key
153 | for (String key : keys) {
154 | PEMProcessor availableKeyProcessor = new PEMProcessor(key);
155 | //Extract public key in PEM format from inner private key
156 | String innerPublicKeyPEM = availableKeyProcessor.extractPEMPublicKeyFromPrivateKey(DEFAULT_WHETHER_USING_K1_LEGACY_FORMAT);
157 |
158 | // Convert input public key to PEM format for comparision
159 | String inputPublicKeyPEM = EOSFormatter.convertEOSPublicKeyToPEMFormat(inputPublicKey);
160 |
161 | if (innerPublicKeyPEM.equals(inputPublicKeyPEM)) {
162 | privateKeyBI = new BigInteger(BIG_INTEGER_POSITIVE, availableKeyProcessor.getKeyData());
163 | curve = availableKeyProcessor.getAlgorithm();
164 | break;
165 | }
166 | }
167 | } catch (EosioError error) {
168 | throw new SignTransactionError(String.format(SoftKeySignatureErrorConstants.SIGN_TRANS_SEARCH_KEY_ERROR, inputPublicKey), error);
169 | }
170 |
171 | // Throw error if found no private key with input public key
172 | //noinspection ConstantConditions
173 | if (privateKeyBI.equals(BigInteger.ZERO) || curve == null) {
174 | throw new SignTransactionError(String.format(SoftKeySignatureErrorConstants.SIGN_TRANS_KEY_NOT_FOUND, inputPublicKey));
175 | }
176 |
177 | for (int i = 0; i < MAX_NOT_CANONICAL_RE_SIGN; i++) {
178 | // Sign transaction
179 | // Use default constructor to have signature generated with secureRandom, otherwise it would generate same signature for same key all the time
180 | ECDSASigner signer = new ECDSASigner();
181 |
182 | ECDomainParameters domainParameters;
183 | try {
184 | domainParameters = PEMProcessor.getCurveDomainParameters(curve);
185 | } catch (PEMProcessorError processorError) {
186 | throw new SignTransactionError(String.format(SoftKeySignatureErrorConstants.SIGN_TRANS_GET_CURVE_DOMAIN_ERROR, curve.getString()), processorError);
187 | }
188 |
189 | ECPrivateKeyParameters parameters = new ECPrivateKeyParameters(privateKeyBI, domainParameters);
190 | signer.init(true, parameters);
191 | BigInteger[] signatureComponents = signer.generateSignature(hashedMessage);
192 |
193 | try {
194 | String signature = EOSFormatter.convertRawRandSofSignatureToEOSFormat(signatureComponents[R_INDEX].toString(), signatureComponents[S_INDEX].toString(), message, EOSFormatter.convertEOSPublicKeyToPEMFormat(inputPublicKey));
195 | // Format Signature
196 | signatures.add(signature);
197 | break;
198 | } catch (EOSFormatterError eosFormatterError) {
199 | // In theory, Non-canonical error only happened with K1 key
200 | if (eosFormatterError.getCause() instanceof EosFormatterSignatureIsNotCanonicalError && curve == AlgorithmEmployed.SECP256K1) {
201 | // Try to sign again until MAX_NOT_CANONICAL_RE_SIGN is reached or get a canonical signature
202 | continue;
203 | }
204 |
205 | throw new SignTransactionError(SoftKeySignatureErrorConstants.SIGN_TRANS_FORMAT_SIGNATURE_ERROR, eosFormatterError);
206 | }
207 | }
208 | }
209 |
210 | return new EosioTransactionSignatureResponse(serializedTransaction, signatures, null);
211 | }
212 |
213 | /**
214 | * Gets available keys from signature provider Check createSignatureRequest() flow in
215 | * "complete workflow" for more detail of how the method is used.
216 | *
217 | * Public key of SECP256K1 has 2 types of format in EOSIO which are "EOS" and "PUB_K1_" so this method return 2 public keys in both format for SECP256K1 and 1 public key for SECP256R1.
218 | *
219 | * @return the available keys of signature provider in EOS format
220 | * @throws GetAvailableKeysError thrown if there are any exceptions during the get available keys process.
221 | */
222 | @Override
223 | public @NotNull List getAvailableKeys() throws GetAvailableKeysError {
224 | List availableKeys = new ArrayList<>();
225 | if (this.keys.isEmpty()) {
226 | return availableKeys;
227 | }
228 |
229 | try {
230 | for (String key : this.keys) {
231 | PEMProcessor processor = new PEMProcessor(key);
232 | AlgorithmEmployed curve = processor.getAlgorithm();
233 |
234 | switch (curve) {
235 | case SECP256R1:
236 | // USING_K1_NON_LEGACY_FORMAT is being used here because its value does not matter to SECP256R1 key
237 | availableKeys.add(processor.extractEOSPublicKeyFromPrivateKey(USING_K1_NON_LEGACY_FORMAT));
238 | break;
239 |
240 | case SECP256K1:
241 | // Non legacy
242 | availableKeys.add(processor.extractEOSPublicKeyFromPrivateKey(USING_K1_NON_LEGACY_FORMAT));
243 | // legacy
244 | availableKeys.add(processor.extractEOSPublicKeyFromPrivateKey(USING_K1_LEGACY_FORMAT));
245 | break;
246 |
247 | default:
248 | throw new GetAvailableKeysError(SoftKeySignatureErrorConstants.GET_KEYS_KEY_FORMAT_NOT_SUPPORTED);
249 | }
250 | }
251 | } catch (PEMProcessorError pemProcessorError) {
252 | throw new GetAvailableKeysError(SoftKeySignatureErrorConstants.CONVERT_TO_PEM_EMPTY_ERROR, pemProcessorError);
253 | }
254 |
255 | return availableKeys;
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |