Skip to content

Commit

Permalink
Improvement of test coverage of datasafe (#328)
Browse files Browse the repository at this point in the history
* Added mutable encryption config to SimpleDatasafeServiceImpl

* Added mutable encryption config to BasicFunctionalityIT

* Added mutable encryption config to BasicFunctionalityIT

* Added removeKey test for KeyStoreService and made changes to KeyStoreAuthTest noPasswords test

* Added two new tests for KeyStoreService and one test for CmsEncryptionServiceImpl

* Added two new tests for KeyStoreService and one test for CmsEncryptionServiceImpl

* Added new test to KeyStoreServiceTest and change made to pom.xml

* Added test for PublicKeySerdeImpl class and tests for  BucketAccessServiceImpl and DefaultDFSConfig

* fix for PublicKeySerdeImpl test

* Removed updateKeyStoreReadKeyPassword test

* fixes made

* fixes made

* fixes made
  • Loading branch information
Thendo20 committed Jul 10, 2024
1 parent c456aca commit 26674d8
Show file tree
Hide file tree
Showing 11 changed files with 276 additions and 19 deletions.
10 changes: 9 additions & 1 deletion datasafe-business/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,13 @@
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
Expand Down Expand Up @@ -226,6 +231,9 @@
<ignoredUnusedDeclaredDependency>javax.xml.bind:jaxb-api:jar</ignoredUnusedDeclaredDependency>
</ignoredUnusedDeclaredDependencies>
<ignoredUsedUndeclaredDependencies>
<ignoredUsedUndeclaredDependency>com.fasterxml.jackson.core:jackson-annotations</ignoredUsedUndeclaredDependency>
<ignoredUsedUndeclaredDependency>com.fasterxml.jackson.core:jackson-core</ignoredUsedUndeclaredDependency>
<ignoredUsedUndeclaredDependency>com.fasterxml.jackson.core:jackson-databind</ignoredUsedUndeclaredDependency>
<ignoredUsedUndeclaredDependency>javax.inject:javax.inject</ignoredUsedUndeclaredDependency>
<ignoredUsedUndeclaredDependency>com.amazonaws</ignoredUsedUndeclaredDependency>
<ignoredUsedUndeclaredDependency>org.bouncycastle</ignoredUsedUndeclaredDependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package de.adorsys.datasafe.business.impl.e2e;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.google.common.io.Resources;
import de.adorsys.datasafe.business.impl.service.DefaultDatasafeServices;
import de.adorsys.datasafe.encrypiton.api.types.UserID;
import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth;
import de.adorsys.datasafe.encrypiton.api.types.encryption.MutableEncryptionConfig;
import de.adorsys.datasafe.storage.api.StorageService;
import de.adorsys.datasafe.teststorage.WithStorageProvider;
import de.adorsys.datasafe.types.api.actions.ListRequest;
Expand All @@ -21,11 +27,11 @@
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.shaded.com.google.common.collect.ImmutableSet;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.UnrecoverableKeyException;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -54,6 +60,7 @@ class BasicFunctionalityIT extends BaseE2EIT {

private StorageService storage;
private Uri location;
private static ObjectMapper mapper = createMapper();


/**
Expand Down Expand Up @@ -277,6 +284,37 @@ void testWriteToPrivateListPrivateReadPrivateAndSendToAndReadFromInbox(
removeFromPrivate(jane, privateJane.getResource().asPrivate());
removeFromInbox(john, inboxJohn.getResource().asPrivate());
}
@ParameterizedTest
@MethodSource("allStorages")
void testWriteToPrivateListPrivateReadPrivateAndSendToAndReadFromInboxCustom( WithStorageProvider.StorageDescriptor descriptor) {
String yamlFixture = "config/mutable.yaml";
customInit(descriptor, yamlFixture);

registerJohnAndJane();

writeDataToPrivate(jane, PRIVATE_FILE_PATH, MESSAGE_ONE);

AbsoluteLocation<ResolvedResource> privateJane = getFirstFileInPrivate(jane);

String privateContentJane = readPrivateUsingPrivateKey(jane, privateJane.getResource().asPrivate());

sendToInbox(jane, john.getUserID(), SHARED_FILE_PATH, privateContentJane);

AbsoluteLocation<ResolvedResource> inboxJohn = getFirstFileInInbox(john);

String result = readInboxUsingPrivateKey(john, inboxJohn.getResource().asPrivate());

assertThat(result).isEqualTo(MESSAGE_ONE);
assertThat(privateJane.getResource().asPrivate().decryptedPath())
.extracting(Uri::toASCIIString).isEqualTo(PRIVATE_FILE_PATH);
assertThat(privateJane.getResource().asPrivate().encryptedPath())
.extracting(Uri::toASCIIString).isNotEqualTo(PRIVATE_FILE_PATH);
validateInboxStructAndEncryption(inboxJohn);
validatePrivateStructAndEncryption(privateJane);

removeFromPrivate(jane, privateJane.getResource().asPrivate());
removeFromInbox(john, inboxJohn.getResource().asPrivate());
}

@ParameterizedTest
@MethodSource("allStorages")
Expand Down Expand Up @@ -387,4 +425,28 @@ private void init(WithStorageProvider.StorageDescriptor descriptor) {
this.location = descriptor.getLocation();
this.storage = descriptor.getStorageService().get();
}
private void customInit(WithStorageProvider.StorageDescriptor descriptor, String yamlFixture) {
MutableEncryptionConfig config = readResource(mapper, yamlFixture, MutableEncryptionConfig.class);
DefaultDatasafeServices datasafeServices = DatasafeServicesProvider
.customConfigDatasafeServices(descriptor.getStorageService().get(), descriptor.getLocation(), config);
initialize(DatasafeServicesProvider.dfsConfig(descriptor.getLocation()), datasafeServices);

this.location = descriptor.getLocation();
this.storage = descriptor.getStorageService().get();
}

private static <T> T readResource(ObjectMapper mapper, String path, Class<T> type) {
try (Reader reader = Resources.asCharSource(Resources.getResource(path), StandardCharsets.UTF_8).openStream()) {
return mapper.readValue(reader, type);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}

private static ObjectMapper createMapper() {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory().enable(YAMLGenerator.Feature.MINIMIZE_QUOTES));
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return mapper;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import de.adorsys.datasafe.business.impl.service.VersionedDatasafeServices;
import de.adorsys.datasafe.directory.api.config.DFSConfig;
import de.adorsys.datasafe.directory.impl.profile.config.DefaultDFSConfig;
import de.adorsys.datasafe.encrypiton.api.types.encryption.MutableEncryptionConfig;
import de.adorsys.datasafe.storage.api.StorageService;
import de.adorsys.datasafe.types.api.resource.Uri;
import de.adorsys.datasafe.types.api.types.ReadStorePassword;
Expand All @@ -26,6 +27,14 @@ public static DefaultDatasafeServices defaultDatasafeServices(StorageService sto
.storage(storageService)
.build();
}
public static DefaultDatasafeServices customConfigDatasafeServices(StorageService storageService, Uri systemRoot, MutableEncryptionConfig config) {
return DaggerDefaultDatasafeServices
.builder()
.config(dfsConfig(systemRoot))
.encryption(config.toEncryptionConfig())
.storage(storageService)
.build();
}

public static VersionedDatasafeServices versionedDatasafeServices(StorageService storageService, Uri systemRoot) {
return DaggerVersionedDatasafeServices
Expand Down
30 changes: 30 additions & 0 deletions datasafe-business/src/test/resources/config/mutable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
keystore:
type: BCFKS
encryptionAlgo: AES256_KWP
pbkdf:
scrypt:
cost: 16384
blockSize: 8
parallelization: 1
saltLength: 16
macAlgo: HmacSHA3_512
passwordKeysAlgo: PBEWithHmacSHA256AndAES_256
keys:
encKeyNumber: 1
signKeyNumber: 2
secret:
algo: AES
size: 256
encrypting:
algo: RSA
size: 2048
sigAlgo: SHA256withRSA
# curve:
signing:
algo: RSA
size: 2048
sigAlgo: SHA256withRSA
# curve:
cms:
algo: AES256_GCM
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth;
import de.adorsys.datasafe.types.api.resource.BasePrivateResource;
import de.adorsys.datasafe.types.api.resource.BasePublicResource;
import de.adorsys.datasafe.types.api.resource.Uri;
import de.adorsys.datasafe.types.api.shared.BaseMockitoTest;
import de.adorsys.datasafe.types.api.utils.ReadKeyPasswordTestFactory;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -35,4 +36,10 @@ void publicAccessFor() {
BasePublicResource.forAbsolutePublic(ABSOLUTE_BUCKET).getResource()).location().asURI()
).asString().isEqualTo(ABSOLUTE_BUCKET);
}
@Test
void withSystemAccess() {
assertThat(bucketAccessService.withSystemAccess(
BasePublicResource.forAbsolutePublic(ABSOLUTE_BUCKET)).location().asURI()
).asString().isEqualTo(ABSOLUTE_BUCKET);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package de.adorsys.datasafe.directory.impl.profile.dfs;

import de.adorsys.datasafe.directory.api.types.CreateUserPublicProfile;
import de.adorsys.datasafe.directory.impl.profile.config.DefaultDFSConfig;
import de.adorsys.datasafe.encrypiton.api.types.UserID;
import de.adorsys.datasafe.types.api.resource.Uri;
import de.adorsys.datasafe.types.api.types.ReadStorePassword;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -38,5 +41,14 @@ public void checkUriWithSlash() {
Uri result2 = DefaultDFSConfig.addTrailingSlashIfNeeded(result1);
Assertions.assertEquals(new Uri(uriString + "/"), result2);
}
@Test
@SneakyThrows
public void createDefaultPublicTemplate() {
ReadStorePassword systemPassword = new ReadStorePassword("storePassword");
DefaultDFSConfig config = new DefaultDFSConfig(new URI(uriString), systemPassword);
CreateUserPublicProfile template = config.defaultPublicTemplate(new UserID("user1"));
Assertions.assertEquals(new UserID("user1"), template.getId());

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ KeyCreationConfig.EncryptingKeyCreationCfg toEncryptingKeyCreationCfg() {
builder.sigAlgo(sigAlgo);
}

if (null != curve) {

builder.curve(curve);
}


return builder.build();
}
Expand Down Expand Up @@ -231,9 +231,9 @@ KeyCreationConfig.SigningKeyCreationCfg toSigningKeyCreationCfg() {
builder.sigAlgo(sigAlgo);
}

if (null != curve) {

builder.curve(curve);
}


return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package de.adorsys.datasafe.encrypiton.impl.cmsencryption;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.google.common.io.ByteStreams;
import com.google.common.io.Resources;
import de.adorsys.datasafe.encrypiton.api.cmsencryption.CMSEncryptionService;
import de.adorsys.datasafe.encrypiton.api.keystore.KeyStoreService;
import de.adorsys.datasafe.encrypiton.api.types.encryption.CmsEncryptionConfig;
Expand Down Expand Up @@ -28,17 +33,10 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
Expand Down Expand Up @@ -145,6 +143,48 @@ void cmsStreamEnvelopeEncryptAndDecryptTest() {

assertThat(TEST_MESSAGE_CONTENT).isEqualTo(new String(actualResult));
}
@Test
@SneakyThrows
void cmsStreamEnvelopeEncryptAndDecryptTestCustom() {
ReadKeyPassword readKeyPassword = ReadKeyPasswordTestFactory.getForString("readkeypassword");
ReadStorePassword readStorePassword = new ReadStorePassword("readstorepassword");

KeyStoreAuth keyStoreAuth = new KeyStoreAuth(readStorePassword, readKeyPassword);
KeyCreationConfig config = KeyCreationConfig.builder()
.signing(KeyCreationConfig.SigningKeyCreationCfg.builder().algo("RSA").size(2048).sigAlgo( "SHA256withRSA").curve(null).build())
.encrypting(KeyCreationConfig.EncryptingKeyCreationCfg.builder().algo("RSA").size(2048).sigAlgo("SHA256withRSA").curve(null).build())
.build();

KeyStore keyStore = keyStoreService.createKeyStore(keyStoreAuth, config);
KeyStoreAccess keyStoreAccess = new KeyStoreAccess(keyStore, keyStoreAuth);

PublicKeyIDWithPublicKey publicKeyIDWithPublicKey = keyStoreService.getPublicKeys(keyStoreAccess).get(0);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

KeyStoreAccess keyStoreAccessSender = getKeyStoreAccess("Sender");

OutputStream encryptionStream = cmsEncryptionService.buildEncryptionOutputStream(
outputStream,
Collections.singleton(new PublicKeyIDWithPublicKey(
publicKeyIDWithPublicKey.getKeyID(),
publicKeyIDWithPublicKey.getPublicKey()
)),
getKeyPair(keyStoreAccessSender, "Sender")
);

encryptionStream.write(TEST_MESSAGE_CONTENT.getBytes());
encryptionStream.close();

byte[] byteArray = outputStream.toByteArray();

ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
InputStream decryptionStream = cmsEncryptionService.buildDecryptionInputStream(
inputStream, keyIds -> getKeys(keyIds, keyStoreAccess)
);
byte[] actualResult = toByteArray(decryptionStream);

assertThat(TEST_MESSAGE_CONTENT).isEqualTo(new String(actualResult));
}

@Test
@SneakyThrows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class KeyStoreAuthTest extends BaseMockitoTest {
@Test
void noPasswords() {
KeyStoreAuth keyStoreAuth = new KeyStoreAuth(null, null);
assertThrows(KeyStoreAuthException.class, () -> keyStoreAuth.getReadKeyPassword());
assertThrows(KeyStoreAuthException.class, () -> keyStoreAuth.getReadKeyPassword());
assertThrows(KeyStoreAuthException.class, keyStoreAuth::getReadKeyPassword);
assertThrows(KeyStoreAuthException.class, keyStoreAuth::getReadStorePassword);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import javax.crypto.SecretKey;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

Expand Down Expand Up @@ -69,7 +70,28 @@ void createKeyStoreEmptyConfig() throws Exception {
// One additional secret key being generated for path encryption and one for private doc encryption.
Assertions.assertEquals(4, list.size());
}
@Test
void serializeAndDeserializeKeyStore() {
KeyStore keyStore = keyStoreService.createKeyStore(keyStoreAuth, KeyCreationConfig.builder().build());
ReadStorePassword password = new ReadStorePassword("storepass");

byte[] serializedKeyStore = keyStoreService.serialize(keyStore, password);
KeyStore deserializedKeyStore = keyStoreService.deserialize(serializedKeyStore, password);

Assertions.assertEquals(keyStore.getType(), deserializedKeyStore.getType());
Assertions.assertEquals(keyStore.getProvider(), deserializedKeyStore.getProvider());
}

@Test
void addPasswordBasedSecretKey() {
KeyStore keyStore = keyStoreService.createKeyStore(keyStoreAuth, KeyCreationConfig.builder().build());
KeyStoreAccess keyStoreAccess = new KeyStoreAccess(keyStore, keyStoreAuth);

keyStoreService.addPasswordBasedSecretKey(keyStoreAccess, "alias", "secret".toCharArray());
SecretKey secretKey = keyStoreService.getSecretKey(keyStoreAccess, new KeyID("alias"));

Assertions.assertEquals("secret", new String(secretKey.getEncoded()));
}
@Test
void getPublicKeys() {
KeyStore keyStore = keyStoreService.createKeyStore(keyStoreAuth, KeyCreationConfig.builder().build());
Expand Down Expand Up @@ -119,4 +141,15 @@ void getSecretKey() {
SecretKey secretKey = keyStoreService.getSecretKey(keyStoreAccess, keyID);
Assertions.assertNotNull(secretKey);
}
@Test
void removeKey() {
KeyCreationConfig config = KeyCreationConfig.builder().signKeyNumber(1).encKeyNumber(0).build();
KeyStore keyStore = keyStoreService.createKeyStore(keyStoreAuth, config);
KeyStoreAccess keyStoreAccess = new KeyStoreAccess(keyStore, keyStoreAuth);

KeyID keyID = KeystoreUtil.keyIdByPrefix(keyStore, DOCUMENT_KEY_ID_PREFIX);
keyStoreService.removeKey(keyStoreAccess, keyID.getValue());
SecretKey secretKey = keyStoreService.getSecretKey(keyStoreAccess, keyID);
Assertions.assertNull(secretKey);
}
}
Loading

0 comments on commit 26674d8

Please sign in to comment.