From e187ef1cbd606004cbe32ca1465068b5b4a01d24 Mon Sep 17 00:00:00 2001 From: JeremyTubongbanua Date: Thu, 13 Oct 2022 11:06:42 -0400 Subject: [PATCH 1/3] feat: PrivateHiddenKey interface methods `AtClient.java` --- .../src/main/java/org/atsign/client/api/AtClient.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/at_client/src/main/java/org/atsign/client/api/AtClient.java b/at_client/src/main/java/org/atsign/client/api/AtClient.java index fb89b7b2..24c231f8 100644 --- a/at_client/src/main/java/org/atsign/client/api/AtClient.java +++ b/at_client/src/main/java/org/atsign/client/api/AtClient.java @@ -4,6 +4,7 @@ import org.atsign.client.api.impl.connections.AtRootConnection; import org.atsign.client.api.impl.connections.DefaultAtConnectionFactory; import org.atsign.client.api.impl.events.SimpleAtEventBus; +import org.atsign.client.api.impl.notification.NotificationParams; import org.atsign.client.api.impl.secondaries.RemoteSecondary; import org.atsign.common.AtSign; import org.atsign.common.AtException; @@ -16,6 +17,8 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +import javax.management.remote.NotificationResult; + /** * The primary interface of the AtSign client library. */ @@ -156,9 +159,15 @@ static AtClient withRemoteSecondary(Secondary.Address remoteSecondaryAddress, At CompletableFuture put(PublicKey publicKey, String value); CompletableFuture delete(PublicKey publicKey); + CompletableFuture get(PrivateHiddenKey privateHiddenKey); + CompletableFuture getBinary(PrivateHiddenKey privateHiddenKey); + CompletableFuture put(PrivateHiddenKey privateHiddenKey, String value); + CompletableFuture delete(PrivateHiddenKey privateHiddenKey); + CompletableFuture put(SharedKey sharedKey, byte[] value); CompletableFuture put(SelfKey selfKey, byte[] value); CompletableFuture put(PublicKey publicKey, byte[] value); + CompletableFuture put(PrivateHiddenKey privateHiddenKey, byte[] value); CompletableFuture> getAtKeys(String regex); } From 03fdd1a62018a584fbc0abf8e3a45b3d0df3f923 Mon Sep 17 00:00:00 2001 From: JeremyTubongbanua Date: Thu, 13 Oct 2022 11:08:31 -0400 Subject: [PATCH 2/3] feat: PrivateHiddenKey implementation `AtClientImpl.java` (unfinished binary methods) --- .../client/api/impl/clients/AtClientImpl.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/at_client/src/main/java/org/atsign/client/api/impl/clients/AtClientImpl.java b/at_client/src/main/java/org/atsign/client/api/impl/clients/AtClientImpl.java index 93ac95db..0aaac0ba 100644 --- a/at_client/src/main/java/org/atsign/client/api/impl/clients/AtClientImpl.java +++ b/at_client/src/main/java/org/atsign/client/api/impl/clients/AtClientImpl.java @@ -299,6 +299,61 @@ public CompletableFuture put(PublicKey publicKey, byte[] value) { }); } + @Override + public CompletableFuture put(PrivateHiddenKey privateHiddenKey, String value) { + return CompletableFuture.supplyAsync(() -> { + try { + return _put(privateHiddenKey, value); + } catch (Exception e) { + throw new CompletionException(e); + } + }); + } + + @Override + public CompletableFuture get(PrivateHiddenKey privateHiddenKey) { + return CompletableFuture.supplyAsync(() -> { + try { + return _get(privateHiddenKey); + } catch (Exception e) { + throw new CompletionException(e); + } + }); + } + + @Override + public CompletableFuture getBinary(PrivateHiddenKey privateHiddenKey) { + return CompletableFuture.supplyAsync(() -> { + try { + return _getBinary(privateHiddenKey); + } catch (Exception e) { + throw new CompletionException(e); + } + }); + } + + @Override + public CompletableFuture delete(PrivateHiddenKey privateHiddenKey) { + return CompletableFuture.supplyAsync(() -> { + try { + return _delete(privateHiddenKey); + } catch (Exception e) { + throw new CompletionException(e); + } + }); + } + + @Override + public CompletableFuture put(PrivateHiddenKey privateHiddenKey, byte[] value) { + return CompletableFuture.supplyAsync(() -> { + try { + return _put(privateHiddenKey, value); + } catch (Exception e) { + throw new CompletionException(e); + } + }); + } + @Override public CompletableFuture> getAtKeys(String regex) { return CompletableFuture.supplyAsync(() -> { @@ -558,13 +613,88 @@ private String _delete(PublicKey key) throws AtException { return rawResponse.toString(); } + private String _put(PrivateHiddenKey key, String value) throws AtException { + // 1. generate dataSignature + key.metadata.dataSignature = generateSignature(value); + + // 2. encrypt data with self encryption key + String cipherText; + try { + cipherText = EncryptionUtil.aesEncryptToBase64(value, keys.get(KeysUtil.selfEncryptionKeyName)); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException e) { + throw new AtException("Failed to encrypt value with self encryption key : " + e.getMessage(), e); + } + + // 3. update secondary + UpdateVerbBuilder builder = new UpdateVerbBuilder(); + builder.with(key, cipherText); + String command = builder.build(); + Secondary.Response response = secondary.executeCommand(command, true); + if(response.isError) { + throw new AtException("Failed to update " + key + " : " + response.error); + } + return response.toString(); + } + + private String _get(PrivateHiddenKey key) throws AtException { + // 1. build command + String command = null; + LlookupVerbBuilder builder = new LlookupVerbBuilder(); + builder.with(key, LlookupVerbBuilder.Type.ALL); + command = builder.build(); + + // 2. run the command + Secondary.Response llookupAllRawResponse = secondary.executeCommand(command, false); + if (llookupAllRawResponse.isError) { + throw new AtException("Failed to " + command + " : " + llookupAllRawResponse.error); + } + + // 3. transform the data to a LlookupAllResponse object + LlookupAllResponse model = null; + LlookupAllResponseTransformer transformer = new LlookupAllResponseTransformer(); + model = transformer.transform(llookupAllRawResponse); + + // 4. update key object metadata + Metadata fetchedMetadata = Metadata.fromModel(model.metaData); + key.metadata = Metadata.squash(fetchedMetadata, key.metadata); + key.metadata.isCached = model.key.contains("cached:"); + + // 5. decrypt data with self encryption key + String decryptedValue; + try { + decryptedValue = EncryptionUtil.aesDecryptFromBase64(model.data, keys.get(KeysUtil.selfEncryptionKeyName)); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException e) { + throw new AtException("Failed to decrypt value with self encryption key : " + e.getMessage(), e); + } + + // 6. return the AtValue + return decryptedValue; + } + + private String _delete(PrivateHiddenKey key) throws AtException { + // 1. build command + String command = null; + DeleteVerbBuilder builder = new DeleteVerbBuilder(); + builder.with(key); + command = builder.build(); + + // 2. run command + Secondary.Response rawResponse = secondary.executeCommand(command, false); + if(rawResponse.isError) { + throw new AtException(rawResponse.error); + } + return rawResponse.toString(); + } + private byte[] _getBinary(SharedKey sharedKey) throws AtException {throw new RuntimeException("Not Implemented");} private byte[] _getBinary(SelfKey selfKey) throws AtException {throw new RuntimeException("Not Implemented");} private byte[] _getBinary(PublicKey publicKey) throws AtException {throw new RuntimeException("Not Implemented");} + private byte[] _getBinary(PrivateHiddenKey privateHiddenKey) throws AtException {throw new RuntimeException("Not Implemented");} private String _put(SharedKey sharedKey, byte[] value) throws AtException {throw new RuntimeException("Not Implemented");} private String _put(SelfKey selfKey, byte[] value) throws AtException {throw new RuntimeException("Not Implemented");} private String _put(PublicKey publicKey, byte[] value) throws AtException {throw new RuntimeException("Not Implemented");} + private String _put(PrivateHiddenKey privateHiddenKey, byte[] value) throws AtException {throw new RuntimeException("Not Implemented");} private List _getAtKeys(String regex) throws AtException, ParseException { ScanVerbBuilder scanVerbBuilder = new ScanVerbBuilder(); From 8804071349332af513949437562291b69357d02a Mon Sep 17 00:00:00 2001 From: JeremyTubongbanua Date: Thu, 13 Oct 2022 11:18:28 -0400 Subject: [PATCH 3/3] chore: remove non-existent imports --- at_client/src/main/java/org/atsign/client/api/AtClient.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/at_client/src/main/java/org/atsign/client/api/AtClient.java b/at_client/src/main/java/org/atsign/client/api/AtClient.java index 24c231f8..9e3aaa42 100644 --- a/at_client/src/main/java/org/atsign/client/api/AtClient.java +++ b/at_client/src/main/java/org/atsign/client/api/AtClient.java @@ -4,7 +4,6 @@ import org.atsign.client.api.impl.connections.AtRootConnection; import org.atsign.client.api.impl.connections.DefaultAtConnectionFactory; import org.atsign.client.api.impl.events.SimpleAtEventBus; -import org.atsign.client.api.impl.notification.NotificationParams; import org.atsign.client.api.impl.secondaries.RemoteSecondary; import org.atsign.common.AtSign; import org.atsign.common.AtException; @@ -17,8 +16,6 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; -import javax.management.remote.NotificationResult; - /** * The primary interface of the AtSign client library. */