This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 35f042e2d74 Hyperledger Aries - connectionless proofs (#8741) 35f042e2d74 is described below commit 35f042e2d74904418bd7c261290c64f27456854a Author: vchernetskyi993 <36628451+vchernetskyi...@users.noreply.github.com> AuthorDate: Wed Nov 23 07:28:46 2022 +0200 Hyperledger Aries - connectionless proofs (#8741) * added create-request & get-did-endpoint * added create-request & get-did-endpoint tests * ran format&sourcecheck * added doc * trimmed space in added doc --- .../src/main/docs/hyperledger-aries-component.adoc | 56 +++++++++++++ .../apache/camel/component/aries/Constants.java | 2 + .../aries/handler/PresentProofServiceHandler.java | 4 + .../aries/handler/WalletServiceHandler.java | 8 ++ .../component/aries/ConnectionlessProofTest.java | 94 ++++++++++++++++++++++ 5 files changed, 164 insertions(+) diff --git a/components/camel-hyperledger-aries/src/main/docs/hyperledger-aries-component.adoc b/components/camel-hyperledger-aries/src/main/docs/hyperledger-aries-component.adoc index b585fdc200b..b7ec61eb0d4 100644 --- a/components/camel-hyperledger-aries/src/main/docs/hyperledger-aries-component.adoc +++ b/components/camel-hyperledger-aries/src/main/docs/hyperledger-aries-component.adoc @@ -401,3 +401,59 @@ verifierExchangeRecord = verifierEvents.presentationEx() Assertions.assertTrue(verifierExchangeRecord.isVerified(), "Not VERIFIED"); --------------------------------------------------------------------------------------------- + +==== Connectionless proofs + +There is a possibility to request proof without securing the connection beforehand. +It's similar to usual credential verification process with two changes: + +1. Verifier should use `/present-proof/create-request` instead of `send-request` service. + +2. Verifier should decorate proof presentation with `~service` decorator with their recipient key and endpoint. + +[source,java] +--------------------------------------------------------------------------------------------- +/* 1. Acme creates Job Application Proof Request. + * + * Notice no connectionId and new service endpoint. + * Everything else is the same as for send-request process. + */ +PresentProofRequest proofRequest = PresentProofRequest.builder() + .proofRequest(...) + .build(); + +String exchangeId = template.requestBodyAndHeader("direct:acme", proofRequest, + HEADER_SERVICE, "/present-proof/create-request", + PresentationExchangeRecord.class).getPresentationExchangeId(); + +/* 2. Acme generates presentation JSON. + * + * This is a new step. Acme needs to decorate the presentation request with their service details. + */ +JsonObject presentation = template.requestBodyAndHeader("direct:acme", null, + HEADER_SERVICE, "/present-proof/records/" + exchangeId, + PresentationExchangeRecord.class).getPresentationRequestDict(); + +DID did = template.requestBodyAndHeader("direct:acme", null, + HEADER_SERVICE, "/wallet/did/public", + DID.class); + +String endpoint = template.requestBodyAndHeaders("direct:acme", null, + Map.of(HEADER_SERVICE, "/wallet/get-did-endpoint", HEADER_DID, did.getDid()), + DIDEndpoint.class).getEndpoint(); + +var decorator = new JsonObject(); +var recipients = new JsonArray(); +recipients.add(did.getVerkey()); +decorator.add("recipientKeys", recipients); +decorator.addProperty("serviceEndpoint", endpoint); + +presentation.add("~service", decorator); + +/* 3. Acme shares presentation request with Alice. + * + * This step is not Camel-specific, thus there is no example. + * The easiest way to share this JSON is to generate QR code using it + * and let Alice scan this QR using her Aries mobile wallet. + */ +--------------------------------------------------------------------------------------------- diff --git a/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/Constants.java b/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/Constants.java index 072ca2c5fa0..d8bc2e1d3a5 100644 --- a/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/Constants.java +++ b/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/Constants.java @@ -21,6 +21,8 @@ public final class Constants { // The ACA-Py API path public static final String HEADER_SERVICE = "service"; + public static final String HEADER_DID = "did"; + public static final String HEADER_WALLET_NAME = "WalletName"; public static final String HEADER_WALLET_RECORD = "WalletRecord"; diff --git a/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/PresentProofServiceHandler.java b/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/PresentProofServiceHandler.java index 59878def556..fea58cfa884 100644 --- a/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/PresentProofServiceHandler.java +++ b/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/PresentProofServiceHandler.java @@ -81,6 +81,10 @@ public class PresentProofServiceHandler extends AbstractServiceHandler { throw new UnsupportedServiceException(service); } + } else if (service.equals("/present-proof/create-request")) { + PresentProofRequest reqObj = assertBody(exchange, PresentProofRequest.class); + PresentationExchangeRecord resObj = createClient().presentProofCreateRequest(reqObj).get(); + exchange.getIn().setBody(resObj); } else { throw new UnsupportedServiceException(service); } diff --git a/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/WalletServiceHandler.java b/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/WalletServiceHandler.java index 79f6c5d1937..0299816b7a2 100644 --- a/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/WalletServiceHandler.java +++ b/components/camel-hyperledger-aries/src/main/java/org/apache/camel/component/aries/handler/WalletServiceHandler.java @@ -20,6 +20,9 @@ import org.apache.camel.Exchange; import org.apache.camel.component.aries.HyperledgerAriesEndpoint; import org.apache.camel.component.aries.UnsupportedServiceException; import org.hyperledger.acy_py.generated.model.DID; +import org.hyperledger.acy_py.generated.model.DIDEndpoint; + +import static org.apache.camel.component.aries.Constants.HEADER_DID; public class WalletServiceHandler extends AbstractServiceHandler { @@ -34,6 +37,11 @@ public class WalletServiceHandler extends AbstractServiceHandler { DID resObj = createClient().walletDidPublic().orElse(null); exchange.getIn().setBody(resObj); + } else if (service.equals("/wallet/get-did-endpoint")) { + String did = assertHeader(exchange, HEADER_DID, String.class); + DIDEndpoint resObj = createClient().walletGetDidEndpoint(did).orElse(null); + exchange.getIn().setBody(resObj); + } else { throw new UnsupportedServiceException(service); } diff --git a/components/camel-hyperledger-aries/src/test/java/org/apache/camel/component/aries/ConnectionlessProofTest.java b/components/camel-hyperledger-aries/src/test/java/org/apache/camel/component/aries/ConnectionlessProofTest.java new file mode 100644 index 00000000000..78a91d80672 --- /dev/null +++ b/components/camel-hyperledger-aries/src/test/java/org/apache/camel/component/aries/ConnectionlessProofTest.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.aries; + +import java.io.IOException; +import java.util.Map; + +import org.hyperledger.acy_py.generated.model.DID; +import org.hyperledger.acy_py.generated.model.DIDEndpoint; +import org.hyperledger.aries.api.present_proof.PresentProofRequest; +import org.hyperledger.aries.api.present_proof.PresentProofRequest.ProofRequest; +import org.hyperledger.aries.api.present_proof.PresentProofRequest.ProofRequest.ProofRequestedAttributes; +import org.hyperledger.aries.api.present_proof.PresentationExchangeRecord; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; + +import static org.hyperledger.aries.api.ledger.IndyLedgerRoles.ENDORSER; +import static org.hyperledger.aries.api.present_proof.PresentationExchangeRole.VERIFIER; +import static org.hyperledger.aries.api.present_proof.PresentationExchangeState.REQUEST_SENT; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * docker compose up --detach && docker compose logs -f acapy + */ +@EnabledIfSystemProperty(named = "enable.hyperledger.aries.itests", matches = "true", + disabledReason = "Requires distributed ledger (i.e. blockchain)") +public class ConnectionlessProofTest extends AbstractCamelAriesTest { + + @BeforeEach + void beforeEach() throws IOException { + setRemoveWalletsOnShutdown(true); + onboardWallet(FABER, ENDORSER); + } + + /** + * Creating proof request without connection ID. + */ + @Test + void shouldCreateProofRequest() { + var request = new PresentProofRequest(); + var proofRequest = new ProofRequest(); + var attribute = new ProofRequestedAttributes(); + attribute.setName("first_name"); + proofRequest.setRequestedAttributes(Map.of("0_first_name_uuid", attribute)); + proofRequest.setRequestedPredicates(Map.of()); + request.setProofRequest(proofRequest); + + var result = template.requestBody( + "hyperledger-aries:faber?service=/present-proof/create-request", + request, + PresentationExchangeRecord.class); + + assertNotNull(result.getPresentationExchangeId()); + assertEquals(REQUEST_SENT, result.getState()); + assertEquals(VERIFIER, result.getRole()); + } + + /** + * This endpoint is required to add service decorator to connectionless proof presentation. + */ + @Test + void shouldReturnPublicDidEndpoint() { + var did = template.requestBody( + "hyperledger-aries:faber?service=/wallet/did/public", + null, + DID.class); + + var result = template.requestBodyAndHeader( + "hyperledger-aries:faber?service=/wallet/get-did-endpoint", + null, + "did", + did.getDid(), + DIDEndpoint.class); + + assertNotNull(result.getEndpoint()); + assertEquals(did.getDid(), result.getDid()); + } +}