Skip to content

Commit

Permalink
Merge pull request #234 from adorsys/add_ECDH
Browse files Browse the repository at this point in the history
Add ecdh
  • Loading branch information
francis-pouatcha committed May 28, 2024
2 parents 3040e57 + fc90a4d commit bd4ab88
Show file tree
Hide file tree
Showing 45 changed files with 447 additions and 152 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[![Build Status](https://travis-ci.com/adorsys/datasafe.svg?branch=develop)](https://travis-ci.com/adorsys/datasafe)
[![codecov](https://codecov.io/gh/adorsys/datasafe/branch/develop/graph/badge.svg)](https://codecov.io/gh/adorsys/datasafe)
[![Maintainability](https://api.codeclimate.com/v1/badges/06ae7d4cafc3012cee85/maintainability)](https://codeclimate.com/github/adorsys/datasafe/maintainability)
[![Maintainability](https://codeclimate.com/github/adorsys/datasafe.png)](https://codeclimate.com/github/adorsys/datasafe/maintainability)

# Secure, Encrypted and Versioned Data Storage Library

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import de.adorsys.datasafe.types.api.actions.ListRequest;
import de.adorsys.datasafe.types.api.actions.ReadRequest;
import de.adorsys.datasafe.types.api.actions.RemoveRequest;
import de.adorsys.datasafe.types.api.actions.WriteInboxRequest;
import de.adorsys.datasafe.types.api.actions.WriteRequest;
import de.adorsys.datasafe.types.api.resource.AbsoluteLocation;
import de.adorsys.datasafe.types.api.resource.BasePrivateResource;
Expand Down Expand Up @@ -117,9 +118,9 @@ protected void writeDataToPrivate(UserIDAuth auth, String path, String data) {
}

@SneakyThrows
protected void writeDataToInbox(UserIDAuth auth, String path, String data) {
protected void writeDataToInbox(UserIDAuth owner, UserIDAuth auth, String path, String data) {
try (OutputStream stream = writeToInbox.write(
WriteRequest.forDefaultPublic(Collections.singleton(auth.getUserID()), path)
WriteInboxRequest.forDefaultPublic(owner, Collections.singleton(auth.getUserID()), path)
)) {

stream.write(data.getBytes(UTF_8));
Expand Down Expand Up @@ -191,9 +192,9 @@ protected void registerJohnAndJane() {
}

@SneakyThrows
protected void sendToInbox(UserID to, String filename, String data) {
protected void sendToInbox(UserIDAuth from, UserID to, String filename, String data) {
try (OutputStream stream = writeToInbox.write(
WriteRequest.forDefaultPublic(Collections.singleton(to), "./" + filename)
WriteInboxRequest.forDefaultPublic(from, Collections.singleton(to), "./" + filename)
)) {
stream.write(data.getBytes());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import de.adorsys.datasafe.types.api.actions.ListRequest;
import de.adorsys.datasafe.types.api.actions.ReadRequest;
import de.adorsys.datasafe.types.api.actions.RemoveRequest;
import de.adorsys.datasafe.types.api.actions.WriteInboxRequest;
import de.adorsys.datasafe.types.api.actions.WriteRequest;
import de.adorsys.datasafe.types.api.global.Version;
import de.adorsys.datasafe.types.api.resource.AbsoluteLocation;
Expand Down Expand Up @@ -194,12 +195,15 @@ void testUserIsRemovedWithFiles(WithStorageProvider.StorageDescriptor descriptor
void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descriptor) {
init(descriptor);

UserIDAuth owner = registerUser("owner");

UserIDAuth john = registerUser("john");
UserIDAuth jane = registerUser("jane");
UserIDAuth jamie = registerUser("jamie");

String multiShareFile = "multishare.txt";
try (OutputStream os = writeToInbox.write(WriteRequest.forDefaultPublic(
try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic(
owner,
ImmutableSet.of(john.getUserID(), jane.getUserID(), jamie.getUserID()),
multiShareFile))
) {
Expand All @@ -217,14 +221,17 @@ void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descrip
void testMultipleRecipientsSharingLargeChunk(WithStorageProvider.StorageDescriptor descriptor) {
init(descriptor);

UserIDAuth owner = registerUser("owner");

UserIDAuth john = registerUser("john");
UserIDAuth jane = registerUser("jane");
UserIDAuth jamie = registerUser("jamie");

String multiShareFile = "multishare.txt";
byte[] bytes = new byte[LARGE_SIZE];
ThreadLocalRandom.current().nextBytes(bytes);
try (OutputStream os = writeToInbox.write(WriteRequest.forDefaultPublic(
try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic(
owner,
ImmutableSet.of(john.getUserID(), jane.getUserID(), jamie.getUserID()),
multiShareFile))
) {
Expand Down Expand Up @@ -253,7 +260,7 @@ void testWriteToPrivateListPrivateReadPrivateAndSendToAndReadFromInbox(

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

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

AbsoluteLocation<ResolvedResource> inboxJohn = getFirstFileInInbox(john);

Expand Down Expand Up @@ -308,9 +315,9 @@ void listingInboxValidation(WithStorageProvider.StorageDescriptor descriptor) {

registerJohnAndJane();

writeDataToInbox(jane, "root.file", MESSAGE_ONE);
writeDataToInbox(jane, "level1/file", MESSAGE_ONE);
writeDataToInbox(jane, "level1/level2/file", MESSAGE_ONE);
writeDataToInbox(john, jane, "root.file", MESSAGE_ONE);
writeDataToInbox(john, jane, "level1/file", MESSAGE_ONE);
writeDataToInbox(john, jane, "level1/level2/file", MESSAGE_ONE);

assertInboxSpaceList(jane, "", "root.file", "level1/file", "level1/level2/file");
assertInboxSpaceList(jane, "./", "root.file", "level1/file", "level1/level2/file");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ void listingPrivatePathWithUnicode(WithStorageProvider.StorageDescriptor descrip
void readInboxContentWithUnicodeUsingUnicodePath(WithStorageProvider.StorageDescriptor descriptor) {
init(descriptor);

john = registerUser("john");
jane = registerUser("jane");


String unicodeMessage = "привет мир!";
writeDataToInbox(jane, " привет/prüfungsdokument=/файл:&? с пробелом.док", unicodeMessage);
writeDataToInbox(john, jane, " привет/prüfungsdokument=/файл:&? с пробелом.док", unicodeMessage);

String inboxContentJane = readInboxUsingPrivateKey(
jane,
Expand All @@ -107,9 +108,9 @@ void listingInboxPathWithUnicode(WithStorageProvider.StorageDescriptor descripto

registerJohnAndJane();

writeDataToInbox(jane, "prüfungsdokument.doc+doc", MESSAGE_ONE);
writeDataToInbox(jane, "уровень1/?файл+doc", MESSAGE_ONE);
writeDataToInbox(jane, "уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE);
writeDataToInbox(john, jane, "prüfungsdokument.doc+doc", MESSAGE_ONE);
writeDataToInbox(john, jane, "уровень1/?файл+doc", MESSAGE_ONE);
writeDataToInbox(john, jane, "уровень1/уровень 2=+/&файл пробел+плюс", MESSAGE_ONE);

assertInboxSpaceList(jane, "", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс");
assertInboxSpaceList(jane, "./", "prüfungsdokument.doc+doc", "уровень1/?файл+doc", "уровень1/уровень 2=+/&файл пробел+плюс");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import de.adorsys.datasafe.encrypiton.api.types.UserIDAuth;
import de.adorsys.datasafe.teststorage.WithStorageProvider;
import de.adorsys.datasafe.types.api.actions.ReadRequest;
import de.adorsys.datasafe.types.api.actions.WriteRequest;
import de.adorsys.datasafe.types.api.actions.WriteInboxRequest;
import de.adorsys.datasafe.types.api.resource.AbsoluteLocation;
import de.adorsys.datasafe.types.api.resource.ResolvedResource;
import de.adorsys.datasafe.types.api.resource.Uri;
Expand Down Expand Up @@ -60,12 +60,14 @@ void testUserIsRemovedWithFiles(WithStorageProvider.StorageDescriptor descriptor
void testMultipleRecipientsSharing(WithStorageProvider.StorageDescriptor descriptor) {
init(descriptor);

UserIDAuth sender = registerUser("sender");

UserIDAuth john = registerUser("john");
UserIDAuth jane = registerUser("jane");
UserIDAuth jamie = registerUser("jamie");

String multiShareFile = "multishare.txt";
multishareFiles(john, jane, jamie, multiShareFile);
multishareFiles(sender, john, jane, jamie, multiShareFile);

Stream.of(john, jane, jamie).forEach(
it -> checkUpdatedCredsWorkAndOldDont(
Expand Down Expand Up @@ -102,7 +104,7 @@ void testWriteToPrivateListPrivateReadPrivateAndSendToAndReadFromInbox(

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

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

AbsoluteLocation<ResolvedResource> inboxJohn = getFirstFileInInbox(john);

Expand Down Expand Up @@ -188,8 +190,9 @@ void listingValidation(WithStorageProvider.StorageDescriptor descriptor) {
}

@SneakyThrows
private void multishareFiles(UserIDAuth userOne, UserIDAuth userTwo, UserIDAuth userThree, String multiShareFile) {
try (OutputStream os = writeToInbox.write(WriteRequest.forDefaultPublic(
private void multishareFiles(UserIDAuth sender, UserIDAuth userOne, UserIDAuth userTwo, UserIDAuth userThree, String multiShareFile) {
try (OutputStream os = writeToInbox.write(WriteInboxRequest.forDefaultPublic(
sender,
ImmutableSet.of(userOne.getUserID(), userTwo.getUserID(), userThree.getUserID()),
multiShareFile))
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import de.adorsys.datasafe.business.impl.service.DefaultDatasafeServices;
import de.adorsys.datasafe.types.api.actions.ListRequest;
import de.adorsys.datasafe.types.api.actions.ReadRequest;
import de.adorsys.datasafe.types.api.actions.WriteInboxRequest;
import de.adorsys.datasafe.types.api.actions.WriteRequest;
import de.adorsys.datasafe.types.api.resource.AbsoluteLocation;
import de.adorsys.datasafe.types.api.resource.ResolvedResource;
Expand Down Expand Up @@ -82,7 +83,7 @@ void testPrivateDocumentContentTamperResistance() {
@SneakyThrows
void testInboxDocumentContentTamperResistance() {
try (OutputStream os = writeToInbox.write(
WriteRequest.forDefaultPublic(Collections.singleton(john.getUserID()), FILENAME))
WriteInboxRequest.forDefaultPublic(jane, Collections.singleton(john.getUserID()), FILENAME))
) {
os.write(FILE_TEXT.getBytes(StandardCharsets.UTF_8));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.google.common.io.ByteStreams;
import com.google.common.io.MoreFiles;
import de.adorsys.datasafe.encrypiton.api.types.UserID;
import de.adorsys.datasafe.types.api.actions.WriteRequest;
import de.adorsys.datasafe.types.api.actions.WriteInboxRequest;
import lombok.SneakyThrows;
import picocli.CommandLine;

Expand Down Expand Up @@ -41,7 +41,8 @@ public class Share implements Runnable {
public void run() {
try (OutputStream os = inbox.getCli().datasafe().inboxService()
.write(
WriteRequest.forDefaultPublic(
WriteInboxRequest.forDefaultPublic(
inbox.getCli().auth(),
recipients.stream().map(UserID::new).collect(Collectors.toSet()),
filename
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import de.adorsys.datasafe.types.api.types.ReadKeyPassword;

import java.security.Key;
import java.security.KeyPair;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -42,4 +43,6 @@ public interface DocumentKeyStoreOperations {
* @return Key aliases from keystore.
*/
Set<String> readAliases(UserIDAuth forUser);

KeyPair getKeyPair(UserIDAuth forUser);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import de.adorsys.datasafe.encrypiton.api.types.keystore.SecretKeyIDWithKey;

import java.security.Key;
import java.security.KeyPair;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -45,4 +46,6 @@ public interface PrivateKeyService {
* {@code keyIds} that are missing - they are silently ignored and not returned in result.
*/
Map<String, Key> keysByIds(UserIDAuth forUser, Set<String> keyIds);

KeyPair getKeyPair(UserIDAuth forUser);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import javax.crypto.SecretKey;
import javax.inject.Inject;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
import java.util.Collection;
Expand Down Expand Up @@ -100,6 +101,11 @@ public Map<String, Key> keysByIds(UserIDAuth forUser, Set<String> keyIds) {
);
}

@Override
public KeyPair getKeyPair(UserIDAuth forUser) {
return keyStoreOper.getKeyPair(forUser);
}

protected SecretKeyIDWithKey keyByPrefix(UserIDAuth forUser, String prefix) {
return keyByPrefix(
forUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import javax.inject.Inject;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -103,6 +105,16 @@ public void updateReadKeyPassword(UserIDAuth forUser, ReadKeyPassword newPasswor
genericOper.updateReadKeyPassword(keyStore(forUser), location, forUser, newPassword);
}

@Override
@SneakyThrows
public KeyPair getKeyPair(UserIDAuth forUser) {
KeyStore keyStore = keyStore(forUser);
KeyStoreAuth auth = keystoreAuth(forUser, forUser.getReadKeyPassword());
List<PublicKeyIDWithPublicKey> publicKeys = keyStoreService.getPublicKeys(new KeyStoreAccess(keyStore, auth));
Key key = genericOper.getKey(() -> keyStore(forUser), forUser, publicKeys.get(0).getKeyID().getValue());
return new KeyPair(publicKeys.get(0).getPublicKey(), (PrivateKey) key);
}

private AbsoluteLocation<PrivateResource> keystoreLocationWithAccess(UserIDAuth forUser) {
return this.access.privateAccessFor(
forUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
Expand All @@ -25,7 +26,8 @@ public interface CMSEncryptionService {
* @return Encrypted stream that wraps {@code dataContentStream}
* @apiNote Closes underlying stream when result is closed
*/
OutputStream buildEncryptionOutputStream(OutputStream dataContentStream, Set<PublicKeyIDWithPublicKey> publicKeys);
OutputStream buildEncryptionOutputStream(OutputStream dataContentStream, Set<PublicKeyIDWithPublicKey> publicKeys,
KeyPair senderKeyPair);

/**
* Builds symmetrically encrypted stream.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import de.adorsys.datasafe.types.api.resource.WithCallback;

import java.io.OutputStream;
import java.security.KeyPair;
import java.util.Map;

/**
Expand All @@ -22,7 +23,7 @@ public interface EncryptedDocumentWriteService {
* @param recipientsWithInbox Map of (recipient public key - recipients' inbox) of users with whom to share file.
* @return Sink where you can send unencrypted data that will be encrypted and stored
*/
OutputStream write(Map<PublicKeyIDWithPublicKey, AbsoluteLocation> recipientsWithInbox);
OutputStream write(Map<PublicKeyIDWithPublicKey, AbsoluteLocation> recipientsWithInbox, KeyPair senderKeyPair);

/**
* Writes and encrypts data using symmetric cryptography.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,32 @@ public static class SecretKeyCreationCfg {
public static class EncryptingKeyCreationCfg {

@Builder.Default
private final String algo = "RSA";
private final String algo = "ECDH";

@Builder.Default
private final int size = 2048;
private final int size = 256;

@Builder.Default
private final String sigAlgo = "SHA256withECDSA";

@Builder.Default
private final String sigAlgo = "SHA256withRSA";
private final String curve = "secp256r1";
}

@Getter
@Builder
public static class SigningKeyCreationCfg {

@Builder.Default
private final String algo = "RSA";
private final String algo = "ECDH";

@Builder.Default
private final int size = 256;

@Builder.Default
private final int size = 2048;
private final String sigAlgo = "SHA256withECDSA";

@Builder.Default
private final String sigAlgo = "SHA256withRSA";
private final String curve = "secp256r1";
}
}
Loading

0 comments on commit bd4ab88

Please sign in to comment.