# Way to encrypt/decrypt data of a particular activity/workflow

**URL:** <https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227>\
**Category:** Community Support\
**Tags:** java-sdk\
**Created:** [March 21, 2022, 9:17am UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227 "2022-03-21T09:17:25Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 21, 2022, 9:17am UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/1 "2022-03-21T09:17:25Z")

</div>

Hi Team,

I am trying to figure out if there is any way to encrypt/decrypt only a specific portion of the payload being passed to activity/workflow? Also, can we have encryption logic only for a particular activity?  
I read about DataConverter and PayloadConverter, but unable to understand if the same can be done for just a specific activity/workflow??  
It would be really helpful if I can refer to any sample implementing this kind of behavior.

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [March 21, 2022, 12:38pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/2 "2022-03-21T12:38:43Z")

</div>

Check out the recently added [crypto example](https://github.com/temporalio/samples-java/tree/main/src/main/java/io/temporal/samples/payloadconverter/crypto). In the sample we use the [jackson-json-crypto](https://github.com/codesqueak/jackson-json-crypto) lib which allows you via annotations in your model classes to define which parts of the payload to encrypt or not, see for example [here](https://github.com/temporalio/samples-java/blob/main/src/main/java/io/temporal/samples/payloadconverter/crypto/MyCustomer.java#L36).

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 21, 2022, 1:07pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/3 "2022-03-21T13:07:49Z")

</div>

@tihomir This should help, will go across this example. Thank you!

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 21, 2022, 2:57pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/4 "2022-03-21T14:57:31Z")

</div>

@tihomir Mentioned sample works fine. But I tried to modify the sample a bit by creating Account class with 2 variables (@Encrypt) and then embedded the same as an array inside MyCustomer.java  
When I try to run the workflow, initially I get an exception as below but eventually the workflow succeeds. Not able to figure out the reason. Can you please suggest on this.

```auto
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
  @Encrypt private String accountName;

  @Encrypt private String accountType;
}

```

```auto
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyCustomer {
  @Encrypt private String name;
  private int age;
  private boolean approved;
  private Account[] accounts;

  public MyCustomer(String name, int age, Account[] accounts) {
    this.name = name;
    this.age = age;
    this.accounts = accounts;
  }
}

```

> io.temporal.internal.replay.InternalWorkflowTaskException: Failure handling event 3 of type ‘EVENT\_TYPE\_WORKFLOW\_TASK\_STARTED’ during execution. {PreviousStartedEventId=3, workflowTaskStartedEventId=3, Currently Processing StartedEventId=3} io.temporal.internal.statemachines.WorkflowStateMachines.createEventProcessingException(WorkflowStateMachines.java:222) io.temporal.internal.statemachines.WorkflowStateMachines.handleEventsBatch(WorkflowStateMachines.java:201) io.temporal.internal.statemachines.WorkflowStateMachines.handleEvent(WorkflowStateMachines.java:175) io.temporal.internal.replay.ReplayWorkflowRunTaskHandler.handleWorkflowTaskImpl(ReplayWorkflowRunTaskHandler.java:176) io.temporal.internal.replay.ReplayWorkflowRunTaskHandler.handleWorkflowTask(ReplayWorkflowRunTaskHandler.java:145) io.temporal.internal.replay.ReplayWorkflowTaskHandler.handleWorkflowTaskWithQuery(ReplayWorkflowTaskHandler.java:122) io.temporal.internal.replay.ReplayWorkflowTaskHandler.handleWorkflowTask(ReplayWorkflowTaskHandler.java:97) io.temporal.internal.worker.WorkflowWorker$TaskHandlerImpl.handle(WorkflowWorker.java:241) io.temporal.internal.worker.WorkflowWorker$TaskHandlerImpl.handle(WorkflowWorker.java:199) io.temporal.internal.worker.PollTaskExecutor.lambda$process$0(PollTaskExecutor.java:93) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) java.base/java.lang.Thread.run(Thread.java:834) Caused By: java.lang.RuntimeException: WorkflowTask: failure executing SCHEDULED-\>WORKFLOW\_TASK\_STARTED, transition history is [CREATED-\>WORKFLOW\_TASK\_SCHEDULED] io.temporal.internal.statemachines.StateMachine.executeTransition(StateMachine.java:151) io.temporal.internal.statemachines.StateMachine.handleHistoryEvent(StateMachine.java:101) io.temporal.internal.statemachines.EntityStateMachineBase.handleEvent(EntityStateMachineBase.java:67) io.temporal.internal.statemachines.WorkflowStateMachines.handleSingleEvent(WorkflowStateMachines.java:235) io.temporal.internal.statemachines.WorkflowStateMachines.handleEventsBatch(WorkflowStateMachines.java:199) io.temporal.internal.statemachines.WorkflowStateMachines.handleEvent(WorkflowStateMachines.java:175) io.temporal.internal.replay.ReplayWorkflowRunTaskHandler.handleWorkflowTaskImpl(ReplayWorkflowRunTaskHandler.java:176) io.temporal.internal.replay.ReplayWorkflowRunTaskHandler.handleWorkflowTask(ReplayWorkflowRunTaskHandler.java:145) io.temporal.internal.replay.ReplayWorkflowTaskHandler.handleWorkflowTaskWithQuery(ReplayWorkflowTaskHandler.java:122) io.temporal.internal.replay.ReplayWorkflowTaskHandler.handleWorkflowTask(ReplayWorkflowTaskHandler.java:97) io.temporal.internal.worker.WorkflowWorker$TaskHandlerImpl.handle(WorkflowWorker.java:241) io.temporal.internal.worker.WorkflowWorker$TaskHandlerImpl.handle(WorkflowWorker.java:199) io.temporal.internal.worker.PollTaskExecutor.lambda$process$0(PollTaskExecutor.java:93) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) java.base/java.lang.Thread.run(Thread.java:834) Caused By: io.temporal.internal.sync.PotentialDeadlockException: Potential deadlock detected: workflow thread “workflow-method-cryptoWorkflo-e907120c-b0c9-4cc1-9e5e-8eaa283329f6” didn’t yield control for over a second. Other workflow threads: java.base@11.0.2/sun.security.provider.ByteArrayAccess.l2bBig(ByteArrayAccess.java:449) java.base@11.0.2/sun.security.provider.SHA5.implDigest(SHA5.java:131) java.base@11.0.2/sun.security.provider.DigestBase.engineDigest(DigestBase.java:210) java.base@11.0.2/sun.security.provider.DigestBase.engineDigest(DigestBase.java:189) java.base@11.0.2/java.security.MessageDigest$Delegate.engineDigest(MessageDigest.java:629) java.base@11.0.2/java.security.MessageDigest.digest(MessageDigest.java:385) java.base@11.0.2/com.sun.crypto.provider.HmacCore.engineDoFinal(HmacCore.java:220) java.base@11.0.2/javax.crypto.Mac.doFinal(Mac.java:581) java.base@11.0.2/javax.crypto.Mac.doFinal(Mac.java:624) java.base@11.0.2/com.sun.crypto.provider.PBKDF2KeyImpl.deriveKey(PBKDF2KeyImpl.java:197) java.base@11.0.2/com.sun.crypto.provider.PBKDF2KeyImpl.(PBKDF2KeyImpl.java:122) java.base@11.0.2/com.sun.crypto.provider.PBKDF2Core.engineGenerateSecret(PBKDF2Core.java:69) java.base@11.0.2/javax.crypto.SecretKeyFactory.generateSecret(SecretKeyFactory.java:344) app//com.codingrodent.jackson.crypto.BaseCryptoContext.createSecretKeySpec(BaseCryptoContext.java:189) app//com.codingrodent.jackson.crypto.BaseCryptoContext.getDecryptCipher(BaseCryptoContext.java:139) app//com.codingrodent.jackson.crypto.BaseCryptoContext.decrypt(BaseCryptoContext.java:85) app//com.codingrodent.jackson.crypto.EncryptionService.decrypt(EncryptionService.java:127) app//com.codingrodent.jackson.crypto.EncryptionService.decrypt(EncryptionService.java:141) app//com.codingrodent.jackson.crypto.EncryptedJsonDeserializer.deserialize(EncryptedJsonDeserializer.java:64) app//com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129) app//com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:313) app//com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:176) app//com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:214) app//com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:24) app//com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129) app//com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:313) app//com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:176) app//com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) app//com.fasterxml.jackson.databind.ObjectMapper.\_readMapAndClose(ObjectMapper.java:4674) app//com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3723) app//io.temporal.common.converter.JacksonJsonPayloadConverter.fromData(JacksonJsonPayloadConverter.java:82) app//io.temporal.common.converter.DefaultDataConverter.fromPayload(DefaultDataConverter.java:135) app//io.temporal.common.converter.DataConverter.arrayFromPayloads(DataConverter.java:104) app//io.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation.execute(POJOWorkflowImplementationFactory.java:285) app//io.temporal.internal.sync.WorkflowExecuteRunnable.run(WorkflowExecuteRunnable.java:72) app//io.temporal.internal.sync.SyncWorkflow.lambda$start$0(SyncWorkflow.java:137) app//io.temporal.internal.sync.SyncWorkflow$$Lambda$135/0x0000000800413840.run(Unknown Source) app//io.temporal.internal.sync.CancellationScopeImpl.run(CancellationScopeImpl.java:101) app//io.temporal.internal.sync.WorkflowThreadImpl$RunnableWrapper.run(WorkflowThreadImpl.java:111) java.base@11.0.2/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) java.base@11.0.2/java.util.concurrent.FutureTask.run(FutureTask.java:264) java.base@11.0.2/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) java.base@11.0.2/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) java.base@11.0.2/java.lang.Thread.run(Thread.java:834)

 ![Error](https://us1.discourse-cdn.com/flex016/uploads/temporal/original/2X/5/5743af53a10c4f6855598bc65873b62ef2f5374a.jpeg)

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 21, 2022, 3:04pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/5 "2022-03-21T15:04:07Z")

</div>

Also, one point to note here. It works fine if I have any one of the variables inside Account.java with @Encrypt annotation. Issue occurs when both the variables are annotated with @Encrypt.

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [March 21, 2022, 5:00pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/6 "2022-03-21T17:00:56Z")

</div>

I am not able to reproduce this issue, could you maybe share your sample with changes in a github repo so can try to run?

One thing maybe is that:

1. Always provide a public no-args constructor, this is needed regardless of using crypto or not
2. Annotate the public getter methods rather the the fields themselves.

Here is what i get when passing MyCustomer with two Account items in the array:

 ![Screen Shot 2022-03-21 at 12.58.36 PM](https://us1.discourse-cdn.com/flex016/uploads/temporal/original/2X/a/a4b1e8e7416ac3e37288200f3bfafbeca2cab184.png)

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 22, 2022, 4:15am UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/7 "2022-03-22T04:15:38Z")

</div>

@tihomir I will try both the things that you talked about.  
But any specific reason for point 1 - public no-args constructor? I had defined the class with annotation @NoArgsConstructor. Should it not suffice ?  
Also, as mentioned in [GitHub - codesqueak/jackson-json-crypto: Jackson Crypto Extension Module](https://github.com/codesqueak/jackson-json-crypto) - States “Any field that is required to be encrypted has to be marked as such. This can be done by either annotating the getter() or by annotating the field definition.”  
Can you explain on above points please.

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 22, 2022, 7:55am UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/8 "2022-03-22T07:55:14Z")

</div>

@tihomir Also, as I understand, this is not being supported out of the box by Temporal since it is using another open source project “jackson-json-crypto”. Are there any plans to add this feature as part of Temporal Java SDK in future?

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [March 22, 2022, 2:04pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/9 "2022-03-22T14:04:20Z")

</div>

> [@poojabhutada](#):
>
> Can you explain on above points please.

I don’t use Lombok so just wanted to mention these points. In the past iirc I ran into some issues with Lombok so wasn’t sure if your annotations are really applied or not, but generally public no-arg constructor is needed for any inputs to be converted to Payload via default Temporal data converter.

Another thing you could try is a newer version of jackson-json-crypto (latest should be 2.2.0) than what [its used in the sample](https://github.com/temporalio/samples-java/blob/main/build.gradle#L60).  
We had to use an older version because their 2.x require Java 11 and our samples have to run on 1.8 as well.  
For the second point, I found that with the 1.1.0 version used I had better luck with annotating the getter methods rather than the fields directly, but that might be just a side-effect of not using their latest as well.

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [March 22, 2022, 2:09pm UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/10 "2022-03-22T14:09:19Z")

</div>

> [@poojabhutada](#):
>
> Are there any plans to add this feature as part of Temporal Java SDK in future?

I think this would be a good idea. We trying to find similar open source solutions and trying to evaluate them as well (let us know if you know of any we could look at).  
jackson-json-crypto was suggested by community, see [here](https://github.com/temporalio/samples-java/issues/229). One thing that’s a little alarming is [this](https://github.com/temporalio/samples-java/issues/229#issuecomment-1045078208) particular user comment regarding performance issues. It would be nice if you could test this out as well and let us know if you run into it and how you solved it.

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 23, 2022, 3:56am UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/11 "2022-03-23T03:56:31Z")

</div>

> [@tihomir](#):
>
> newer version of jackson-json-crypto

Ok, Will try to use newer version of jackson-json-crypto and verify the same.

---

<div class="post-metadata">

**Author:** ![poojabhutada](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/poojabhutada/32/3372_2.png) [@poojabhutada](https://community.temporal.io/u/poojabhutada)\
**Post date:** [March 23, 2022, 3:57am UTC](https://community.temporal.io/t/way-to-encrypt-decrypt-data-of-a-particular-activity-workflow/4227/12 "2022-03-23T03:57:20Z")

</div>

@tihomir Thanks for that feedback. Will check this for performance issues and confirm on the same once we are through with that.
