diff --git a/wls-auth-service/pom.xml b/wls-auth-service/pom.xml index ade10daef..7d761aaba 100644 --- a/wls-auth-service/pom.xml +++ b/wls-auth-service/pom.xml @@ -393,7 +393,7 @@ db-h2,dummy.clients - secret + please change me seed diff --git a/wls-common/security/src/main/java/de/muenchen/oss/wahllokalsystem/wls/common/security/AESEncryptionConfiguration.java b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/configuration/AESEncryptionConfiguration.java similarity index 89% rename from wls-common/security/src/main/java/de/muenchen/oss/wahllokalsystem/wls/common/security/AESEncryptionConfiguration.java rename to wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/configuration/AESEncryptionConfiguration.java index c84f8911b..e282ee84f 100644 --- a/wls-common/security/src/main/java/de/muenchen/oss/wahllokalsystem/wls/common/security/AESEncryptionConfiguration.java +++ b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/configuration/AESEncryptionConfiguration.java @@ -1,4 +1,4 @@ -package de.muenchen.oss.wahllokalsystem.wls.common.security; +package de.muenchen.oss.wahllokalsystem.authservice.configuration; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; @@ -12,7 +12,7 @@ public class AESEncryptionConfiguration { private static final String AES = "AES"; - @Value("${app.crypto.key}") + @Value("${service.config.crypto.key}") String key; @Bean diff --git a/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/configuration/EncryptionConfiguration.java b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/configuration/EncryptionConfiguration.java deleted file mode 100644 index 4c5ffcc3f..000000000 --- a/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/configuration/EncryptionConfiguration.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.muenchen.oss.wahllokalsystem.authservice.configuration; - -import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; -import de.muenchen.oss.wahllokalsystem.wls.common.security.EncryptionBuilder; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import javax.crypto.NoSuchPaddingException; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class EncryptionConfiguration { - - @Bean - public EncryptionBuilder encryptionBuilder(@Value("{serviceauth.crypto.key}") final String cryptoKey, final ServiceIDFormatter serviceIDFormatter) - throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException { - return new EncryptionBuilder(cryptoKey.getBytes(), serviceIDFormatter); - } -} diff --git a/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/exception/ExceptionConstants.java b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/exception/ExceptionConstants.java index 5ac4b7a61..d2582a5cd 100644 --- a/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/exception/ExceptionConstants.java +++ b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/exception/ExceptionConstants.java @@ -7,6 +7,8 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class ExceptionConstants { + public static final String CRYPTO_EXCEPTION_CODE = "399"; + public static ExceptionDataWrapper KOMMUNIKATIONSFEHLER_MIT_KONFIGSERVICE = new ExceptionDataWrapper( "100", "Bei der Kommunikation mit dem Konfigurationsservice kam es zu einem Fehler."); } diff --git a/wls-common/security/src/main/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilder.java b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/security/EncryptionBuilder.java similarity index 97% rename from wls-common/security/src/main/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilder.java rename to wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/security/EncryptionBuilder.java index cf7925f3b..d04a1e505 100644 --- a/wls-common/security/src/main/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilder.java +++ b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/security/EncryptionBuilder.java @@ -1,7 +1,7 @@ /** * */ -package de.muenchen.oss.wahllokalsystem.wls.common.security; +package de.muenchen.oss.wahllokalsystem.authservice.security; import de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException; import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; diff --git a/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoService.java b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoService.java index 77fa5a506..bfbec6db0 100644 --- a/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoService.java +++ b/wls-auth-service/src/main/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoService.java @@ -1,37 +1,85 @@ package de.muenchen.oss.wahllokalsystem.authservice.service; -import de.muenchen.oss.wahllokalsystem.wls.common.security.EncryptionBuilder; -import lombok.RequiredArgsConstructor; +import de.muenchen.oss.wahllokalsystem.authservice.exception.ExceptionConstants; +import de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException; +import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; +import java.util.Base64; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import lombok.val; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service -@RequiredArgsConstructor @Slf4j +@Getter +@Setter public class CryptoService { - private final EncryptionBuilder encryptionBuilder; + private final ServiceIDFormatter formatter; + private final Cipher encryptionCipher; + private final Cipher decryptionCipher; @Value("${service.config.crypto.encryptionPrefix}") private String encryptedPrefix = ""; + public CryptoService(ServiceIDFormatter formatter, + @Qualifier("encryptionCipher") Cipher encryptionCipher, + @Qualifier("decryptionCipher") Cipher decryptionCipher) { + this.formatter = formatter; + this.encryptionCipher = encryptionCipher; + this.decryptionCipher = decryptionCipher; + } + public boolean isEncrypted(final String value) { return value.startsWith(encryptedPrefix); } public String encrypt(final String value) { - return encryptedPrefix + encryptionBuilder.encryptValue(value); + return encryptedPrefix + encryptValue(value); } public String decrypt(final String value) { - if (value.startsWith(encryptedPrefix)) { + if (isEncrypted(value)) { val encryptedSubstring = value.substring(encryptedPrefix.length()); - return encryptionBuilder.decryptValue(encryptedSubstring); + return decryptValue(encryptedSubstring); } else { log.warn("value was already decrypted"); return value; } } + + private String decryptValue(String value) { + if (value != null && !value.isEmpty()) { + try { + val decode = Base64.getUrlDecoder().decode(value.getBytes()); + val finalized = decryptionCipher.doFinal(decode); + return new String(finalized); + } catch (IllegalBlockSizeException | BadPaddingException e) { + log.error("Unable to decrypt the value due to " + e.getClass().getSimpleName() + ". Using direct object reference!", e); + throw TechnischeWlsException.withCode(ExceptionConstants.CRYPTO_EXCEPTION_CODE).inService(formatter.getId()) + .buildWithMessage("Problem bei der Entschlüsselung von Objekt-Referenzen"); + } + } + return value; + } + + private String encryptValue(String value) { + if (value != null && !value.isEmpty()) { + try { + val finalized = encryptionCipher.doFinal(value.getBytes()); + value = Base64.getUrlEncoder().encodeToString(finalized); + } catch (IllegalBlockSizeException | BadPaddingException e) { + log.error("Unable to encrypt the value due to " + e.getClass().getSimpleName() + ". Using direct object reference!", e); + throw TechnischeWlsException.withCode(ExceptionConstants.CRYPTO_EXCEPTION_CODE).inService(formatter.getId()) + .buildWithMessage("Problem bei der Verschlüsselung von Objekt-Referenzen"); + } + } + return value; + } } diff --git a/wls-auth-service/src/main/resources/application-local.yml b/wls-auth-service/src/main/resources/application-local.yml index 3d3cebc29..0e9614386 100644 --- a/wls-auth-service/src/main/resources/application-local.yml +++ b/wls-auth-service/src/main/resources/application-local.yml @@ -3,11 +3,10 @@ server: service: config: + crypto: + key: "please change me" oauth2: jwk: rsa: init: - seed: change_me -serviceauth: - crypto: - key: "please change me" \ No newline at end of file + seed: change_me \ No newline at end of file diff --git a/wls-auth-service/src/main/resources/application-test.yml b/wls-auth-service/src/main/resources/application-test.yml index 64a55fcd1..d396d7126 100644 --- a/wls-auth-service/src/main/resources/application-test.yml +++ b/wls-auth-service/src/main/resources/application-test.yml @@ -17,6 +17,8 @@ spring: service: config: + crypto: + key: "please change me" oauth2: jwk: rsa: diff --git a/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/domain/UserRepositoryImplIntegrationTest.java b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/domain/UserRepositoryImplIntegrationTest.java index 539981578..4b4038b99 100644 --- a/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/domain/UserRepositoryImplIntegrationTest.java +++ b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/domain/UserRepositoryImplIntegrationTest.java @@ -19,12 +19,12 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.support.TransactionTemplate; -@SpringBootTest(classes = MicroServiceApplication.class, properties = { "serviceauth.crypto.key=secret" }) +@SpringBootTest(classes = MicroServiceApplication.class, properties = { "service.config.crypto.key=veryLongAndVerySaveKeyIHopeXXXabc123!!" }) @ActiveProfiles({ TestConstants.SPRING_TEST_PROFILE, Profiles.DUMMY_CLIENTS }) class UserRepositoryImplIntegrationTest { private static final String USERNAME_UNENCRYPTED = "username"; - private static final String USERNAME_ENCRYPTED = "ENCRYPTED:AcZZ7iVGyYoE-DTb9rNwgQ=="; + private static final String USERNAME_ENCRYPTED = "ENCRYPTED:TLXm2wsx1kcDLHHU8ZWptQ=="; @Autowired UserRepositoryImpl userRepository; diff --git a/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/rest/WahllokalBenutzerControllerIntegrationTest.java b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/rest/WahllokalBenutzerControllerIntegrationTest.java index 43988dfe4..07b1cd952 100644 --- a/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/rest/WahllokalBenutzerControllerIntegrationTest.java +++ b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/rest/WahllokalBenutzerControllerIntegrationTest.java @@ -33,7 +33,7 @@ @SpringBootTest( classes = MicroServiceApplication.class, - properties = { "service.config.crypto.key=secret", "service.config.user.authority.wahlvorstand=" + PROP_USER_AUTHORITY_WAHLVORSTAND } + properties = { "service.config.user.authority.wahlvorstand=" + PROP_USER_AUTHORITY_WAHLVORSTAND } ) @AutoConfigureMockMvc @ActiveProfiles({ TestConstants.SPRING_TEST_PROFILE, TestConstants.SPRING_NO_SECURITY_PROFILE, Profiles.DUMMY_CLIENTS }) diff --git a/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoServiceIntegrationTest.java b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoServiceIntegrationTest.java new file mode 100644 index 000000000..6e7613787 --- /dev/null +++ b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoServiceIntegrationTest.java @@ -0,0 +1,25 @@ +package de.muenchen.oss.wahllokalsystem.authservice.service; + +import de.muenchen.oss.wahllokalsystem.authservice.configuration.AESEncryptionConfiguration; +import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; +import lombok.val; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest( + classes = { AESEncryptionConfiguration.class, CryptoService.class, ServiceIDFormatter.class }, + properties = { "service.config.crypto.key = 770A8A65DA156D24EE2A093277530142" } +) +class CryptoServiceIntegrationTest { + + @Autowired + CryptoService cryptoService; + + @Test + void should_useProvidedBeans_when_startingContext() { + val valueToEncrypt = "Mzc2NTI2NzIzQUZEQUIzRA=="; + Assertions.assertThat(cryptoService.decrypt(cryptoService.encrypt(valueToEncrypt))).isEqualTo(valueToEncrypt); + } +} diff --git a/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoServiceTest.java b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoServiceTest.java new file mode 100644 index 000000000..de289926d --- /dev/null +++ b/wls-auth-service/src/test/java/de/muenchen/oss/wahllokalsystem/authservice/service/CryptoServiceTest.java @@ -0,0 +1,160 @@ +package de.muenchen.oss.wahllokalsystem.authservice.service; + +import de.muenchen.oss.wahllokalsystem.authservice.exception.ExceptionConstants; +import de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException; +import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; +import java.util.Base64; +import java.util.Set; +import java.util.stream.Stream; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import lombok.val; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class CryptoServiceTest { + + private static final String ENCRYPTION_PREFIX = "encryptionPrefix"; + + @Mock + ServiceIDFormatter idFormatter; + + @Mock + Cipher cipher; + + @InjectMocks + CryptoService unitUnderTest; + + @BeforeEach + void setUp() { + unitUnderTest.setEncryptedPrefix(ENCRYPTION_PREFIX); + } + + @Nested + class IsEncrypted { + + @Test + void should_returnTrue_when_valueStartsWithPrefix() { + Assertions.assertThat(unitUnderTest.isEncrypted(ENCRYPTION_PREFIX + "the encrypted value")).isTrue(); + } + + @Test + void should_returnFalse_when_valueDoesNotStartWithPrefix() { + unitUnderTest.setEncryptedPrefix("prefix"); + Assertions.assertThat(unitUnderTest.isEncrypted("values without encryption prefix")).isFalse(); + } + } + + @Nested + class Encrypt { + + @Test + void should_returnEncryptedValueWithPrefix_when_valueIsGiven() throws Exception { + val valueToEncrypt = "hello world"; + + val mockedEncryptedValue = "encrypted value".getBytes(); + Mockito.when(cipher.doFinal(valueToEncrypt.getBytes())).thenReturn(mockedEncryptedValue); + + val result = unitUnderTest.encrypt(valueToEncrypt); + + val expectedResult = ENCRYPTION_PREFIX + Base64.getEncoder().encodeToString(mockedEncryptedValue); + Assertions.assertThat(result).isEqualTo(expectedResult); + } + + @Test + void should_returnEncryptionPrefix_when_emptyStringValueIsGiven() { + Assertions.assertThat(unitUnderTest.encrypt("")).isEqualTo(ENCRYPTION_PREFIX); + } + + @Test + void should_returnEncryptionPrefix_when_nullIsGiven() { + Assertions.assertThat(unitUnderTest.encrypt(null)).isEqualTo(ENCRYPTION_PREFIX + null); + } + + @ParameterizedTest + @MethodSource("de.muenchen.oss.wahllokalsystem.authservice.service.CryptoServiceTest#exceptionsMappedToWlsException") + void should_throwTechnischeWlsException_when_cipherThrowsException(final Exception exceptionThrownByCipher) throws Exception { + val valueToEncrypt = "hello world"; + + val mockedServiceID = "authService"; + Mockito.when(idFormatter.getId()).thenReturn(mockedServiceID); + Mockito.doThrow(exceptionThrownByCipher).when(cipher).doFinal(valueToEncrypt.getBytes()); + + val expectedException = TechnischeWlsException.withCode(ExceptionConstants.CRYPTO_EXCEPTION_CODE).inService(mockedServiceID) + .buildWithMessage(""); + + Assertions.assertThatThrownBy(() -> unitUnderTest.encrypt(valueToEncrypt)) + .satisfies(exception -> { + Assertions.assertThat(exception) + .usingRecursiveComparison() + .ignoringFields("message") + .isEqualTo(expectedException); + Assertions.assertThat(exception).hasNoNullFieldsOrProperties(); + }); + } + } + + @Nested + class Decrypt { + + @Test + void should_returnValue_when_valueIsNotEncrypted() { + val notEncryptedValue = Base64.getEncoder().encodeToString("not encrypted value".getBytes()); + Assertions.assertThat(unitUnderTest.decrypt(notEncryptedValue)).isEqualTo(notEncryptedValue); + } + + @Test + void should_returnDecryptedValue_when_valueIsGiven() throws Exception { + val encryptedValue = "the encrypted value"; + val encryptedValueAsBase64WithPrefix = ENCRYPTION_PREFIX + Base64.getEncoder().encodeToString(encryptedValue.getBytes()); + + val mockDecrypted = "decrypted value"; + Mockito.when(cipher.doFinal(encryptedValue.getBytes())).thenReturn(mockDecrypted.getBytes()); + + val result = unitUnderTest.decrypt(encryptedValueAsBase64WithPrefix); + + Assertions.assertThat(result).isEqualTo(mockDecrypted); + } + + @ParameterizedTest + @MethodSource("de.muenchen.oss.wahllokalsystem.authservice.service.CryptoServiceTest#exceptionsMappedToWlsException") + void should_throwTechnischeWlsException_when_cipherThrowsException(final Exception exceptionThrownByCipher) throws Exception { + val encryptedValue = "the encrypted value"; + val encryptedValueAsBase64WithPrefix = ENCRYPTION_PREFIX + Base64.getEncoder().encodeToString(encryptedValue.getBytes()); + + val mockedServiceID = "authService"; + Mockito.when(idFormatter.getId()).thenReturn(mockedServiceID); + Mockito.doThrow(exceptionThrownByCipher).when(cipher).doFinal(encryptedValue.getBytes()); + + val expectedException = TechnischeWlsException.withCode(ExceptionConstants.CRYPTO_EXCEPTION_CODE).inService(mockedServiceID) + .buildWithMessage(""); + + Assertions.assertThatThrownBy(() -> unitUnderTest.decrypt(encryptedValueAsBase64WithPrefix)) + .satisfies(exception -> { + Assertions.assertThat(exception) + .usingRecursiveComparison() + .ignoringFields("message") + .isEqualTo(expectedException); + Assertions.assertThat(exception).hasNoNullFieldsOrProperties(); + }); + } + } + + public static Stream exceptionsMappedToWlsException() { + val exceptions = Set.of(new IllegalBlockSizeException(), new BadPaddingException()); + + return exceptions.stream().map(exception -> Arguments.of(exception, exception.getClass().getName())); + } +} diff --git a/wls-common/security/src/test/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilderIntegrationTest.java b/wls-common/security/src/test/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilderIntegrationTest.java deleted file mode 100644 index 09c9da983..000000000 --- a/wls-common/security/src/test/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilderIntegrationTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.muenchen.oss.wahllokalsystem.wls.common.security; - -import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest( - classes = { AESEncryptionConfiguration.class, EncryptionBuilder.class, ServiceIDFormatter.class }, - properties = { "app.crypto.key = 770A8A65DA156D24EE2A093277530142" } -) -class EncryptionBuilderIntegrationTest { - - @Autowired - EncryptionBuilder encryptionBuilder; - - @Test - void should_useProvidedBeans_when_startingContext() { - Assertions.assertThatNoException().isThrownBy(() -> encryptionBuilder.encryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")); - } -} diff --git a/wls-common/security/src/test/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilderTest.java b/wls-common/security/src/test/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilderTest.java deleted file mode 100644 index 21f00b052..000000000 --- a/wls-common/security/src/test/java/de/muenchen/oss/wahllokalsystem/wls/common/security/EncryptionBuilderTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package de.muenchen.oss.wahllokalsystem.wls.common.security; - -import de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException; -import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter; -import de.muenchen.oss.wahllokalsystem.wls.common.testing.LoggerExtension; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import lombok.val; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class EncryptionBuilderTest { - - @RegisterExtension - public LoggerExtension loggerExtension = new LoggerExtension(); - - @Mock - Cipher cipher; - - @Mock - ServiceIDFormatter formatter; - - @InjectMocks - EncryptionBuilder unitUnderTest; - - @Nested - class DecryptValue { - - @Test - void successful() throws IllegalBlockSizeException, BadPaddingException { - Mockito.when(cipher.doFinal("376526723AFDAB3D".getBytes())).thenReturn("mockedText".getBytes()); - Assertions.assertThat(unitUnderTest.decryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")).isEqualTo("mockedText"); - } - - @Test - void emptyValue() { - Assertions.assertThat(unitUnderTest.decryptValue("")).isEmpty(); - } - - @Test - void valueIsNull() { - Assertions.assertThat(unitUnderTest.decryptValue(null)).isNull(); - } - - @Test - void throwBadPadding() throws IllegalBlockSizeException, BadPaddingException { - val mockedBadPaddingException = new BadPaddingException("MockedBadPadding"); - Mockito.when(formatter.getId()).thenReturn("1"); - Mockito.when(cipher.doFinal("376526723AFDAB3D".getBytes())).thenThrow(mockedBadPaddingException); - - Assertions.assertThatThrownBy(() -> unitUnderTest.decryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")) - .isInstanceOf(TechnischeWlsException.class); - } - - @Test - void throwIllegalBlockSize() throws IllegalBlockSizeException, BadPaddingException { - val mockedIllegalBlockSizeException = new IllegalBlockSizeException("MockedIllegalBlockSize"); - Mockito.when(formatter.getId()).thenReturn("1"); - Mockito.when(cipher.doFinal("376526723AFDAB3D".getBytes())).thenThrow(mockedIllegalBlockSizeException); - - Assertions.assertThatThrownBy(() -> unitUnderTest.decryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")) - .isInstanceOf(TechnischeWlsException.class); - } - - @Test - void correctExceptionCodeIsThrown() throws IllegalBlockSizeException, BadPaddingException { - val mockedIllegalBlockSizeException = new IllegalBlockSizeException("MockedIllegalBlockSize"); - Mockito.when(formatter.getId()).thenReturn("1"); - Mockito.when(cipher.doFinal("376526723AFDAB3D".getBytes())).thenThrow(mockedIllegalBlockSizeException); - - Assertions.assertThatThrownBy(() -> unitUnderTest.decryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")) - .hasFieldOrPropertyWithValue("code", "399"); - } - } - - @Nested - class EncryptValue { - - @Test - void successful() throws Exception { - Mockito.when(cipher.doFinal("376526723AFDAB3D".getBytes())).thenReturn("secret".getBytes()); - Assertions.assertThat(unitUnderTest.encryptValue("376526723AFDAB3D")).isEqualTo("c2VjcmV0"); - } - - @Test - void emptyValue() { - Assertions.assertThat(unitUnderTest.encryptValue("")).isEmpty(); - } - - @Test - void valueIsNull() { - Assertions.assertThat(unitUnderTest.encryptValue(null)).isNull(); - } - - @Test - void throwBadPadding() throws IllegalBlockSizeException, BadPaddingException { - val mockedBadPaddingException = new BadPaddingException("MockedBadPadding"); - Mockito.when(formatter.getId()).thenReturn("1"); - Mockito.when(cipher.doFinal("Mzc2NTI2NzIzQUZEQUIzRA==".getBytes())).thenThrow(mockedBadPaddingException); - - Assertions.assertThatThrownBy(() -> unitUnderTest.encryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")) - .isInstanceOf(TechnischeWlsException.class); - } - - @Test - void throwIllegalBlockSize() throws IllegalBlockSizeException, BadPaddingException { - val mockedIllegalBlockSizeException = new IllegalBlockSizeException("MockedIllegalBlockSize"); - Mockito.when(formatter.getId()).thenReturn("1"); - Mockito.when(cipher.doFinal("Mzc2NTI2NzIzQUZEQUIzRA==".getBytes())).thenThrow(mockedIllegalBlockSizeException); - - Assertions.assertThatThrownBy(() -> unitUnderTest.encryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")) - .isInstanceOf(TechnischeWlsException.class); - } - - @Test - void correctExceptionCodeIsThrown() throws IllegalBlockSizeException, BadPaddingException { - val mockedIllegalBlockSizeException = new IllegalBlockSizeException("MockedIllegalBlockSize"); - - Mockito.when(formatter.getId()).thenReturn("1"); - Mockito.when(cipher.doFinal("Mzc2NTI2NzIzQUZEQUIzRA==".getBytes())).thenThrow(mockedIllegalBlockSizeException); - - Assertions.assertThatThrownBy(() -> unitUnderTest.encryptValue("Mzc2NTI2NzIzQUZEQUIzRA==")) - .hasFieldOrPropertyWithValue("code", "399"); - } - } -}