Skip to content

Commit

Permalink
Merge pull request #480 from wultra/develop
Browse files Browse the repository at this point in the history
Merge develop to master
  • Loading branch information
banterCZ authored Oct 25, 2024
2 parents cb5d81e + b02709f commit d857d16
Show file tree
Hide file tree
Showing 29 changed files with 400 additions and 64 deletions.
17 changes: 11 additions & 6 deletions docs/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ This file is automatically created by the utility after you call the `create` me
## Specifying PowerAuth Protocol Version

Command-line tool supports following PowerAuth protocol versions:
- Version `3.2` (default)
- Version `3.3` (default)
- Version `3.2`
- Version `3.1`
- Version `3.0`

Expand Down Expand Up @@ -297,14 +298,15 @@ Use this method to send encrypted data to the server.
```bash
java -jar powerauth-java-cmd.jar \
--url "http://localhost:8080/enrollment-server/exchange" \
--base-url "http://localhost:8080/enrollment-server" \
--config-file "config.json" \
--method "encrypt" \
--data-file "request.json" \
--scope "application"
```

Uses the `encrypt` method to encrypt data in `request.json` file using ECIES encryption. The encryption uses `application` scope, you can use the `activation` option to switch to activation scope.
The encrypted data is sent to specified endpoint URL. The endpoint which receives encrypted data needs to decrypt the data and return encrypted response back to the client. The cmd line tool receives the encrypted response from server, decrypts it and prints it into the command line.
The encrypted data is sent to specified endpoint URL. The base URL is used for PowerAuth Standard RESTful API requests, e.g. to request temporary encryption keys. The endpoint which receives encrypted data needs to decrypt the data and return encrypted response back to the client. The cmd line tool receives the encrypted response from server, decrypts it and prints it into the command line.

### Send Signed and Encrypted Data to Server

Expand All @@ -313,6 +315,7 @@ Use this method to send signed and encrypted data to the server.
```bash
java -jar powerauth-java-cmd.jar \
--url "http://localhost:8080/enrollment-server/exchange/v3/signed" \
--base-url "http://localhost:8080/enrollment-server" \
--status-file "pa_status.json" \
--config-file "config.json" \
--method "sign-encrypt" \
Expand All @@ -324,7 +327,7 @@ java -jar powerauth-java-cmd.jar \
```

The data in `request.json` file is signed and encrypted using ECIES encryption. See chapter [Validate the Signature](#validate-the-signature) which describes signature parameters.
The encrypted data is sent to specified endpoint URL. The endpoint which receives encrypted data needs to decrypt the data, verify data signature and return encrypted response back to the client. The cmd line tool receives the encrypted response from server, decrypts it and prints it into the command line.
The encrypted data is sent to specified endpoint URL. The base URL is used for PowerAuth Standard RESTful API requests, e.g. to request temporary encryption keys. The endpoint which receives encrypted data needs to decrypt the data, verify data signature and return encrypted response back to the client. The cmd line tool receives the encrypted response from server, decrypts it and prints it into the command line.

### Send Encrypted Data with Token Validation to Server

Expand All @@ -333,6 +336,7 @@ Use this method to send encrypted data with token validation to the server.
```bash
java -jar powerauth-java-cmd.jar \
--url "http://localhost:8080/enrollment-server/exchange/v3/token" \
--base-url "http://localhost:8080/enrollment-server" \
--status-file "pa_status.json" \
--config-file "config.json" \
--method "token-encrypt" \
Expand All @@ -343,7 +347,7 @@ java -jar powerauth-java-cmd.jar \
```

The data in `request.json` file is encrypted using ECIES encryption and token authentication is computed.
The encrypted data is sent to specified endpoint URL. The endpoint which receives encrypted data needs to decrypt the data, validate the token and return encrypted response back to the client. The cmd line tool receives the encrypted response from server, decrypts it and prints it into the command line.
The encrypted data is sent to specified endpoint URL. The base URL is used for PowerAuth Standard RESTful API requests, e.g. to request temporary encryption keys. The endpoint which receives encrypted data needs to decrypt the data, validate the token and return encrypted response back to the client. The cmd line tool receives the encrypted response from server, decrypts it and prints it into the command line.

### Start Upgrade

Expand All @@ -365,7 +369,7 @@ Use this method to commit upgrade of a version `2` activation to version `3`.

```
java -jar powerauth-java-cmd.jar \
--url "http://localhost:8080/powerauth-webflow" \
--url "http://localhost:8080/enrollment-server" \
--status-file "pa_status.json" \
--config-file "config.json" \
--method "commit-upgrade"
Expand Down Expand Up @@ -399,6 +403,7 @@ usage: java -jar powerauth-java-cmd.jar
-a,--activation-code <arg> In case a specified method is 'create', this field contains the
activation key (a concatenation of a short activation ID and
activation OTP).
-b,--base-url <arg> Base URL of the PowerAuth Standard RESTful API.
-A,--activation-otp <arg> In case a specified method is 'create', this field contains
additional activation OTP (PA server 0.24+)
-c,--config-file <arg> Specifies a path to the config file with Base64 encoded server
Expand Down Expand Up @@ -445,7 +450,7 @@ usage: java -jar powerauth-java-cmd.jar
'token-encrypt', this field specifies a HTTP method, as
specified in PowerAuth signature process.
-T,--token-id <arg> Token ID (UUID4), in case of 'token-validate' method.
-u,--url <arg> Base URL of the PowerAuth Standard RESTful API.
-u,--url <arg> URL used for the request.
-v,--version <arg> PowerAuth protocol version.
-y,--dry-run In case a specified method is 'sign', 'sign-encrypt',
'validate-token' or 'token-encrypt' and this attribute is
Expand Down
20 changes: 10 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

<groupId>io.getlime.security</groupId>
<artifactId>powerauth-cmd-parent</artifactId>
<version>1.8.0</version>
<version>1.9.0</version>
<packaging>pom</packaging>

<inceptionYear>2016</inceptionYear>
Expand Down Expand Up @@ -78,19 +78,19 @@

<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
<maven-deploy-plugin.version>3.1.2</maven-deploy-plugin.version>
<maven-javadoc-plugin.version>3.8.0</maven-javadoc-plugin.version>
<maven-deploy-plugin.version>3.1.3</maven-deploy-plugin.version>
<maven-javadoc-plugin.version>3.10.1</maven-javadoc-plugin.version>
<maven-enforcer-plugin.version>3.5.0</maven-enforcer-plugin.version>
<maven-surefire-plugin.version>3.3.1</maven-surefire-plugin.version>
<spring-boot.version>3.3.2</spring-boot.version>
<commons-cli.version>1.8.0</commons-cli.version>
<commons-io.version>2.16.1</commons-io.version>
<maven-surefire-plugin.version>3.5.1</maven-surefire-plugin.version>
<spring-boot.version>3.3.4</spring-boot.version>
<commons-cli.version>1.9.0</commons-cli.version>
<commons-io.version>2.17.0</commons-io.version>
<json-simple.version>1.1.1</json-simple.version>

<!-- Wultra Dependencies -->
<powerauth-restful-integration>1.8.0</powerauth-restful-integration>
<powerauth-crypto.version>1.8.0</powerauth-crypto.version>
<wultra-core.version>1.10.0</wultra-core.version>
<powerauth-restful-integration>1.9.0</powerauth-restful-integration>
<powerauth-crypto.version>1.9.0</powerauth-crypto.version>
<wultra-core.version>1.11.0</wultra-core.version>
</properties>

<dependencyManagement>
Expand Down
6 changes: 5 additions & 1 deletion powerauth-java-cmd-lib/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<parent>
<artifactId>powerauth-cmd-parent</artifactId>
<groupId>io.getlime.security</groupId>
<version>1.8.0</version>
<version>1.9.0</version>
</parent>

<dependencies>
Expand Down Expand Up @@ -54,6 +54,10 @@
<artifactId>powerauth-java-http</artifactId>
<version>${powerauth-crypto.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ public enum PowerAuthVersion {
V3_1(3, "3.1"),

/**
* Version 3.1
* Version 3.2
*/
V3_2(3, "3.2");
V3_2(3, "3.2"),

/**
* Version 3.3
*/
V3_3(3, "3.3");

/**
* All supported versions
Expand All @@ -49,20 +54,20 @@ public enum PowerAuthVersion {
/**
* Default version
*/
public static final PowerAuthVersion DEFAULT = V3_2;
public static final PowerAuthVersion DEFAULT = V3_3;

/**
* All versions belonging to major version 3
*/
public static final List<PowerAuthVersion> VERSION_3 = List.of(V3_0, V3_1, V3_2);
public static final List<PowerAuthVersion> VERSION_3 = List.of(V3_0, V3_1, V3_2, V3_3);

/**
* Major version value
*/
private final int majorVersion;

/**
* Version string value ("3.0", "3.1", "3.2", ...)
* Version string value ("3.0", "3.1", "3.2", "3.3", ...)
*/
private final String value;

Expand Down Expand Up @@ -94,7 +99,7 @@ public boolean useIv() {
* @return Flag whether decryption uses different non-zero initialization vector.
*/
public boolean useDifferentIvForResponse() {
return majorVersion >= 3 && V3_2.equals(this);
return majorVersion >= 3 && !V3_0.equals(this) && !V3_1.equals(this);
}

/**
Expand All @@ -107,6 +112,16 @@ public boolean useTimestamp() {
return majorVersion >= 3 && !V3_0.equals(this) && !V3_1.equals(this);
}

/**
* Provides flag whether encryption uses temporary keys.
* <p>This feature is supported only for protocol V3.3.+</p>
*
* @return Flag whether encryption uses temporary keys
*/
public boolean useTemporaryKeys() {
return majorVersion >= 3 && !V3_0.equals(this) && !V3_1.equals(this) && !V3_2.equals(this);
}

/**
* @return Version string value
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
import io.getlime.security.powerauth.crypto.client.vault.PowerAuthClientVault;
import io.getlime.security.powerauth.crypto.lib.encryptor.ClientEncryptor;
import io.getlime.security.powerauth.crypto.lib.encryptor.EncryptorFactory;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptedRequest;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptedResponse;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptorId;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptorParameters;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.*;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.v3.ClientEncryptorSecrets;
import io.getlime.security.powerauth.crypto.lib.generator.KeyGenerator;
import io.getlime.security.powerauth.crypto.lib.util.KeyConvertor;
Expand Down Expand Up @@ -57,6 +54,9 @@
import java.security.PublicKey;
import java.util.*;

import static io.getlime.security.powerauth.lib.cmd.util.TemporaryKeyUtil.TEMPORARY_KEY_ID;
import static io.getlime.security.powerauth.lib.cmd.util.TemporaryKeyUtil.TEMPORARY_PUBLIC_KEY;

/**
* Abstract step with common parts used in activations steps
*
Expand Down Expand Up @@ -135,7 +135,6 @@ public void processResponse(StepContext<M, EciesEncryptedResponse> stepContext)
public ResultStatusObject processResponse(EciesEncryptedResponse encryptedResponseL1,
StepContext<M, EciesEncryptedResponse> context) throws Exception {
M model = context.getModel();
final PowerAuthVersion version = model.getVersion();
final ActivationSecurityContext securityContext = (ActivationSecurityContext) context.getSecurityContext();

// Decrypt activation layer 1 response
Expand Down Expand Up @@ -252,17 +251,22 @@ protected ParameterizedTypeReference<EciesEncryptedResponse> getResponseTypeRefe
*/
protected void addEncryptedRequest(StepContext<M, EciesEncryptedResponse> stepContext) throws Exception {
M model = stepContext.getModel();
fetchTemporaryKey(stepContext, EncryptorScope.APPLICATION_SCOPE);

final String temporaryPublicKey = (String) stepContext.getAttributes().get(TEMPORARY_PUBLIC_KEY);
final PublicKey encryptionPublicKey = temporaryPublicKey == null ?
model.getMasterPublicKey() :
KEY_CONVERTOR.convertBytesToPublicKey(Base64.getDecoder().decode(temporaryPublicKey));
// Get activation key and secret
ClientEncryptor clientEncryptorL1 = ENCRYPTOR_FACTORY.getClientEncryptor(
EncryptorId.APPLICATION_SCOPE_GENERIC,
new EncryptorParameters(model.getVersion().value(), model.getApplicationKey(), null),
new ClientEncryptorSecrets(model.getMasterPublicKey(), model.getApplicationSecret())
new EncryptorParameters(model.getVersion().value(), model.getApplicationKey(), null, (String) stepContext.getAttributes().get(TEMPORARY_KEY_ID)),
new ClientEncryptorSecrets(encryptionPublicKey, model.getApplicationSecret())
);
ClientEncryptor clientEncryptorL2 = ENCRYPTOR_FACTORY.getClientEncryptor(
EncryptorId.ACTIVATION_LAYER_2,
new EncryptorParameters(model.getVersion().value(), model.getApplicationKey(), null),
new ClientEncryptorSecrets(model.getMasterPublicKey(), model.getApplicationSecret())
new EncryptorParameters(model.getVersion().value(), model.getApplicationKey(), null, (String) stepContext.getAttributes().get(TEMPORARY_KEY_ID)),
new ClientEncryptorSecrets(encryptionPublicKey, model.getApplicationSecret())
);

KeyPair deviceKeyPair = ACTIVATION.generateDeviceKeyPair();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@
import com.wultra.core.rest.client.base.RestClientException;
import io.getlime.security.powerauth.crypto.lib.encryptor.ClientEncryptor;
import io.getlime.security.powerauth.crypto.lib.encryptor.EncryptorFactory;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptedRequest;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptedResponse;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptorId;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptorParameters;
import io.getlime.security.powerauth.crypto.lib.encryptor.ecies.exception.EciesException;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.*;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.v3.ClientEncryptorSecrets;
import io.getlime.security.powerauth.crypto.lib.util.KeyConvertor;
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.DisabledStepLogger;
Expand Down Expand Up @@ -54,8 +53,12 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.security.PublicKey;
import java.util.*;

import static io.getlime.security.powerauth.lib.cmd.util.TemporaryKeyUtil.TEMPORARY_KEY_ID;
import static io.getlime.security.powerauth.lib.cmd.util.TemporaryKeyUtil.TEMPORARY_PUBLIC_KEY;

/**
* Abstract step with common execution patterns and methods
*
Expand All @@ -66,6 +69,7 @@
public abstract class AbstractBaseStep<M extends BaseStepData, R> implements BaseStep {

private static final Logger logger = LoggerFactory.getLogger(AbstractBaseStep.class);
private static final KeyConvertor KEY_CONVERTOR = new KeyConvertor();

/**
* Corresponding PowerAuth step
Expand Down Expand Up @@ -147,8 +151,15 @@ public final ResultStatusObject execute(StepLogger stepLogger, Map<String, Objec
null
);

final StepContext<M, R> stepContext = prepareStepContext(stepLogger, context);
if (stepContext == null) {
final StepContext<M, R> stepContext;
try {
stepContext = prepareStepContext(stepLogger, context);
if (stepContext == null) {
return null;
}
} catch (EciesException e) {
stepLogger.writeError(getStep().id() + "-error-encryption", e);
stepLogger.writeDoneFailed(getStep().id() + "-failed");
return null;
}

Expand Down Expand Up @@ -184,18 +195,26 @@ public final ResultStatusObject execute(StepLogger stepLogger, Map<String, Objec
* @param applicationSecret Application secret
* @param encryptorId Encryptor identifier
* @param data Request data for the encryption
* @param scope Encryptor scope
* @throws Exception when an error during encryption of the request data occurred
*/
public void addEncryptedRequest(StepContext<M, R> stepContext, String applicationKey, String applicationSecret, EncryptorId encryptorId, byte[] data) throws Exception {
public void addEncryptedRequest(StepContext<M, R> stepContext, String applicationKey, String applicationSecret, EncryptorId encryptorId, byte[] data, EncryptorScope scope) throws Exception {
M model = stepContext.getModel();
final SimpleSecurityContext securityContext = (SimpleSecurityContext) stepContext.getSecurityContext();
final ResultStatusObject resultStatusObject = model.getResultStatus();

fetchTemporaryKey(stepContext, scope);

final ClientEncryptor encryptor;
if (securityContext == null) {
final String temporaryKeyId = (String) stepContext.getAttributes().get(TEMPORARY_KEY_ID);
final String temporaryPublicKey = (String) stepContext.getAttributes().get(TEMPORARY_PUBLIC_KEY);
final PublicKey encryptionPublicKey = temporaryKeyId == null ?
resultStatusObject.getServerPublicKeyObject() :
KEY_CONVERTOR.convertBytesToPublicKey(Base64.getDecoder().decode(temporaryPublicKey));
final byte[] transportMasterKeyBytes = Base64.getDecoder().decode(resultStatusObject.getTransportMasterKey());
final EncryptorParameters encryptorParameters = new EncryptorParameters(model.getVersion().value(), applicationKey, resultStatusObject.getActivationId());
final ClientEncryptorSecrets encryptorSecrets = new ClientEncryptorSecrets(resultStatusObject.getServerPublicKeyObject(), applicationSecret, transportMasterKeyBytes);
final EncryptorParameters encryptorParameters = new EncryptorParameters(model.getVersion().value(), applicationKey, resultStatusObject.getActivationId(), temporaryKeyId);
final ClientEncryptorSecrets encryptorSecrets = new ClientEncryptorSecrets(encryptionPublicKey, applicationSecret, transportMasterKeyBytes);
encryptor = ENCRYPTOR_FACTORY.getClientEncryptor(encryptorId, encryptorParameters, encryptorSecrets);
stepContext.setSecurityContext(SimpleSecurityContext.builder()
.encryptor(encryptor)
Expand Down Expand Up @@ -232,6 +251,16 @@ public void addEncryptedRequest(StepContext<M, R> stepContext, ClientEncryptor e
stepContext.getRequestContext().setRequestObject(requestObject);
}

/**
* Fetch temporary key for current request, if applicable.
* @param stepContext Step context.
* @param scope ECIES scope.
* @throws Exception In case request fails.
*/
public void fetchTemporaryKey(StepContext<M, R> stepContext, EncryptorScope scope) throws Exception {
TemporaryKeyUtil.fetchTemporaryKey(getStep(), stepContext, scope);
}

/**
* Decrypts an object from a response
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
* <li>3.0</li>
* <li>3.1</li>
* <li>3.2</li>
* <li>3.3</li>
* </ul>
*
* @author Roman Strobl, [email protected]
Expand Down
Loading

0 comments on commit d857d16

Please sign in to comment.