From bf0a4646ea4b85c0566de233c0dc761049897e52 Mon Sep 17 00:00:00 2001 From: Roman Strobl Date: Thu, 23 Jun 2022 18:26:08 +0200 Subject: [PATCH 01/17] Fix #249: Update version --- pom.xml | 4 ++-- powerauth-java-cmd-lib/pom.xml | 4 ++-- powerauth-java-cmd/pom.xml | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index f74b6a01..a4f90539 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ io.getlime.security powerauth-cmd-parent - 1.3.0 + 1.4.0-SNAPSHOT pom 2016 @@ -84,7 +84,7 @@ 1.5.0 2.11.0 1.1.1 - 1.3.0 + 1.4.0-SNAPSHOT 1.5.0 1.18.24 5.8.2 diff --git a/powerauth-java-cmd-lib/pom.xml b/powerauth-java-cmd-lib/pom.xml index af00f3e7..a5b8f7d2 100644 --- a/powerauth-java-cmd-lib/pom.xml +++ b/powerauth-java-cmd-lib/pom.xml @@ -6,12 +6,12 @@ 4.0.0 powerauth-java-cmd-lib PowerAuth Command-line Utility - Java Library - 1.3.0 + 1.4.0-SNAPSHOT powerauth-cmd-parent io.getlime.security - 1.3.0 + 1.4.0-SNAPSHOT ../pom.xml diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index a4f99d1e..4d39d0d2 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -22,7 +22,7 @@ 4.0.0 powerauth-java-cmd - 1.3.0 + 1.4.0-SNAPSHOT powerauth-java-cmd PowerAuth Reference Client Application connected to PowerAuth Standard RESTful API @@ -31,7 +31,7 @@ io.getlime.security powerauth-cmd-parent - 1.3.0 + 1.4.0-SNAPSHOT ../pom.xml @@ -39,7 +39,7 @@ io.getlime.security powerauth-java-cmd-lib - 1.3.0 + 1.4.0-SNAPSHOT log4j-to-slf4j From cc33a84655eb792213dfe4b48602136937a0db32 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 23 Sep 2022 04:43:01 +0000 Subject: [PATCH 02/17] fix: pom.xml to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JAVA-ORGYAML-2806360 - https://snyk.io/vuln/SNYK-JAVA-ORGYAML-3016888 - https://snyk.io/vuln/SNYK-JAVA-ORGYAML-3016889 - https://snyk.io/vuln/SNYK-JAVA-ORGYAML-3016891 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a4f90539..ef36fe5c 100644 --- a/pom.xml +++ b/pom.xml @@ -78,7 +78,7 @@ 3.2.1 3.0.0-M2 3.4.0 - 2.6.8 + 2.6.12 1.70 2.13.3 1.5.0 From f12e61a14a917c21a7dda505af9dcd6977fecabd Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Mon, 3 Oct 2022 05:12:42 +0000 Subject: [PATCH 03/17] fix: pom.xml to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JAVA-COMFASTERXMLJACKSONCORE-3038424 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ef36fe5c..1af086d5 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 3.4.0 2.6.12 1.70 - 2.13.3 + 2.13.4 1.5.0 2.11.0 1.1.1 From 6049c73f608baf0fc4f8f139a1e358c1e01094a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20=C4=8Cern=C3=BD?= Date: Tue, 18 Oct 2022 11:13:27 +0200 Subject: [PATCH 04/17] new reusable workflows part of wultra/tasklist#23 (#253) * Add basic reusable flows as part of wultra/tasklist#23 --- .github/workflows/maven-deploy.yml | 50 +++++++++++++++++++++ .github/workflows/maven-test.yml | 19 ++++++++ pom.xml | 71 +++++++++++++++++++++++++----- powerauth-java-cmd/pom.xml | 31 ++++++++++--- 4 files changed, 153 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/maven-deploy.yml create mode 100644 .github/workflows/maven-test.yml diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy.yml new file mode 100644 index 00000000..2d385630 --- /dev/null +++ b/.github/workflows/maven-deploy.yml @@ -0,0 +1,50 @@ +name: Deploy with Maven + +on: + workflow_dispatch: + branches: + - 'develop' + - 'master' + - 'releases/**' + - 'test/ci' + inputs: + release_type: + type: choice + description: releasing to snapshot or release + default: snapshot + options: + - snapshot + - release + environment: + type: environment + default: internal-publish + description: internal or external repository + push: + branches: + - 'develop' + - 'test/ci' + + + +jobs: + maven-deploy-internal: + if: ${{ github.event_name == 'push' }} + name: Deploy to ${{ inputs.environment }} + uses: wultra/wultra-infrastructure/.github/workflows/maven-deploy.yml@develop + with: + environment: internal-publish + release_type: snapshot + secrets: + username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + + maven-deploy-public: + if: ${{ github.event_name == 'workflow_dispatch' }} + name: Deploy to ${{ inputs.environment }} + uses: wultra/wultra-infrastructure/.github/workflows/maven-deploy.yml@develop + with: + environment: ${{ inputs.environment }} + release_type: ${{ inputs.release_type }} + secrets: + username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} diff --git a/.github/workflows/maven-test.yml b/.github/workflows/maven-test.yml new file mode 100644 index 00000000..5f4e4c13 --- /dev/null +++ b/.github/workflows/maven-test.yml @@ -0,0 +1,19 @@ +name: Test with Maven + +on: + workflow_dispatch: + push: + branches: + - 'develop' + - 'master' + - 'releases/**' + - 'test/ci' + pull_request: + branches: + - 'develop' + - 'master' + - 'releases/**' + +jobs: + maven-tests: + uses: wultra/wultra-infrastructure/.github/workflows/maven-test.yml@develop \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1af086d5..398b6108 100644 --- a/pom.xml +++ b/pom.xml @@ -157,6 +157,66 @@ + + internal-repository + + + useInternalRepo + true + + + + + + + jfrog-central + Wultra Artifactory-releases + https://wultra.jfrog.io/artifactory/internal-maven-repository + + + jfrog-central + Wultra Artifactory-snapshots + https://wultra.jfrog.io/artifactory/internal-maven-repository + + + + + jfrog-central + Wultra Artifactory-releases + https://wultra.jfrog.io/artifactory/internal-maven-repository + + + ossrh-snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + false + + + true + + + + + + public-repository + + + !useInternalRepo + + + + + + + ossrh-snapshots-distribution + https://oss.sonatype.org/content/repositories/snapshots/ + + + ossrh-staging-distribution + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + @@ -172,15 +232,4 @@ - - - ossrh-snapshots-distribution - https://oss.sonatype.org/content/repositories/snapshots/ - - - ossrh-staging-distribution - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index 4d39d0d2..30340306 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -78,13 +78,6 @@ io.getlime.security.powerauth.app.cmd.Application - - org.apache.maven.plugins - maven-deploy-plugin - - true - - maven-surefire-plugin ${maven-surefire-plugin.version} @@ -92,4 +85,28 @@ + + + public-repository + + + !useInternalRepo + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + + From 2969d6fdc4c56b7823fe67fa40c07600a37d1591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20=C5=A0trobl?= Date: Thu, 3 Nov 2022 13:16:41 +0100 Subject: [PATCH 05/17] Fix #165: Offline signatures (#256) --- docs/Readme.md | 17 ++ .../lib/cmd/consts/PowerAuthStep.java | 5 + .../steps/ComputeOfflineSignatureStep.java | 233 ++++++++++++++++++ .../lib/cmd/steps/VerifyTokenStep.java | 4 +- .../ComputeOfflineSignatureStepModel.java | 72 ++++++ .../powerauth/app/cmd/Application.java | 20 ++ 6 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/ComputeOfflineSignatureStep.java create mode 100644 powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/model/ComputeOfflineSignatureStepModel.java diff --git a/docs/Readme.md b/docs/Readme.md index 916b37f6..8e0914a8 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -361,6 +361,23 @@ java -jar powerauth-java-cmd.jar \ The commit upgrade request is sent to the server including a version `3.0` signature. The server verifies the request signature and commits the upgrade of activation to version `3`. +## Compute Offline Signature + +Use this method to compute offline PowerAuth signature. + +```bash +java -jar powerauth-java-cmd.jar \ + --status-file "/tmp/pa_status.json" \ + --config-file "/tmp/pamk.json" \ + --method "compute-offline-signature" \ + --qr-code-data "c68dc57f-ee5f-497c-8c92-338439426e76\nApprove Login\nPlease confirm the login request.\nA2\nB\nETIK4iFz1E9u6vABKSbytg==\n1MEYCIQCnQqFFzS589auwdMRZ9Aq5qFxso21oxd2sng9Vp7gCUgIhAITaJ9L3fP2tov63mcIgU2e/37h9EXyAMhzrCXXDNJZE" \ + --password "1234" +``` + +The `qr-code-data` parameter is taken from QR code generated by PowerAuth RESTful services. Note that the QR code is signed, the signature is verified during offline signature computation. The method unlocks the knowledge related signing key using `1234` as a password. + +The method does not execute any server calls due to its offline nature. The computed offline signature is used as an OTP and it is available from the output of the command in decimal format, e.g.: `"offlineSignature" : "99961544-80193814"`. + ## Basic Usage PowerAuth Reference Client is called as any Java application that is packaged as a JAR file and it uses following command-line arguments. diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/consts/PowerAuthStep.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/consts/PowerAuthStep.java index 65d6ef6b..45833dce 100644 --- a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/consts/PowerAuthStep.java +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/consts/PowerAuthStep.java @@ -73,6 +73,11 @@ public enum PowerAuthStep { */ SIGN_ENCRYPT("sign-encrypt", "Sign and Encrypt Request", "sign-encrypt"), + /** + * Compute an offline signature + */ + SIGNATURE_OFFLINE_COMPUTE("signature-offline-compute", "Compute Offline Signature", "compute-offline-signature"), + /** * Verifying a signed request */ diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/ComputeOfflineSignatureStep.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/ComputeOfflineSignatureStep.java new file mode 100644 index 00000000..b8a29b80 --- /dev/null +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/ComputeOfflineSignatureStep.java @@ -0,0 +1,233 @@ +/* + * PowerAuth Command-line utility + * Copyright 2022 Wultra s.r.o. + * + * 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 io.getlime.security.powerauth.lib.cmd.steps; + +import com.google.common.io.BaseEncoding; +import io.getlime.security.powerauth.crypto.lib.enums.PowerAuthSignatureFormat; +import io.getlime.security.powerauth.crypto.lib.generator.KeyGenerator; +import io.getlime.security.powerauth.crypto.lib.util.KeyConvertor; +import io.getlime.security.powerauth.crypto.lib.util.SignatureUtils; +import io.getlime.security.powerauth.http.PowerAuthHttpBody; +import io.getlime.security.powerauth.lib.cmd.consts.BackwardCompatibilityConst; +import io.getlime.security.powerauth.lib.cmd.consts.PowerAuthStep; +import io.getlime.security.powerauth.lib.cmd.consts.PowerAuthVersion; +import io.getlime.security.powerauth.lib.cmd.logging.StepLogger; +import io.getlime.security.powerauth.lib.cmd.logging.StepLoggerFactory; +import io.getlime.security.powerauth.lib.cmd.status.ResultStatusService; +import io.getlime.security.powerauth.lib.cmd.steps.context.RequestContext; +import io.getlime.security.powerauth.lib.cmd.steps.context.StepContext; +import io.getlime.security.powerauth.lib.cmd.steps.model.ComputeOfflineSignatureStepModel; +import io.getlime.security.powerauth.lib.cmd.steps.pojo.ResultStatusObject; +import io.getlime.security.powerauth.lib.cmd.util.CounterUtil; +import io.getlime.security.powerauth.lib.cmd.util.EncryptedStorageUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import java.io.Console; +import java.nio.charset.StandardCharsets; +import java.security.interfaces.ECPublicKey; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Step for computing offline PowerAuth signature. + * + *

PowerAuth protocol versions: + *

    + *
  • 2.0
  • + *
  • 2.1
  • + *
  • 3.0
  • + *
  • 3.1
  • + *
+ * + * @author Roman Strobl, roman.strobl@wultra.com + */ +@Component +public class ComputeOfflineSignatureStep extends AbstractBaseStep { + + private static final KeyGenerator KEY_GENERATOR = new KeyGenerator(); + private static final KeyConvertor KEY_CONVERTOR = new KeyConvertor(); + private static final SignatureUtils SIGNATURE_UTILS = new SignatureUtils(); + + /** + * Constructor + * @param resultStatusService Result status service + * @param stepLoggerFactory Step logger factory + */ + @Autowired + public ComputeOfflineSignatureStep( + ResultStatusService resultStatusService, + StepLoggerFactory stepLoggerFactory) { + super(PowerAuthStep.SIGNATURE_OFFLINE_COMPUTE, PowerAuthVersion.ALL_VERSIONS, resultStatusService, stepLoggerFactory); + } + + /** + * Constructor for backward compatibility + */ + public ComputeOfflineSignatureStep() { + this( + BackwardCompatibilityConst.RESULT_STATUS_SERVICE, + BackwardCompatibilityConst.STEP_LOGGER_FACTORY + ); + } + + @Override + public ParameterizedTypeReference getResponseTypeReference() { + // No response type, server is not called due to offline nature of the step + return null; + } + + @Override + public StepContext prepareStepContext(StepLogger stepLogger, Map context) throws Exception { + final ComputeOfflineSignatureStepModel model = new ComputeOfflineSignatureStepModel(); + model.fromMap(context); + + final RequestContext requestContext = RequestContext.builder() + .uri(model.getUriString()) + .build(); + + final StepContext stepContext = + buildStepContext(stepLogger, model, requestContext); + + if (model.getQrCodeData() == null) { + stepLogger.writeError(getStep().id() + "-error-missing-qr-code-data", "Missing offline signature data", "Specify offline signature data which is encoded in QR code"); + stepLogger.writeDoneFailed(getStep().id() + "-failed"); + return null; + } + + final String offlineData = unescape(model.getQrCodeData()); + final Map inputMap = new HashMap<>(); + inputMap.put("qrCodeData", offlineData); + + stepLogger.writeItem( + getStep().id() + "-start", + "Offline Signature Computation Started", + null, + "OK", + inputMap + ); + + // Ask for the password to unlock knowledge factor key + final char[] password; + if (model.getPassword() == null) { + Console console = System.console(); + password = console.readPassword("Enter your password to unlock the knowledge related key: "); + } else { + password = model.getPassword().toCharArray(); + } + + final String offlineSignature = calculateOfflineSignature(offlineData, stepLogger, model.getResultStatus(), password); + if (offlineSignature == null) { + return null; + } + + final Map resultMap = new HashMap<>(); + resultMap.put("offlineSignature", offlineSignature); + + stepLogger.writeItem( + getStep().id() + "-finished", + "Offline Signature Computation Finished", + null, + "OK", + resultMap + ); + + incrementCounter(stepContext.getModel()); + + return stepContext; + } + + private String unescape(String text) { + return text.replace("\\n", "\n"); + } + + private String calculateOfflineSignature(final String offlineData, final StepLogger stepLogger, + final ResultStatusObject resultStatusObject, final char[] password) { + // Split the offline data into individual lines, see: https://github.com/wultra/powerauth-webflow/blob/develop/docs/Off-line-Signatures-QR-Code.md + final String[] parts = offlineData.split("\n"); + if (parts.length < 7) { + stepLogger.writeError(getStep().id() + "-error-invalid-qr-code-data", "Invalid QR code data", "Invalid QR code, expected 7 lines of data or more"); + stepLogger.writeDoneFailed(getStep().id() + "-failed"); + return null; + } + final String operationId = parts[0]; + final String operationData = parts[3]; + final String nonce = parts[5]; + final String signatureLine = parts[parts.length - 1]; + + // 1 = KEY_SERVER_PRIVATE was used to sign data (personalized offline signature), otherwise return error + final String signatureType = signatureLine.substring(0, 1); + if (!"1".equals(signatureType)) { + stepLogger.writeError(getStep().id() + "-error-invalid-signature-type", "Invalid signature type", "Personalized offline signature expected, however other signature type is used"); + stepLogger.writeDoneFailed(getStep().id() + "-failed"); + return null; + } + + try { + // Verify ECDSA signature from the offline data, return error in case of invalid signature + final String ecdsaSignature = signatureLine.substring(1); + final byte[] serverPublicKeyBytes = BaseEncoding.base64().decode(resultStatusObject.getServerPublicKey()); + final ECPublicKey serverPublicKey = (ECPublicKey) KEY_CONVERTOR.convertBytesToPublicKey(serverPublicKeyBytes); + final String offlineDataWithoutSignature = offlineData.substring(0, offlineData.length() - ecdsaSignature.length()); + final boolean dataSignatureValid = SIGNATURE_UTILS.validateECDSASignature( + offlineDataWithoutSignature.getBytes(StandardCharsets.UTF_8), + BaseEncoding.base64().decode(ecdsaSignature), + serverPublicKey); + if (!dataSignatureValid) { + stepLogger.writeError(getStep().id() + "-error-invalid-signature", "Invalid signature", "Invalid signature of offline data"); + stepLogger.writeDoneFailed(getStep().id() + "-failed"); + return null; + } + + // Prepare data for PowerAuth offline signature calculation + final String dataForSignature = operationId + "&" + operationData; + final String signatureBaseString = PowerAuthHttpBody.getSignatureBaseString( + "POST", + "/operation/authorize/offline", + BaseEncoding.base64().decode(nonce), + dataForSignature.getBytes(StandardCharsets.UTF_8)); + + // Prepare keys for PowerAuth offline signature calculation + final byte[] signaturePossessionKeyBytes = BaseEncoding.base64().decode(resultStatusObject.getSignaturePossessionKey()); + final byte[] signatureKnowledgeKeySalt = BaseEncoding.base64().decode(resultStatusObject.getSignatureKnowledgeKeySalt()); + final byte[] signatureKnowledgeKeyEncryptedBytes = BaseEncoding.base64().decode(resultStatusObject.getSignatureKnowledgeKeyEncrypted()); + final SecretKey signaturePossessionKey = KEY_CONVERTOR.convertBytesToSharedSecretKey(signaturePossessionKeyBytes); + final SecretKey signatureKnowledgeKey = EncryptedStorageUtil.getSignatureKnowledgeKey( + password, + signatureKnowledgeKeyEncryptedBytes, + signatureKnowledgeKeySalt, + KEY_GENERATOR); + final List signatureKeys = new ArrayList<>(); + signatureKeys.add(signaturePossessionKey); + signatureKeys.add(signatureKnowledgeKey); + + // Calculate signature of normalized signature base string with 'offline' constant used as application secret + return SIGNATURE_UTILS.computePowerAuthSignature((signatureBaseString + "&offline").getBytes(StandardCharsets.UTF_8), + signatureKeys, + CounterUtil.getCtrData(resultStatusObject, stepLogger), + PowerAuthSignatureFormat.DECIMAL); + } catch (Exception ex) { + stepLogger.writeError(getStep().id() + "-error-cryptography", "Cryptography error", ex.getMessage()); + stepLogger.writeDoneFailed(getStep().id() + "-failed"); + return null; + } + } +} diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/VerifyTokenStep.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/VerifyTokenStep.java index d6e2463a..126eb792 100644 --- a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/VerifyTokenStep.java +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/VerifyTokenStep.java @@ -102,8 +102,8 @@ public StepContext> prepareStepContext buildStepContext(stepLogger, model, requestContext); Map map = new HashMap<>(); - map.put("TOKEN_ID", model.getTokenId()); - map.put("TOKEN_SECRET", model.getTokenSecret()); + map.put("tokenId", model.getTokenId()); + map.put("tokenSecret", model.getTokenSecret()); stepLogger.writeItem( "token-validate-start", "Token Digest Validation Started", diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/model/ComputeOfflineSignatureStepModel.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/model/ComputeOfflineSignatureStepModel.java new file mode 100644 index 00000000..506eec69 --- /dev/null +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/model/ComputeOfflineSignatureStepModel.java @@ -0,0 +1,72 @@ +/* + * PowerAuth Command-line utility + * Copyright 2022 Wultra s.r.o. + * + * 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 io.getlime.security.powerauth.lib.cmd.steps.model; + +import io.getlime.security.powerauth.lib.cmd.steps.model.feature.DryRunCapable; +import io.getlime.security.powerauth.lib.cmd.steps.model.feature.ResultStatusChangeable; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Map; + +/** + * Model representing parameters of the step for computing offline signatures. + * + * @author Roman Strobl, roman.strobl@wultra.com + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ComputeOfflineSignatureStepModel extends BaseStepModel implements ResultStatusChangeable, DryRunCapable { + + /** + * File name of the file with stored activation status. + */ + private String statusFileName; + + /** + * QR code data. + */ + private String qrCodeData; + + /** + * Knowledge key password (PIN). + */ + private String password; + + @Override + public Map toMap() { + Map context = super.toMap(); + context.put("STATUS_FILENAME", statusFileName); + context.put("QR_CODE_DATA", qrCodeData); + context.put("PASSWORD", password); + return context; + } + + @Override + public void fromMap(Map context) { + super.fromMap(context); + setStatusFileName((String) context.get("STATUS_FILENAME")); + setQrCodeData((String) context.get("QR_CODE_DATA")); + setPassword((String) context.get("PASSWORD")); + } + + @Override + public boolean isDryRun() { + return true; + } + +} diff --git a/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java b/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java index db5af222..d1674f5f 100755 --- a/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java +++ b/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java @@ -104,6 +104,7 @@ public static void main(String[] args) { options.addOption("R", "recovery-code", true, "Recovery code to be confirmed."); options.addOption("P", "platform", true, "User device platform."); options.addOption("D", "device-info", true, "Information about user device."); + options.addOption("q", "qr-code-data", true, "Data for offline signature encoded in QR code."); options.addOption("v", "version", true, "PowerAuth protocol version."); Option httpHeaderOption = Option.builder("H") @@ -173,6 +174,11 @@ public static void main(String[] args) { deviceInfo = "cmd-tool"; } + String qrCodeData = null; + if (cmd.hasOption("q")) { + qrCodeData = cmd.getOptionValue("q"); + } + // Read values String method = cmd.getOptionValue("m"); String uriString = cmd.getOptionValue("u"); @@ -520,6 +526,20 @@ public static void main(String[] args) { model.setVersion(version); stepExecutionService.execute(powerAuthStep, version, model); + break; + } + + case SIGNATURE_OFFLINE_COMPUTE: { + + ComputeOfflineSignatureStepModel model = new ComputeOfflineSignatureStepModel(); + model.setStatusFileName(statusFileName); + model.setQrCodeData(qrCodeData); + model.setPassword(cmd.getOptionValue("p")); + model.setResultStatus(resultStatusObject); + model.setVersion(version); + + stepExecutionService.execute(powerAuthStep, version, model); + break; } default: From f36e9cb7012874d0a332788ce6693da83c2e8831 Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Fri, 9 Dec 2022 16:31:37 +0100 Subject: [PATCH 06/17] Fix #257: Clean up maven configuration --- pom.xml | 10 ++++++++++ powerauth-java-cmd-lib/pom.xml | 2 -- powerauth-java-cmd/pom.xml | 3 --- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 398b6108..f648ea7f 100644 --- a/pom.xml +++ b/pom.xml @@ -91,6 +91,16 @@ 2.22.2 + + + + io.getlime.security + powerauth-java-cmd-lib + ${project.version} + + + + diff --git a/powerauth-java-cmd-lib/pom.xml b/powerauth-java-cmd-lib/pom.xml index a5b8f7d2..49b19325 100644 --- a/powerauth-java-cmd-lib/pom.xml +++ b/powerauth-java-cmd-lib/pom.xml @@ -6,13 +6,11 @@ 4.0.0 powerauth-java-cmd-lib PowerAuth Command-line Utility - Java Library - 1.4.0-SNAPSHOT powerauth-cmd-parent io.getlime.security 1.4.0-SNAPSHOT - ../pom.xml diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index 30340306..36e464b7 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -22,7 +22,6 @@ 4.0.0 powerauth-java-cmd - 1.4.0-SNAPSHOT powerauth-java-cmd PowerAuth Reference Client Application connected to PowerAuth Standard RESTful API @@ -32,14 +31,12 @@ io.getlime.security powerauth-cmd-parent 1.4.0-SNAPSHOT - ../pom.xml io.getlime.security powerauth-java-cmd-lib - 1.4.0-SNAPSHOT log4j-to-slf4j From 3226d7fb729d95337868b3a59156e403f21eb5a6 Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Fri, 9 Dec 2022 16:38:02 +0100 Subject: [PATCH 07/17] Fix #259: Update to Spring Boot 2.6.14 --- pom.xml | 13 +++++++++---- powerauth-java-cmd-lib/pom.xml | 4 ---- powerauth-java-cmd/pom.xml | 1 - 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index f648ea7f..f93266a5 100644 --- a/pom.xml +++ b/pom.xml @@ -78,21 +78,26 @@ 3.2.1 3.0.0-M2 3.4.0 - 2.6.12 + 2.6.14 1.70 - 2.13.4 1.5.0 2.11.0 1.1.1 1.4.0-SNAPSHOT 1.5.0 - 1.18.24 - 5.8.2 2.22.2 + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + io.getlime.security powerauth-java-cmd-lib diff --git a/powerauth-java-cmd-lib/pom.xml b/powerauth-java-cmd-lib/pom.xml index 49b19325..eeb49690 100644 --- a/powerauth-java-cmd-lib/pom.xml +++ b/powerauth-java-cmd-lib/pom.xml @@ -17,7 +17,6 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} commons-cli @@ -66,7 +65,6 @@ org.springframework.boot spring-boot-starter - ${spring-boot.version} log4j-to-slf4j @@ -77,7 +75,6 @@ org.springframework.boot spring-boot-configuration-processor - ${spring-boot.version} true @@ -89,7 +86,6 @@ org.projectlombok lombok - ${lombok.version} diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index 36e464b7..a06b8819 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -47,7 +47,6 @@ org.junit.jupiter junit-jupiter-engine - ${junit.version} test From 17ce3eb6ef001ce1085f6be9a40a9ae79d4763e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20=C4=8Cern=C3=BD?= Date: Tue, 13 Dec 2022 10:01:24 +0100 Subject: [PATCH 08/17] Issues/coverity scan (#263) * scheduled and manual workflow for Coverity scan --- .github/workflows/coverity-scan.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/coverity-scan.yml diff --git a/.github/workflows/coverity-scan.yml b/.github/workflows/coverity-scan.yml new file mode 100644 index 00000000..8a887f33 --- /dev/null +++ b/.github/workflows/coverity-scan.yml @@ -0,0 +1,16 @@ +name: Run Coverity scan and upload results + +on: + workflow_dispatch: + schedule: + - cron: '0 10 1 * *' # monthly + + +jobs: + coverity-scan: + uses: wultra/wultra-infrastructure/.github/workflows/coverity-scan.yml@develop + secrets: inherit + with: + project-name: ${{ github.event.repository.name }} + version: ${{ github.sha }} + description: ${{ github.ref }} From f590137ab00eefe90f8ead92332c589514662199 Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Thu, 15 Dec 2022 15:00:18 +0100 Subject: [PATCH 09/17] Fix #264: Coverity - Missing break in switch --- .../java/io/getlime/security/powerauth/app/cmd/Application.java | 1 + 1 file changed, 1 insertion(+) diff --git a/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java b/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java index d1674f5f..0b9ddc84 100755 --- a/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java +++ b/powerauth-java-cmd/src/main/java/io/getlime/security/powerauth/app/cmd/Application.java @@ -454,6 +454,7 @@ public static void main(String[] args) { model.setData(dataFileBytes); stepExecutionService.execute(powerAuthStep, version, model); + break; } case UPGRADE_START: { StartUpgradeStepModel model = new StartUpgradeStepModel(); From c7d80d69fbd1c199ae34f186f5781e8c39ec6673 Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Thu, 15 Dec 2022 15:23:56 +0100 Subject: [PATCH 10/17] Fix #266: Coverity - Dereference null return value at Steps --- .../powerauth/lib/cmd/steps/AbstractBaseStep.java | 4 ++++ .../lib/cmd/steps/v2/PrepareActivationStep.java | 10 ++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java index a4c46f02..c4e3adbd 100644 --- a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java @@ -295,6 +295,10 @@ protected void logDryRun(StepLogger stepLogger) { * Calls the server and prepares response context with the response data */ private @Nullable ResponseContext callServer(StepContext stepContext) throws Exception { + if (stepContext == null) { + return null; + } + M model = stepContext.getModel(); RequestContext requestContext = stepContext.getRequestContext(); diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/v2/PrepareActivationStep.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/v2/PrepareActivationStep.java index 47d57810..2839a82d 100755 --- a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/v2/PrepareActivationStep.java +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/v2/PrepareActivationStep.java @@ -78,7 +78,7 @@ public class PrepareActivationStep extends AbstractBaseStepV2 { */ @Autowired public PrepareActivationStep(StepLogger stepLogger) { - super(PowerAuthStep.ACTIVATION_CREATE, PowerAuthVersion.VERSION_2, stepLogger); + super(PowerAuthStep.ACTIVATION_CREATE, PowerAuthVersion.VERSION_2, Objects.requireNonNull(stepLogger, "stepLogger must not be null")); } /** @@ -110,11 +110,9 @@ public ResultStatusObject execute(Map context) throws Exception Pattern p = Pattern.compile("^[A-Z2-7]{5}-[A-Z2-7]{5}-[A-Z2-7]{5}-[A-Z2-7]{5}(#.*)?$"); Matcher m = p.matcher(model.getActivationCode()); if (!m.find()) { - if (stepLogger != null) { - stepLogger.writeError("activation-create-error-activation-code", "Activation failed", "Activation code has invalid format"); - stepLogger.writeDoneFailed("activation-create-failed"); - return null; - } + stepLogger.writeError("activation-create-error-activation-code", "Activation failed", "Activation code has invalid format"); + stepLogger.writeDoneFailed("activation-create-failed"); + return null; } String activationIdShort = model.getActivationCode().substring(0, 11); String activationOTP = model.getActivationCode().substring(12, 23); From 1636efbc39f7b99b394c27942b70a49783fd90be Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Tue, 20 Dec 2022 15:13:51 +0100 Subject: [PATCH 11/17] Fix #268: Set release version to 1.4.0 --- pom.xml | 2 +- powerauth-java-cmd-lib/pom.xml | 2 +- powerauth-java-cmd/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f93266a5..5701d1ef 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ io.getlime.security powerauth-cmd-parent - 1.4.0-SNAPSHOT + 1.4.0 pom 2016 diff --git a/powerauth-java-cmd-lib/pom.xml b/powerauth-java-cmd-lib/pom.xml index eeb49690..8672cb40 100644 --- a/powerauth-java-cmd-lib/pom.xml +++ b/powerauth-java-cmd-lib/pom.xml @@ -10,7 +10,7 @@ powerauth-cmd-parent io.getlime.security - 1.4.0-SNAPSHOT + 1.4.0 diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index a06b8819..ed003497 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -30,7 +30,7 @@ io.getlime.security powerauth-cmd-parent - 1.4.0-SNAPSHOT + 1.4.0 From 41a2b29851b9137fc031ef4403915133bce45829 Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Tue, 20 Dec 2022 15:21:13 +0100 Subject: [PATCH 12/17] Fix #270: Update Wultra dependencies --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f93266a5..ad09ef9d 100644 --- a/pom.xml +++ b/pom.xml @@ -83,8 +83,8 @@ 1.5.0 2.11.0 1.1.1 - 1.4.0-SNAPSHOT - 1.5.0 + 1.4.0 + 1.6.0 2.22.2 From 70e1a159cd32826b79a0fdbdfa0b1aa59060e12b Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Tue, 20 Dec 2022 15:33:23 +0100 Subject: [PATCH 13/17] Fix #271: Update dependencies --- pom.xml | 12 +++++++++--- powerauth-java-cmd-lib/pom.xml | 3 +-- powerauth-java-cmd/pom.xml | 3 +-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index f93266a5..d47b80c8 100644 --- a/pom.xml +++ b/pom.xml @@ -76,10 +76,10 @@ 1.8 1.8 3.2.1 - 3.0.0-M2 - 3.4.0 + 3.0.0 + 3.4.1 2.6.14 - 1.70 + 1.72 1.5.0 2.11.0 1.1.1 @@ -103,6 +103,12 @@ powerauth-java-cmd-lib ${project.version} + + + org.bouncycastle + bcprov-jdk18on + ${bc.version} + diff --git a/powerauth-java-cmd-lib/pom.xml b/powerauth-java-cmd-lib/pom.xml index eeb49690..1f551978 100644 --- a/powerauth-java-cmd-lib/pom.xml +++ b/powerauth-java-cmd-lib/pom.xml @@ -57,8 +57,7 @@ org.bouncycastle - bcprov-jdk15on - ${bc.version} + bcprov-jdk18on provided diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index a06b8819..3a12370a 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -51,8 +51,7 @@
org.bouncycastle - bcprov-jdk15on - ${bc.version} + bcprov-jdk18on From dc45eca84272742a62dc4915343b4561ebda23ff Mon Sep 17 00:00:00 2001 From: Lubos Racansky Date: Wed, 21 Dec 2022 08:05:57 +0100 Subject: [PATCH 14/17] Fix #276: Coverity - Dereference null return value --- .../powerauth/lib/cmd/steps/AbstractBaseStep.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java index c4e3adbd..776bd54c 100644 --- a/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java +++ b/powerauth-java-cmd-lib/src/main/java/io/getlime/security/powerauth/lib/cmd/steps/AbstractBaseStep.java @@ -142,7 +142,10 @@ public final JSONObject execute(StepLogger stepLogger, Map conte null ); - StepContext stepContext = prepareStepContext(stepLogger, context); + final StepContext stepContext = prepareStepContext(stepLogger, context); + if (stepContext == null) { + return null; + } try { ResponseContext responseContext = callServer(stepContext); @@ -299,6 +302,11 @@ protected void logDryRun(StepLogger stepLogger) { return null; } + final ParameterizedTypeReference responseTypeReference = getResponseTypeReference(); + if (responseTypeReference == null) { + return null; + } + M model = stepContext.getModel(); RequestContext requestContext = stepContext.getRequestContext(); @@ -332,9 +340,9 @@ protected void logDryRun(StepLogger stepLogger) { try { // Call the right method with the REST client if (HttpMethod.GET.equals(requestContext.getHttpMethod())) { - responseEntity = restClient.get(requestContext.getUri(), null, MapUtil.toMultiValueMap(headers), ParameterizedTypeReference.forType(getResponseTypeReference().getType())); + responseEntity = restClient.get(requestContext.getUri(), null, MapUtil.toMultiValueMap(headers), responseTypeReference); } else { - responseEntity = restClient.post(requestContext.getUri(), requestBytes, null, MapUtil.toMultiValueMap(headers), ParameterizedTypeReference.forType(getResponseTypeReference().getType())); + responseEntity = restClient.post(requestContext.getUri(), requestBytes, null, MapUtil.toMultiValueMap(headers), responseTypeReference); } } catch (RestClientException ex) { stepContext.getStepLogger().writeServerCallError(step.id() + "-error-server-call", ex.getStatusCode().value(), ex.getResponse(), HttpUtil.flattenHttpHeaders(ex.getResponseHeaders())); From ed74c9a39f4875c0a78ff65d8ed1f3180e700122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20=C4=8Cern=C3=BD?= Date: Wed, 21 Dec 2022 20:33:57 +0100 Subject: [PATCH 15/17] Added workflow for OWASP dependency check --- .github/workflows/owas-dependecy-check.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/owas-dependecy-check.yml diff --git a/.github/workflows/owas-dependecy-check.yml b/.github/workflows/owas-dependecy-check.yml new file mode 100644 index 00000000..c79178b2 --- /dev/null +++ b/.github/workflows/owas-dependecy-check.yml @@ -0,0 +1,12 @@ +name: Run OWASP Dependency Check +on: + workflow_dispatch: + + push: + branches: + - 'develop' + +jobs: + owasp-check: + uses: wultra/wultra-infrastructure/.github/workflows/owasp-dependency-check.yml@develop + secrets: inherit \ No newline at end of file From 1cbe19d21e2ea58a51bf11f29ad90e5ac09d5963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20=C4=8Cern=C3=BD?= Date: Wed, 21 Dec 2022 20:48:10 +0100 Subject: [PATCH 16/17] Added credentials and GPG keys for maven --- .github/workflows/maven-deploy.yml | 10 ++++++---- .github/workflows/maven-test.yml | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy.yml index 2d385630..58607393 100644 --- a/.github/workflows/maven-deploy.yml +++ b/.github/workflows/maven-deploy.yml @@ -27,9 +27,9 @@ on: jobs: - maven-deploy-internal: + maven-deploy-jfrog: if: ${{ github.event_name == 'push' }} - name: Deploy to ${{ inputs.environment }} + name: Deploy to jfrog uses: wultra/wultra-infrastructure/.github/workflows/maven-deploy.yml@develop with: environment: internal-publish @@ -38,9 +38,9 @@ jobs: username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} - maven-deploy-public: + maven-deploy-manual: if: ${{ github.event_name == 'workflow_dispatch' }} - name: Deploy to ${{ inputs.environment }} + name: Deploy by parameter uses: wultra/wultra-infrastructure/.github/workflows/maven-deploy.yml@develop with: environment: ${{ inputs.environment }} @@ -48,3 +48,5 @@ jobs: secrets: username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + gpg_passphrase: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} + gpg_key: ${{ secrets.OSSRH_GPG_SECRET_KEY }} \ No newline at end of file diff --git a/.github/workflows/maven-test.yml b/.github/workflows/maven-test.yml index 5f4e4c13..4bba5877 100644 --- a/.github/workflows/maven-test.yml +++ b/.github/workflows/maven-test.yml @@ -16,4 +16,5 @@ on: jobs: maven-tests: - uses: wultra/wultra-infrastructure/.github/workflows/maven-test.yml@develop \ No newline at end of file + uses: wultra/wultra-infrastructure/.github/workflows/maven-test.yml@develop + secrets: inherit \ No newline at end of file From f3051a2e226fb093df0fc616bb9b35e965312e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20=C5=A0trobl?= Date: Thu, 22 Dec 2022 12:36:13 +0100 Subject: [PATCH 17/17] Fix #254: SLF4J warning on startup (#282) --- powerauth-java-cmd/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/powerauth-java-cmd/pom.xml b/powerauth-java-cmd/pom.xml index 3a12370a..7fdb06f5 100644 --- a/powerauth-java-cmd/pom.xml +++ b/powerauth-java-cmd/pom.xml @@ -53,6 +53,10 @@ org.bouncycastle bcprov-jdk18on + + ch.qos.logback + logback-classic +