Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use general encryptor for E2EE #423

Merged
merged 3 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions docs/RESTful-API-for-Spring.md
Original file line number Diff line number Diff line change
Expand Up @@ -394,16 +394,16 @@ You can encrypt data in `application` scope (non-personalized) using following p
public class EncryptedDataExchangeController {

@RequestMapping(value = "application", method = RequestMethod.POST)
@PowerAuthEncryption(scope = EciesScope.APPLICATION_SCOPE)
@PowerAuthEncryption(scope = EncryptionScope.APPLICATION_SCOPE)
public DataExchangeResponse exchangeInApplicationScope(@EncryptedRequestBody DataExchangeRequest request,
EciesEncryptionContext eciesContext) throws PowerAuthEncryptionException {
EncryptionContext encryptionContext) throws PowerAuthEncryptionException {

if (eciesContext == null) {
if (encryptionContext == null) {
throw new PowerAuthEncryptionException();
}

// Return a slightly different String containing original data in response
return new DataExchangeResponse("Server successfully decrypted signed data: " + (request == null ? "''" : request.getData()) + ", scope: " + eciesContext.getEciesScope());
return new DataExchangeResponse("Server successfully decrypted signed data: " + (request == null ? "''" : request.getData()) + ", scope: " + encryptionContext.getEncryptionScope());
}
}
```
Expand All @@ -422,16 +422,16 @@ You can encrypt data in `activation` scope (personalized) using following patter
public class EncryptedDataExchangeController {

@RequestMapping(value = "activation", method = RequestMethod.POST)
@PowerAuthEncryption(scope = EciesScope.ACTIVATION_SCOPE)
@PowerAuthEncryption(scope = EncryptionScope.ACTIVATION_SCOPE)
public DataExchangeResponse exchangeInActivationScope(@EncryptedRequestBody DataExchangeRequest request,
EciesEncryptionContext eciesContext) throws PowerAuthEncryptionException {
EncryptionContext encryptionContext) throws PowerAuthEncryptionException {

if (eciesContext == null) {
if (encryptionContext == null) {
throw new PowerAuthEncryptionException();
}

// Return a slightly different String containing original data in response
return new DataExchangeResponse("Server successfully decrypted signed data: " + (request == null ? "''" : request.getData()) + ", scope: " + eciesContext.getEciesScope());
return new DataExchangeResponse("Server successfully decrypted signed data: " + (request == null ? "''" : request.getData()) + ", scope: " + encryptionContext.getEncryptionScope());
}
}
```
Expand All @@ -451,16 +451,16 @@ public class EncryptedDataExchangeController {

@RequestMapping(value = "signed", method = RequestMethod.POST)
@PowerAuth(resourceId = "/exchange/signed")
@PowerAuthEncryption(scope = EciesScope.ACTIVATION_SCOPE)
@PowerAuthEncryption(scope = EncryptionScope.ACTIVATION_SCOPE)
public DataExchangeResponse exchangeSignedAndEncryptedData(@EncryptedRequestBody DataExchangeRequest request,
EciesEncryptionContext eciesContext,
EncryptionContext encryptionContext,
PowerAuthApiAuthentication auth) throws PowerAuthAuthenticationException, PowerAuthEncryptionException {

if (auth == null || auth.getUserId() == null) {
throw new PowerAuthSignatureInvalidException();
}

if (eciesContext == null) {
if (encryptionContext == null) {
throw new PowerAuthEncryptionException();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
*/
package io.getlime.security.powerauth.rest.api.spring.annotation;

import io.getlime.security.powerauth.crypto.lib.encryptor.ecies.model.EciesScope;
import io.getlime.security.powerauth.crypto.lib.encryptor.model.EncryptorScope;
import io.getlime.security.powerauth.rest.api.spring.encryption.EncryptionScope;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Annotation that simplifies end to end encryption.
* Annotation that simplifies end-to-end encryption.
*
* @author Roman Strobl, [email protected]
*/
Expand All @@ -36,10 +37,9 @@
public @interface PowerAuthEncryption {

/**
* Encryption scope, either EciesScope.ACTIVATION_SCOPE or EciesScope.APPLICATION_SCOPE.
* @see EciesScope
* Encryption scope, either {@link EncryptionScope#ACTIVATION_SCOPE} or {@link EncryptionScope#APPLICATION_SCOPE}.
* @see EncryptorScope
* @return Encryption scope.
*/
EciesScope scope() default EciesScope.ACTIVATION_SCOPE;

EncryptionScope scope() default EncryptionScope.ACTIVATION_SCOPE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.getlime.security.powerauth.rest.api.spring.annotation.EncryptedRequestBody;
import io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthEncryption;
import io.getlime.security.powerauth.rest.api.spring.encryption.EciesEncryptionContext;
import io.getlime.security.powerauth.rest.api.spring.encryption.PowerAuthEciesEncryption;
import io.getlime.security.powerauth.rest.api.spring.encryption.EncryptionContext;
import io.getlime.security.powerauth.rest.api.spring.encryption.PowerAuthEncryptorData;
import io.getlime.security.powerauth.rest.api.spring.model.PowerAuthRequestObjects;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
Expand All @@ -36,13 +37,12 @@
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Type;

/**
* Argument resolver for {@link PowerAuthEciesEncryption} objects. It enables automatic
* parameter resolution for methods that are annotated via {@link PowerAuthEciesEncryption} annotation.
* Argument resolver for {@link PowerAuthEncryptorData} objects. It enables automatic
* parameter resolution for methods that are annotated via {@link PowerAuthEncryptorData} annotation.
*
* @author Roman Strobl, [email protected]
*/
Expand All @@ -55,13 +55,13 @@ public class PowerAuthEncryptionArgumentResolver implements HandlerMethodArgumen
@Override
public boolean supportsParameter(@NonNull MethodParameter parameter) {
return parameter.hasMethodAnnotation(PowerAuthEncryption.class)
&& (parameter.hasParameterAnnotation(EncryptedRequestBody.class) || EciesEncryptionContext.class.isAssignableFrom(parameter.getParameterType()));
&& (parameter.hasParameterAnnotation(EncryptedRequestBody.class) || EncryptionContext.class.isAssignableFrom(parameter.getParameterType()));
}

@Override
public Object resolveArgument(@NonNull MethodParameter parameter, ModelAndViewContainer mavContainer, @NonNull NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
final HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
final PowerAuthEciesEncryption eciesObject = (PowerAuthEciesEncryption) request.getAttribute(PowerAuthRequestObjects.ENCRYPTION_OBJECT);
final PowerAuthEncryptorData eciesObject = (PowerAuthEncryptorData) request.getAttribute(PowerAuthRequestObjects.ENCRYPTION_OBJECT);
// Decrypted object is inserted into parameter annotated by @EncryptedRequestBody annotation
if (parameter.hasParameterAnnotation(EncryptedRequestBody.class) && eciesObject != null && eciesObject.getDecryptedRequest() != null) {
final Type requestType = parameter.getGenericParameterType();
Expand All @@ -81,11 +81,11 @@ public Object resolveArgument(@NonNull MethodParameter parameter, ModelAndViewCo
}
}
// Ecies encryption object is inserted into parameter which is of type PowerAuthEciesEncryption
if (eciesObject != null && EciesEncryptionContext.class.isAssignableFrom(parameter.getParameterType())) {
if (eciesObject != null && EncryptionContext.class.isAssignableFrom(parameter.getParameterType())) {
// Set ECIES scope in case it is specified by the @PowerAuthEncryption annotation
PowerAuthEncryption powerAuthEncryption = parameter.getMethodAnnotation(PowerAuthEncryption.class);
final PowerAuthEncryption powerAuthEncryption = parameter.getMethodAnnotation(io.getlime.security.powerauth.rest.api.spring.annotation.PowerAuthEncryption.class);
if (powerAuthEncryption != null) {
EciesEncryptionContext eciesContext = eciesObject.getContext();
EncryptionContext eciesContext = eciesObject.getContext();
boolean validScope = validateEciesScope(eciesContext);
if (validScope) {
return eciesContext;
Expand All @@ -99,8 +99,8 @@ public Object resolveArgument(@NonNull MethodParameter parameter, ModelAndViewCo
* Validate that encryption HTTP header contains correct values for given ECIES scope.
* @param eciesContext ECIES context.
*/
private boolean validateEciesScope(EciesEncryptionContext eciesContext) {
switch (eciesContext.getEciesScope()) {
private boolean validateEciesScope(EncryptionContext eciesContext) {
switch (eciesContext.getEncryptionScope()) {
case ACTIVATION_SCOPE -> {
if (eciesContext.getApplicationKey() == null || eciesContext.getApplicationKey().isEmpty()) {
logger.warn("ECIES activation scope is invalid because of missing application key");
Expand All @@ -118,7 +118,7 @@ private boolean validateEciesScope(EciesEncryptionContext eciesContext) {
}
}
default -> {
logger.warn("Unsupported ECIES scope: {}", eciesContext.getEciesScope());
logger.warn("Unsupported ECIES scope: {}", eciesContext.getEncryptionScope());
return false;
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* PowerAuth integration libraries for RESTful API applications, examples and
* related software components
*
* Copyright (C) 2018 Wultra s.r.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package io.getlime.security.powerauth.rest.api.spring.encryption;

import io.getlime.security.powerauth.http.PowerAuthHttpHeader;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* Class for storing PowerAuth End-To-End encryption context derived from HTTP headers.
*
* @author Roman Strobl, [email protected]
*/
@Getter
@AllArgsConstructor
public class EncryptionContext {
/**
* Application key.
*/
private final String applicationKey;
/**
* Activation ID.
*/
private final String activationId;
/**
* Protocol version.
*/
private final String version;
/**
* PowerAuth HTTP header used for deriving ECIES encryption context.
*/
private final PowerAuthHttpHeader httpHeader;
/**
* Scope of the encryption.
*/
private final EncryptionScope encryptionScope;
}
Loading