Search in sources :

Example 21 with PublicKey

use of com.quorum.tessera.encryption.PublicKey in project tessera by ConsenSys.

the class TransactionResource method sendRaw.

@Operation(summary = "/sendraw", operationId = "encryptStoreAndSendOctetStream", description = "encrypts a payload, stores result in database, and publishes result to recipients")
@ApiResponse(responseCode = "200", description = "encrypted payload hash", content = @Content(schema = @Schema(type = "string", format = "base64", description = "encrypted payload hash")))
@POST
@Path("sendraw")
@Consumes(APPLICATION_OCTET_STREAM)
@Produces(TEXT_PLAIN)
public Response sendRaw(@HeaderParam("c11n-from") @Parameter(description = "public key identifying the server's key pair that will be used in the encryption; if not set, default used", schema = @Schema(format = "base64")) @Valid @ValidBase64 final String sender, @HeaderParam("c11n-to") @Parameter(description = "comma-separated list of recipient public keys", schema = @Schema(format = "base64")) final String recipientKeys, @Schema(description = "data to be encrypted") @NotNull @Size(min = 1) @Valid final byte[] payload) {
    final PublicKey senderKey = Optional.ofNullable(sender).filter(Predicate.not(String::isEmpty)).map(base64Decoder::decode).map(PublicKey::from).orElseGet(transactionManager::defaultPublicKey);
    final List<PublicKey> recipients = Stream.of(recipientKeys).filter(Objects::nonNull).filter(s -> !Objects.equals("", s)).map(v -> v.split(",")).flatMap(Arrays::stream).map(base64Decoder::decode).map(PublicKey::from).collect(Collectors.toList());
    final com.quorum.tessera.transaction.SendRequest request = com.quorum.tessera.transaction.SendRequest.Builder.create().withSender(senderKey).withRecipients(recipients).withPayload(payload).withPrivacyMode(PrivacyMode.STANDARD_PRIVATE).withAffectedContractTransactions(Collections.emptySet()).withExecHash(new byte[0]).build();
    final com.quorum.tessera.transaction.SendResponse sendResponse = transactionManager.send(request);
    final String encodedTransactionHash = Optional.of(sendResponse).map(com.quorum.tessera.transaction.SendResponse::getTransactionHash).map(MessageHash::getHashBytes).map(base64Encoder::encodeToString).get();
    LOGGER.debug("Encoded key: {}", encodedTransactionHash);
    URI location = UriBuilder.fromPath("transaction").path(URLEncoder.encode(encodedTransactionHash, StandardCharsets.UTF_8)).build();
    return Response.status(Response.Status.OK).entity(encodedTransactionHash).location(location).build();
}
Also used : PublicKey(com.quorum.tessera.encryption.PublicKey) java.util(java.util) PrivacyMode(com.quorum.tessera.enclave.PrivacyMode) Size(jakarta.validation.constraints.Size) LoggerFactory(org.slf4j.LoggerFactory) Valid(jakarta.validation.Valid) NotNull(jakarta.validation.constraints.NotNull) PrivacyValid(com.quorum.tessera.api.constraint.PrivacyValid) Content(io.swagger.v3.oas.annotations.media.Content) Operation(io.swagger.v3.oas.annotations.Operation) Response(jakarta.ws.rs.core.Response) ApiResponse(io.swagger.v3.oas.annotations.responses.ApiResponse) URI(java.net.URI) MessageHash(com.quorum.tessera.data.MessageHash) Schema(io.swagger.v3.oas.annotations.media.Schema) Pattern(jakarta.validation.constraints.Pattern) Logger(org.slf4j.Logger) PrivacyGroup(com.quorum.tessera.enclave.PrivacyGroup) Hidden(io.swagger.v3.oas.annotations.Hidden) com.quorum.tessera.api(com.quorum.tessera.api) ExampleObject(io.swagger.v3.oas.annotations.media.ExampleObject) Predicate(java.util.function.Predicate) TransactionManager(com.quorum.tessera.transaction.TransactionManager) PrivacyGroupManager(com.quorum.tessera.privacygroup.PrivacyGroupManager) jakarta.ws.rs(jakarta.ws.rs) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) ValidBase64(com.quorum.tessera.config.constraints.ValidBase64) Parameter(io.swagger.v3.oas.annotations.Parameter) ArraySchema(io.swagger.v3.oas.annotations.media.ArraySchema) URLEncoder(java.net.URLEncoder) Stream(java.util.stream.Stream) MediaType(jakarta.ws.rs.core.MediaType) UriBuilder(jakarta.ws.rs.core.UriBuilder) Tag(io.swagger.v3.oas.annotations.tags.Tag) PublicKey(com.quorum.tessera.encryption.PublicKey) MessageHash(com.quorum.tessera.data.MessageHash) URI(java.net.URI) Operation(io.swagger.v3.oas.annotations.Operation) ApiResponse(io.swagger.v3.oas.annotations.responses.ApiResponse)

Example 22 with PublicKey

use of com.quorum.tessera.encryption.PublicKey in project tessera by ConsenSys.

the class TransactionResource method receiveRaw.

@Operation(summary = "/receiveraw", operationId = "getDecryptedPayloadOctetStream", description = "get payload from database, decrypt, and return")
@ApiResponse(responseCode = "200", description = "decrypted ciphertext payload", content = @Content(array = @ArraySchema(schema = @Schema(type = "string", format = "byte", description = "decrypted ciphertext payload"))))
@GET
@Path("receiveraw")
@Consumes(APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response receiveRaw(@Schema(description = "hash indicating encrypted payload to retrieve from database", format = "base64") @ValidBase64 @NotNull @HeaderParam(value = "c11n-key") String hash, @Schema(description = "(optional) public key of recipient of the encrypted payload; used in decryption; if not provided, decryption is attempted with all known recipient keys in turn", format = "base64") @ValidBase64 @HeaderParam(value = "c11n-to") String recipientKey) {
    LOGGER.debug("Received receiveraw request for hash : {}, recipientKey: {}", hash, recipientKey);
    MessageHash transactionHash = Optional.of(hash).map(base64Decoder::decode).map(MessageHash::new).get();
    PublicKey recipient = Optional.ofNullable(recipientKey).map(base64Decoder::decode).map(PublicKey::from).orElse(null);
    com.quorum.tessera.transaction.ReceiveRequest request = com.quorum.tessera.transaction.ReceiveRequest.Builder.create().withTransactionHash(transactionHash).withRecipient(recipient).build();
    com.quorum.tessera.transaction.ReceiveResponse receiveResponse = transactionManager.receive(request);
    byte[] payload = receiveResponse.getUnencryptedTransactionData();
    return Response.status(Response.Status.OK).entity(payload).build();
}
Also used : PublicKey(com.quorum.tessera.encryption.PublicKey) MessageHash(com.quorum.tessera.data.MessageHash) Operation(io.swagger.v3.oas.annotations.Operation) ApiResponse(io.swagger.v3.oas.annotations.responses.ApiResponse)

Example 23 with PublicKey

use of com.quorum.tessera.encryption.PublicKey in project tessera by ConsenSys.

the class TransactionResource3 method receive.

// path /transaction/{hash} is overloaded (application/json and application/vnd.tessera-2.1+json);
// swagger
// annotations cannot handle situations like this so this operation documents both
@Operation(summary = "/transaction/{hash}", operationId = "getDecryptedPayloadJsonUrl", description = "get payload from database, decrypt, and return")
@ApiResponse(responseCode = "200", description = "decrypted payload", content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = ReceiveResponse.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = ReceiveResponse.class)) })
@GET
@Path("/transaction/{hash}")
@Produces({ MIME_TYPE_JSON_2_1, MIME_TYPE_JSON_3 })
public Response receive(@Parameter(description = "hash indicating encrypted payload to retrieve from database", schema = @Schema(format = "base64")) @Valid @ValidBase64 @PathParam("hash") final String hash, @Parameter(description = "(optional) public key of recipient of the encrypted payload; used in decryption; if not provided, decryption is attempted with all known recipient keys in turn", schema = @Schema(format = "base64")) @QueryParam("to") final String toStr, @Parameter(description = "(optional) indicates whether the payload is raw; determines which database the payload is retrieved from; possible values\n* true - for pre-stored payloads in the \"raw\" database\n* false (default) - for already sent payloads in \"standard\" database") @Valid @Pattern(flags = Pattern.Flag.CASE_INSENSITIVE, regexp = "^(true|false)$") @QueryParam("isRaw") final String isRaw) {
    final PublicKey recipient = Optional.ofNullable(toStr).filter(Predicate.not(String::isEmpty)).map(base64Decoder::decode).map(PublicKey::from).orElse(null);
    final MessageHash transactionHash = Optional.of(hash).map(base64Decoder::decode).map(MessageHash::new).get();
    final com.quorum.tessera.transaction.ReceiveRequest request = com.quorum.tessera.transaction.ReceiveRequest.Builder.create().withRecipient(recipient).withTransactionHash(transactionHash).withRaw(Boolean.parseBoolean(isRaw)).build();
    com.quorum.tessera.transaction.ReceiveResponse response = transactionManager.receive(request);
    final ReceiveResponse receiveResponse = new ReceiveResponse();
    receiveResponse.setPayload(response.getUnencryptedTransactionData());
    receiveResponse.setSenderKey(response.sender().encodeToBase64());
    receiveResponse.setAffectedContractTransactions(response.getAffectedTransactions().stream().map(MessageHash::getHashBytes).map(base64Encoder::encodeToString).toArray(String[]::new));
    Optional.ofNullable(response.getExecHash()).map(String::new).ifPresent(receiveResponse::setExecHash);
    receiveResponse.setPrivacyFlag(response.getPrivacyMode().getPrivacyFlag());
    receiveResponse.setManagedParties(Optional.ofNullable(response.getManagedParties()).orElse(Collections.emptySet()).stream().map(PublicKey::encodeToBase64).toArray(String[]::new));
    response.getPrivacyGroupId().map(PrivacyGroup.Id::getBase64).ifPresent(receiveResponse::setPrivacyGroupId);
    return Response.ok(receiveResponse).build();
}
Also used : PublicKey(com.quorum.tessera.encryption.PublicKey) ReceiveResponse(com.quorum.tessera.api.ReceiveResponse) MessageHash(com.quorum.tessera.data.MessageHash) PrivacyGroup(com.quorum.tessera.enclave.PrivacyGroup) Operation(io.swagger.v3.oas.annotations.Operation) ApiResponse(io.swagger.v3.oas.annotations.responses.ApiResponse)

Example 24 with PublicKey

use of com.quorum.tessera.encryption.PublicKey in project tessera by ConsenSys.

the class TransactionResource3 method sendSignedTransaction.

// path /sendsignedtx is overloaded (application/octet-stream, application/json and
// application/vnd.tessera-2.1+json); swagger annotations cannot handle situations like this so
// this operation
// documents both
@Operation(operationId = "sendStored", summary = "/sendsignedtx", description = "re-wraps a pre-stored & pre-encrypted payload, stores result in database, and publishes result to recipients", requestBody = @RequestBody(content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SendSignedRequest.class)), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = SendSignedRequest.class)), @Content(mediaType = APPLICATION_OCTET_STREAM, array = @ArraySchema(schema = @Schema(description = "hash of pre-stored payload", type = "string", format = "base64"))) }))
@ApiResponse(responseCode = "200", description = "hash of rewrapped payload (for application/octet-stream requests)", content = @Content(mediaType = APPLICATION_OCTET_STREAM, schema = @Schema(description = "hash of rewrapped payload", type = "string", format = "base64")))
@ApiResponse(responseCode = "201", description = "hash of rewrapped payload", content = { @Content(mediaType = APPLICATION_JSON, schema = @Schema(implementation = SendResponse.class, description = "hash of rewrapped payload")), @Content(mediaType = MIME_TYPE_JSON_2_1, schema = @Schema(implementation = SendResponse.class, description = "hash of rewrapped payload")) })
@POST
@Path("sendsignedtx")
@Consumes({ MIME_TYPE_JSON_2_1, MIME_TYPE_JSON_3 })
@Produces({ MIME_TYPE_JSON_2_1, MIME_TYPE_JSON_3 })
public Response sendSignedTransaction(@NotNull @Valid @PrivacyValid final SendSignedRequest sendSignedRequest) {
    final Optional<PrivacyGroup.Id> privacyGroupId = Optional.ofNullable(sendSignedRequest.getPrivacyGroupId()).map(PrivacyGroup.Id::fromBase64String);
    final List<PublicKey> recipients = privacyGroupId.map(privacyGroupManager::retrievePrivacyGroup).map(PrivacyGroup::getMembers).orElse(Optional.ofNullable(sendSignedRequest.getTo()).stream().flatMap(Arrays::stream).map(base64Decoder::decode).map(PublicKey::from).collect(Collectors.toList()));
    final PrivacyMode privacyMode = PrivacyMode.fromFlag(sendSignedRequest.getPrivacyFlag());
    final Set<MessageHash> affectedTransactions = Stream.ofNullable(sendSignedRequest.getAffectedContractTransactions()).flatMap(Arrays::stream).map(base64Decoder::decode).map(MessageHash::new).collect(Collectors.toSet());
    final byte[] execHash = Optional.ofNullable(sendSignedRequest.getExecHash()).map(String::getBytes).orElse(new byte[0]);
    final com.quorum.tessera.transaction.SendSignedRequest.Builder requestBuilder = com.quorum.tessera.transaction.SendSignedRequest.Builder.create().withSignedData(sendSignedRequest.getHash()).withRecipients(recipients).withPrivacyMode(privacyMode).withAffectedContractTransactions(affectedTransactions).withExecHash(execHash);
    privacyGroupId.ifPresent(requestBuilder::withPrivacyGroupId);
    final com.quorum.tessera.transaction.SendResponse response = transactionManager.sendSignedTransaction(requestBuilder.build());
    final String encodedTransactionHash = Optional.of(response).map(com.quorum.tessera.transaction.SendResponse::getTransactionHash).map(MessageHash::getHashBytes).map(base64Encoder::encodeToString).get();
    LOGGER.debug("Encoded key: {}", encodedTransactionHash);
    final URI location = UriBuilder.fromPath("transaction").path(URLEncoder.encode(encodedTransactionHash, StandardCharsets.UTF_8)).build();
    final String[] managedParties = Optional.of(response).map(com.quorum.tessera.transaction.SendResponse::getManagedParties).orElse(Collections.emptySet()).stream().map(PublicKey::encodeToBase64).toArray(String[]::new);
    final SendResponse responseEntity = new SendResponse();
    responseEntity.setKey(encodedTransactionHash);
    responseEntity.setManagedParties(managedParties);
    responseEntity.setSenderKey(response.getSender().encodeToBase64());
    LOGGER.debug("Encoded key: {}", encodedTransactionHash);
    return Response.created(location).entity(responseEntity).build();
}
Also used : PublicKey(com.quorum.tessera.encryption.PublicKey) SendResponse(com.quorum.tessera.api.SendResponse) PrivacyMode(com.quorum.tessera.enclave.PrivacyMode) MessageHash(com.quorum.tessera.data.MessageHash) URI(java.net.URI) SendSignedRequest(com.quorum.tessera.api.SendSignedRequest) Operation(io.swagger.v3.oas.annotations.Operation) ApiResponse(io.swagger.v3.oas.annotations.responses.ApiResponse)

Example 25 with PublicKey

use of com.quorum.tessera.encryption.PublicKey in project tessera by ConsenSys.

the class BesuTransactionResourceTest method sendToPrivacyGroup.

@Test
public void sendToPrivacyGroup() {
    final Base64.Encoder base64Encoder = Base64.getEncoder();
    final String base64Key = "BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=";
    final SendRequest sendRequest = new SendRequest();
    sendRequest.setPayload(base64Encoder.encode("PAYLOAD".getBytes()));
    sendRequest.setPrivacyGroupId(base64Key);
    final PublicKey sender = mock(PublicKey.class);
    when(transactionManager.defaultPublicKey()).thenReturn(sender);
    final com.quorum.tessera.transaction.SendResponse sendResponse = mock(com.quorum.tessera.transaction.SendResponse.class);
    final MessageHash messageHash = mock(MessageHash.class);
    final byte[] txnData = "TxnData".getBytes();
    when(messageHash.getHashBytes()).thenReturn(txnData);
    when(sendResponse.getTransactionHash()).thenReturn(messageHash);
    when(transactionManager.send(any(com.quorum.tessera.transaction.SendRequest.class))).thenReturn(sendResponse);
    PrivacyGroup retrieved = mock(PrivacyGroup.class);
    PrivacyGroup.Id groupId = PrivacyGroup.Id.fromBase64String(base64Key);
    PublicKey member = PublicKey.from("member".getBytes());
    when(retrieved.getId()).thenReturn(groupId);
    when(retrieved.getMembers()).thenReturn(List.of(member));
    when(privacyGroupManager.retrievePrivacyGroup(groupId)).thenReturn(retrieved);
    final Response result = besuTransactionResource.send(sendRequest);
    // jersey.target("send").request().post(Entity.entity(sendRequest,
    // MediaType.APPLICATION_JSON));
    assertThat(result.getStatus()).isEqualTo(200);
    assertThat(result.getLocation().getPath()).isEqualTo("transaction/" + base64Encoder.encodeToString(txnData));
    SendResponse resultSendResponse = (SendResponse) result.getEntity();
    assertThat(resultSendResponse.getKey()).isEqualTo(Base64.getEncoder().encodeToString(txnData));
    ArgumentCaptor<com.quorum.tessera.transaction.SendRequest> argumentCaptor = ArgumentCaptor.forClass(com.quorum.tessera.transaction.SendRequest.class);
    verify(transactionManager).send(argumentCaptor.capture());
    verify(transactionManager).defaultPublicKey();
    verify(privacyGroupManager).retrievePrivacyGroup(groupId);
    com.quorum.tessera.transaction.SendRequest businessObject = argumentCaptor.getValue();
    assertThat(businessObject).isNotNull();
    assertThat(businessObject.getPayload()).isEqualTo(sendRequest.getPayload());
    assertThat(businessObject.getSender()).isEqualTo(sender);
    assertThat(businessObject.getRecipients()).hasSize(1);
    assertThat(businessObject.getRecipients().get(0)).isEqualTo(member);
    assertThat(businessObject.getPrivacyMode()).isEqualTo(PrivacyMode.STANDARD_PRIVATE);
    assertThat(businessObject.getAffectedContractTransactions()).isEmpty();
    assertThat(businessObject.getExecHash()).isEmpty();
    assertThat(businessObject.getPrivacyGroupId()).isPresent().get().isEqualTo(groupId);
}
Also used : Base64(java.util.Base64) SendRequest(com.quorum.tessera.api.SendRequest) PublicKey(com.quorum.tessera.encryption.PublicKey) SendResponse(com.quorum.tessera.api.SendResponse) MessageHash(com.quorum.tessera.data.MessageHash) PrivacyGroup(com.quorum.tessera.enclave.PrivacyGroup) SendResponse(com.quorum.tessera.api.SendResponse) BesuReceiveResponse(com.quorum.tessera.api.BesuReceiveResponse) ReceiveResponse(com.quorum.tessera.transaction.ReceiveResponse) Response(jakarta.ws.rs.core.Response) Test(org.junit.Test)

Aggregations

PublicKey (com.quorum.tessera.encryption.PublicKey)281 Test (org.junit.Test)213 Response (jakarta.ws.rs.core.Response)59 MessageHash (com.quorum.tessera.data.MessageHash)57 EncodedPayload (com.quorum.tessera.enclave.EncodedPayload)48 Collectors (java.util.stream.Collectors)32 PrivacyGroup (com.quorum.tessera.enclave.PrivacyGroup)28 NodeInfo (com.quorum.tessera.partyinfo.node.NodeInfo)25 java.util (java.util)23 SendResponse (com.quorum.tessera.api.SendResponse)21 Nonce (com.quorum.tessera.encryption.Nonce)20 Recipient (com.quorum.tessera.partyinfo.node.Recipient)20 Operation (io.swagger.v3.oas.annotations.Operation)20 ApiResponse (io.swagger.v3.oas.annotations.responses.ApiResponse)20 Stream (java.util.stream.Stream)19 ReceiveResponse (com.quorum.tessera.transaction.ReceiveResponse)18 EncryptedTransaction (com.quorum.tessera.data.EncryptedTransaction)17 PrivacyMode (com.quorum.tessera.enclave.PrivacyMode)17 URI (java.net.URI)17 SendRequest (com.quorum.tessera.api.SendRequest)15