diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0e08d29
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,4 @@
+FROM java:8-jdk-alpine
+COPY target/coding-0.0.1-SNAPSHOT-jar-with-dependencies.jar /usr/app/
+WORKDIR /usr/app
+ENTRYPOINT ["java", "-jar", "coding-0.0.1-SNAPSHOT-jar-with-dependencies.jar"]
\ No newline at end of file
diff --git a/README.md b/README.md
index a84fba4..b27fe38 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,27 @@
-# coding
-Project 4fun
+# 3DES Encryption
+3DES Encryption algorithm implementation in Java
+- The application takes arguments from command line, the first argument is an encryption key, the second is text to be encrypted
+- If encryption key and encryption text weren't passed from the command line, the application will try reading them from environment variables
+ `ENCRYPTION_KEY` `TEXT_TO_ENCRYPT`
+- The application uses a 24 bit encryption key and 8 bit initialization vector
+- Encryption key and initialization vector use SHA1PRNG for key generation
+- DESede/CBC/PKCS5Padding is used as transformation
+- Null values are not encrypted, if null used as an input for the encrypt method, the method will immediately return the null reference. The same
+applies to the decrypt method
+
+## To run the application
+- Checkout the project
+- `mvn package`
+- `java -jar coding-0.0.1-SNAPSHOT-jar-with-dependencies.jar KEY 'text to encrypt'`
+
+## To run the application via docker-compose
+- Checkout the project
+- `mvn package`
+- Open the `docker-compose.yml` and set `ENCRYPTION_KEY` `TEXT_TO_ENCRYPT` environment variables
+- `docker-compose up`
+
+## To run the application via docker
+- Checkout the project
+- `mvn package`
+- `docker build -t 3des-algorithm_encryption . `
+- `docker run -it 3des-algorithm_encryption encryptionKey text`
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..20ad27c
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,5 @@
+3des-algorithm_encryption:
+ build: .
+ environment:
+ - ENCRYPTION_KEY="KDKDKDKD"
+ - TEXT_TO_ENCRYPT="some t3xt"
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 9f4bf02..a09b27b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,15 +10,86 @@
1.8
+ 2.2
+ 5.6.2
+ 2.23.0
+ 3.10
+ UTF-8
+ UTF-8
org.junit.jupiter
junit-jupiter-api
- 5.6.2
+ ${junit-jupiter.version}
test
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
+ test
+
+
+ org.hamcrest
+ hamcrest
+ ${hamcrest.version}
+ provided
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito-junit-jupiter.version}
+ test
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+
+ com.verygood.security.coding.CodingApplication
+
+
+
+ jar-with-dependencies
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.0
+
+ -Dfile.encoding=UTF-8
+
+
+
+
+
diff --git a/src/main/java/com/verygood/security/coding/CodingApplication.java b/src/main/java/com/verygood/security/coding/CodingApplication.java
index 3854440..5d48a80 100644
--- a/src/main/java/com/verygood/security/coding/CodingApplication.java
+++ b/src/main/java/com/verygood/security/coding/CodingApplication.java
@@ -1,8 +1,49 @@
package com.verygood.security.coding;
+import com.verygood.security.coding.api.Encryption;
+import com.verygood.security.coding.api.IEncryptionKeyService;
+import com.verygood.security.coding.api.exception.WrongInputArgumentsException;
+import com.verygood.security.coding.service.EncryptionKeyServiceImpl;
+import com.verygood.security.coding.service.TripleDesEncryptionImpl;
+import org.apache.commons.lang3.StringUtils;
+
public class CodingApplication {
- public static void main(String[] args) {
- // TODO encrypt passed data with algorithm of your choice
- }
+ static final String ENCRYPTION_KEY_ENV_VARIABLE = "ENCRYPTION_KEY";
+ static final String TEXT_TO_ENCRYPT_ENV_VARIABLE = "TEXT_TO_ENCRYPT";
+ private static String encryptionKey;
+ private static String textToEncrypt;
+
+ public static void main(String[] args) {
+ setArguments(args);
+
+ IEncryptionKeyService encryptionKeyService = new EncryptionKeyServiceImpl(encryptionKey);
+ Encryption encryptionService = new TripleDesEncryptionImpl(encryptionKeyService);
+ String encryptedText = encryptionService.encrypt(textToEncrypt);
+ String decryptedText = encryptionService.decrypt(encryptedText);
+
+ System.out.println("Encrypted text: " + encryptedText);
+ System.out.println("Decrypted text: " + decryptedText);
+ }
+
+ private static void setArguments(String[] args) {
+ if (args.length <= 1) {
+ readArgsFromEnvironmentVariables();
+ if (StringUtils.isAllBlank(encryptionKey, textToEncrypt)) {
+ throw new WrongInputArgumentsException("Arguments are empty or half empty. Please input an encryption key and a text, "
+ + "e.g. ./application.jar FHDGYR 'text to encrypt'");
+ }
+ }
+ else {
+ encryptionKey = args[0];
+ textToEncrypt = args[1];
+ }
+ }
+
+ private static void readArgsFromEnvironmentVariables() {
+ String encryptionKeyFromEnv = System.getenv(ENCRYPTION_KEY_ENV_VARIABLE);
+ String textToEncryptFromEnv = System.getenv(TEXT_TO_ENCRYPT_ENV_VARIABLE);
+ encryptionKey = encryptionKeyFromEnv;
+ textToEncrypt = textToEncryptFromEnv;
+ }
}
diff --git a/src/main/java/com/verygood/security/coding/Encryption.java b/src/main/java/com/verygood/security/coding/api/Encryption.java
similarity index 71%
rename from src/main/java/com/verygood/security/coding/Encryption.java
rename to src/main/java/com/verygood/security/coding/api/Encryption.java
index 3f1a28c..3e04acb 100644
--- a/src/main/java/com/verygood/security/coding/Encryption.java
+++ b/src/main/java/com/verygood/security/coding/api/Encryption.java
@@ -1,4 +1,4 @@
-package com.verygood.security.coding;
+package com.verygood.security.coding.api;
public interface Encryption {
String encrypt(String text);
diff --git a/src/main/java/com/verygood/security/coding/api/IEncryptionKeyService.java b/src/main/java/com/verygood/security/coding/api/IEncryptionKeyService.java
new file mode 100644
index 0000000..2eecff2
--- /dev/null
+++ b/src/main/java/com/verygood/security/coding/api/IEncryptionKeyService.java
@@ -0,0 +1,8 @@
+package com.verygood.security.coding.api;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+
+public interface IEncryptionKeyService {
+ byte[] getKey() throws NoSuchAlgorithmException, InvalidKeySpecException;
+}
diff --git a/src/main/java/com/verygood/security/coding/api/exception/WrongInputArgumentsException.java b/src/main/java/com/verygood/security/coding/api/exception/WrongInputArgumentsException.java
new file mode 100644
index 0000000..3fb1220
--- /dev/null
+++ b/src/main/java/com/verygood/security/coding/api/exception/WrongInputArgumentsException.java
@@ -0,0 +1,8 @@
+package com.verygood.security.coding.api.exception;
+
+public class WrongInputArgumentsException extends RuntimeException {
+
+ public WrongInputArgumentsException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/verygood/security/coding/service/EncryptionKeyServiceImpl.java b/src/main/java/com/verygood/security/coding/service/EncryptionKeyServiceImpl.java
new file mode 100644
index 0000000..abde18d
--- /dev/null
+++ b/src/main/java/com/verygood/security/coding/service/EncryptionKeyServiceImpl.java
@@ -0,0 +1,52 @@
+package com.verygood.security.coding.service;
+
+import com.verygood.security.coding.api.IEncryptionKeyService;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+public class EncryptionKeyServiceImpl implements IEncryptionKeyService {
+
+ private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
+ private static final String SHA1PRNG_ALGORITHM = "SHA1PRNG";
+ static final int KEY_SIZE = 24;
+ private byte[] encryptionKeyInBytes;
+ private String encryptionKey;
+
+ public EncryptionKeyServiceImpl(String encryptionKey) {
+ this.encryptionKey = encryptionKey;
+ }
+
+ @Override
+ public byte[] getKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ if (encryptionKeyInBytes == null) {
+ encryptionKeyInBytes = generateKey();
+ }
+ return encryptionKeyInBytes;
+ }
+
+ private byte[] generateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
+
+ if (encryptionKey == null) {
+ System.out.println("Encryption key is blank, using an autogenerated key");
+ encryptionKey = "";
+ }
+
+ int iterations = 10;
+ char[] chars = encryptionKey.toCharArray();
+ byte[] salt = getSalt();
+
+ PBEKeySpec spec = new PBEKeySpec(chars, salt, iterations, KEY_SIZE * 8);
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
+ return skf.generateSecret(spec).getEncoded();
+ }
+
+ private static byte[] getSalt() throws NoSuchAlgorithmException {
+ SecureRandom sr = SecureRandom.getInstance(SHA1PRNG_ALGORITHM);
+ byte[] salt = new byte[16];
+ sr.nextBytes(salt);
+ return salt;
+ }
+}
diff --git a/src/main/java/com/verygood/security/coding/service/TripleDesEncryptionImpl.java b/src/main/java/com/verygood/security/coding/service/TripleDesEncryptionImpl.java
new file mode 100644
index 0000000..62ddebc
--- /dev/null
+++ b/src/main/java/com/verygood/security/coding/service/TripleDesEncryptionImpl.java
@@ -0,0 +1,95 @@
+package com.verygood.security.coding.service;
+
+import com.verygood.security.coding.api.Encryption;
+import com.verygood.security.coding.api.IEncryptionKeyService;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Base64;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class TripleDesEncryptionImpl implements Encryption {
+
+ private static final Charset ENCODING = StandardCharsets.UTF_8;
+ private static final String ALGORITHM = "DESede";
+ private static final String TRANSFORMATION = ALGORITHM + "/CBC/PKCS5Padding";
+ private static final String SECURE_RANDOM_ALGORITHM = "SHA1PRNG";
+ private final IEncryptionKeyService secretKeyService;
+ private IvParameterSpec ivParameterSpec;
+ private SecretKeySpec secretKeySpecs;
+
+ public TripleDesEncryptionImpl(IEncryptionKeyService secretKeyService) {
+ this.secretKeyService = secretKeyService;
+ }
+
+ @Override
+ public String encrypt(String text) {
+ if (text == null) {
+ return null;
+ }
+ byte[] bytes = new byte[0];
+ try {
+ bytes = encryptDecryptInternal(text.getBytes(ENCODING), Cipher.ENCRYPT_MODE);
+ } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchPaddingException
+ | BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException e) {
+ e.printStackTrace();
+ }
+ return Base64.getEncoder().encodeToString(bytes);
+ }
+
+ @Override
+ public String decrypt(String text) {
+ if (text == null) {
+ return null;
+ }
+ byte[] textDecoded = Base64.getDecoder().decode(text);
+ byte[] bytes = new byte[0];
+ try {
+ bytes = encryptDecryptInternal(textDecoded, Cipher.DECRYPT_MODE);
+ } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchPaddingException
+ | BadPaddingException | IllegalBlockSizeException | InvalidKeySpecException e) {
+ e.printStackTrace();
+ }
+ return new String(bytes, ENCODING);
+ }
+
+ private byte[] encryptDecryptInternal(byte[] text, int mode) throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, InvalidKeyException,
+ NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeySpecException {
+
+ SecretKey key = getSecretKey();
+ IvParameterSpec iv = getIvParameterSpec();
+ Cipher cipher = Cipher.getInstance(TRANSFORMATION);
+ cipher.init(mode, key, iv);
+
+ return cipher.doFinal(text);
+ }
+
+ private SecretKeySpec getSecretKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
+ if (secretKeySpecs == null) {
+ secretKeySpecs = new SecretKeySpec(secretKeyService.getKey(), ALGORITHM);
+ }
+ return secretKeySpecs;
+ }
+
+ private IvParameterSpec getIvParameterSpec() throws NoSuchAlgorithmException {
+ if (ivParameterSpec == null) {
+ SecureRandom randomSecureRandom = SecureRandom.getInstance(SECURE_RANDOM_ALGORITHM);
+ byte[] bytes = new byte[8];
+ randomSecureRandom.nextBytes(bytes);
+ ivParameterSpec = new IvParameterSpec(bytes);
+ }
+ return ivParameterSpec;
+ }
+
+}
diff --git a/src/test/java/com/verygood/security/coding/CodingApplicationTests.java b/src/test/java/com/verygood/security/coding/CodingApplicationTests.java
index bec028b..9a37691 100644
--- a/src/test/java/com/verygood/security/coding/CodingApplicationTests.java
+++ b/src/test/java/com/verygood/security/coding/CodingApplicationTests.java
@@ -1,12 +1,70 @@
package com.verygood.security.coding;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.verygood.security.coding.api.exception.WrongInputArgumentsException;
import org.junit.jupiter.api.Test;
class CodingApplicationTests {
- // TODO add test cases
+ @Test
+ void applicationStartsWithoutErrors() {
+ String[] args = new String[]{"encryptionKey", "textToEncrypt"};
+ CodingApplication.main(args);
+ }
+
+ @Test
+ void applicationEncryptsDecryptsRussian() {
+ String[] args = new String[]{"encryptionKey", "русский"};
+ CodingApplication.main(args);
+ }
+
+ @Test
+ void applicationEncryptsDecryptsRussian_whenKeyInRussian() {
+ String[] args = new String[]{"русскийКлюч", "русский"};
+ CodingApplication.main(args);
+ }
+
+ @Test
+ void applicationStartsWithoutErrors_ifKeyAndTextAreEmpty() {
+ String[] args = new String[]{"", ""};
+ CodingApplication.main(args);
+ }
+
+ @Test
+ void applicationStartsWithoutErrors_ifKeyAndTextAreBlank() {
+ String[] args = new String[]{" ", " "};
+ CodingApplication.main(args);
+ }
+
+ @Test
+ void applicationStartsWithoutErrors_ifKeyIsBlank_whileTextHasSomeValue() {
+ String[] args = new String[]{" ", "test"};
+ CodingApplication.main(args);
+ }
+
+ @Test
+ void applicationStartsWithoutErrors_ifKeyNotBlank_whileTextIsBlank() {
+ String[] args = new String[]{"test", " "};
+ CodingApplication.main(args);
+ }
+
+
+ @Test
+ void applicationThrowsWrongInputArgumentsException_ifOnlyOneArgPassed() {
+ assertThrows(WrongInputArgumentsException.class,
+ ()->{
+ String[] args = new String[]{"encryptionKey"};
+ CodingApplication.main(args);
+ });
+ }
@Test
- void testSomething() {
+ void applicationThrowsWrongInputArgumentsException_ifNoArgPassed() {
+ assertThrows(WrongInputArgumentsException.class,
+ ()->{
+ String[] args = new String[]{};
+ CodingApplication.main(args);
+ });
}
}
diff --git a/src/test/java/com/verygood/security/coding/service/EncryptionKeyServiceImplTest.java b/src/test/java/com/verygood/security/coding/service/EncryptionKeyServiceImplTest.java
new file mode 100644
index 0000000..2003d31
--- /dev/null
+++ b/src/test/java/com/verygood/security/coding/service/EncryptionKeyServiceImplTest.java
@@ -0,0 +1,61 @@
+package com.verygood.security.coding.service;
+
+import static com.verygood.security.coding.service.EncryptionKeyServiceImpl.KEY_SIZE;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+import java.nio.charset.StandardCharsets;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import org.junit.jupiter.api.Test;
+
+class EncryptionKeyServiceImplTest {
+
+ private EncryptionKeyServiceImpl encryptionKeyService;
+
+ @Test
+ void getKey_returns24BytesKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ String keyInString = "test";
+ encryptionKeyService = new EncryptionKeyServiceImpl(keyInString);
+
+ // when
+ byte[] actualEncryptionKey = encryptionKeyService.getKey();
+
+ // then
+ assertThat(actualEncryptionKey.length, is(KEY_SIZE));
+ String keyAfterGeneration = new String(actualEncryptionKey, StandardCharsets.UTF_8);
+ assertThat(keyInString, is(not(keyAfterGeneration)));
+ }
+
+ @Test
+ void getKey_returns24BytesKeyForNull() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ String keyInString = null;
+ encryptionKeyService = new EncryptionKeyServiceImpl(keyInString);
+
+ // when
+ byte[] actualEncryptionKey = encryptionKeyService.getKey();
+
+ // then
+ assertThat(actualEncryptionKey.length, is(KEY_SIZE));
+ String keyAfterGeneration = new String(actualEncryptionKey, StandardCharsets.UTF_8);
+ assertThat(keyInString, is(not(keyAfterGeneration)));
+ }
+
+ @Test
+ void getKey_returns24BytesKeyForEmptyString() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ String keyInString = "";
+ encryptionKeyService = new EncryptionKeyServiceImpl(keyInString);
+
+ // when
+ byte[] actualEncryptionKey = encryptionKeyService.getKey();
+
+ // then
+ assertThat(actualEncryptionKey.length, is(KEY_SIZE));
+ String keyAfterGeneration = new String(actualEncryptionKey, StandardCharsets.UTF_8);
+ assertThat(keyInString, is(not(keyAfterGeneration)));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/verygood/security/coding/service/TripleDesEncryptionImplTest.java b/src/test/java/com/verygood/security/coding/service/TripleDesEncryptionImplTest.java
new file mode 100644
index 0000000..829da2e
--- /dev/null
+++ b/src/test/java/com/verygood/security/coding/service/TripleDesEncryptionImplTest.java
@@ -0,0 +1,116 @@
+package com.verygood.security.coding.service;
+
+import static com.verygood.security.coding.service.EncryptionKeyServiceImpl.KEY_SIZE;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.text.IsEmptyString.emptyString;
+import static org.mockito.BDDMockito.given;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class TripleDesEncryptionImplTest {
+
+ private static final String STRING_TO_ENCRYPT = "test";
+ @Mock
+ EncryptionKeyServiceImpl secretKeyService;
+ @InjectMocks
+ private TripleDesEncryptionImpl tripleDesEncryption;
+
+ @Test
+ void encrypt_encryptsData() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ given(secretKeyService.getKey()).willReturn(new byte[KEY_SIZE]);
+
+ // when
+ String encryptedText = tripleDesEncryption.encrypt(STRING_TO_ENCRYPT);
+
+ // then
+ assertThat(encryptedText, is(not(emptyString())));
+ assertThat(encryptedText, is(not(STRING_TO_ENCRYPT)));
+
+ }
+
+ @Test
+ void encrypt_returnsTheSameValueOnMultipleInvocations() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ given(secretKeyService.getKey()).willReturn(new byte[KEY_SIZE]);
+
+ // when
+ String firstEncryption = tripleDesEncryption.encrypt(STRING_TO_ENCRYPT);
+ String secondEncryption = tripleDesEncryption.encrypt(STRING_TO_ENCRYPT);
+
+ // then
+ assertThat(firstEncryption, is(not(emptyString())));
+ assertThat(secondEncryption, is(not(emptyString())));
+ assertThat(firstEncryption, is((secondEncryption)));
+
+ }
+
+ @Test
+ void decrypt_decryptsData() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ given(secretKeyService.getKey()).willReturn(new byte[KEY_SIZE]);
+
+ // when
+ String encryptedText = tripleDesEncryption.encrypt(STRING_TO_ENCRYPT);
+ String decryptedText = tripleDesEncryption.decrypt(encryptedText);
+
+ // then
+ assertThat(decryptedText, is(not(emptyString())));
+ assertThat(decryptedText, is(STRING_TO_ENCRYPT));
+
+ }
+
+ @Test
+ void decrypt_ProperlyDecryptsRussian() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ given(secretKeyService.getKey()).willReturn(new byte[KEY_SIZE]);
+ String expectedText = "русский";
+
+ // when
+ String encryptedText = tripleDesEncryption.encrypt(expectedText);
+ String decryptedText = tripleDesEncryption.decrypt(encryptedText);
+
+ // then
+ assertThat(decryptedText, is(not(emptyString())));
+ assertThat(decryptedText, is(expectedText));
+
+ }
+
+ @Test
+ void encrypt_properlyEncryptsEmptyString() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ // given
+ given(secretKeyService.getKey()).willReturn(new byte[KEY_SIZE]);
+ String expectedString = "";
+
+ // when
+ String encryptedText = tripleDesEncryption.encrypt(expectedString);
+ String decryptedText = tripleDesEncryption.decrypt(encryptedText);
+
+ // then
+ assertThat(decryptedText, is(expectedString));
+
+ }
+
+ @Test
+ void encrypt_returnsNullOnNullString() {
+ // given
+ String expectedString = null;
+
+ // when
+ String encryptedText = tripleDesEncryption.encrypt(expectedString);
+ String decryptedText = tripleDesEncryption.decrypt(encryptedText);
+
+ // then
+ assertThat(decryptedText, is(expectedString));
+
+ }
+}
\ No newline at end of file