---
title: Create a JWE
description: Learn how to encrypt sensitive data
---

{% callout type="tip" %}
If you are unable to implement JWE encryption in your own systems, you can use Figure's [Encryption API](/jwe-data-protection/encryption-api) to encrypt payloads on your behalf without any cryptographic setup.
{% /callout %}

## 1. Setting up for JWE
### Libraries and tools
To use JWE, you need appropriate libraries for your development environment. We recommend [Nimbus JOSE+JWT](https://connect2id.com/products/nimbus-jose-jwt) for Java/Kotlin.

{% tabs %}
{% tab label="Maven" %}
```xml {% title="Nimbus dependency" %}
<!-- https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt -->
<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>9.40</version>
</dependency>
```
{% /tab %}
{% tab label="Gradle" %}

```kotlin {% title="Nimbus dependency" %}
// https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
implementation 'com.nimbusds:nimbus-jose-jwt:9.40'
```

{% /tab %}
{% tab label="Gradle Kotlin DSL" %}

```kotlin {% title="Nimbus dependency" %}
// https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
implementation("com.nimbusds:nimbus-jose-jwt:9.40")
```

{% /tab %}
{% /tabs %}

## 2. Creating a JWE

The following example shows how to use the Nimbus library to create a JWE token with RSA-OAEP-256 encryption and A256GCM content encryption.

{% tabs %}
{% tab label="Java" %}

```java {% title="Example JWE creation" %}
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEHeader;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.RSAEncrypter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.KeyFactory;
import java.security.Security;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class Main {
  public static void main(String[] args) throws Exception {
    // Add Bouncy Castle Provider
    Security.addProvider(new BouncyCastleProvider());

    // Replace with your recipient's public key string
    String publicKeyPEM = 
      "-----BEGIN PUBLIC KEY-----\n" +
      "MIIBIjANBgkqhkiG9w0 ... your key here\n" +
      "-----END PUBLIC KEY-----";

    // Remove the first and last lines and any whitespace
    String publicKeyPEMFormatted = publicKeyPEM
      .replace("-----BEGIN PUBLIC KEY-----", "")
      .replace("-----END PUBLIC KEY-----", "")
      .replaceAll("\\s", "");

    // Decode the public key
    byte[] keyBytes = Base64.getDecoder().decode(publicKeyPEMFormatted);
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
    RSAPublicKey recipientPublicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);

    // Print the public key to verify
    System.out.println("Loaded Public Key: " + recipientPublicKey);

    // Building the JWE Header
    JWEHeader header = new JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM);

    // Encrypting the Payload
    Payload payload = new Payload("Sensitive data to be encrypted");
    JWEObject jweObject = new JWEObject(header, payload);

    // Encrypt with the recipient's public key
    RSAEncrypter encrypter = new RSAEncrypter(recipientPublicKey);
    jweObject.encrypt(encrypter);

    // Generating the JWE Token
    String jweToken = jweObject.serialize();
    System.out.println("JWE Token: " + jweToken);
  }
}
```
{% /tab %}

{% tab label="Kotlin" %}

```kotlin {% title="Example JWE creation" %}
import com.nimbusds.jose.EncryptionMethod
import com.nimbusds.jose.JWEAlgorithm
import com.nimbusds.jose.JWEHeader
import com.nimbusds.jose.JWEObject
import com.nimbusds.jose.Payload
import com.nimbusds.jose.crypto.RSAEncrypter
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.KeyFactory
import java.security.Security
import java.security.interfaces.RSAPublicKey
import java.security.spec.X509EncodedKeySpec
import java.util.*

fun main() {
  // Add Bouncy Castle Provider
  Security.addProvider(BouncyCastleProvider())

  // Replace with your recipient's public key string
  val publicKeyPEM = """
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0 ... your key here
    -----END PUBLIC KEY-----
    """.trimIndent()

  // Remove the first and last lines and any whitespace
  val publicKeyPEMFormatted = publicKeyPEM
    .replace("-----BEGIN PUBLIC KEY-----", "")
    .replace("-----END PUBLIC KEY-----", "")
    .replace("\\s".toRegex(), "")

  // Decode the public key
  val keyBytes = Base64.getDecoder().decode(publicKeyPEMFormatted)
  val keySpec = X509EncodedKeySpec(keyBytes)
  val keyFactory = KeyFactory.getInstance("RSA", "BC")
  val recipientPublicKey = keyFactory.generatePublic(keySpec) as RSAPublicKey

  // Print the public key to verify
  println("Loaded Public Key: $recipientPublicKey")

  // Replace with your recipient's public key
//    val recipientPublicKey: RSAPublicKey = /* Load the recipient's public key */

  // Building the JWE Header
  val header = JWEHeader(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A256GCM)

  // Encrypting the Payload
  val payload = Payload("Sensitive data to be encrypted")
  val jweObject = JWEObject(header, payload)

  // Encrypt with the recipient's public key
  val encrypter = RSAEncrypter(recipientPublicKey)
  jweObject.encrypt(encrypter)

  // Generating the JWE Token
  val jweToken = jweObject.serialize()
  println("JWE Token: $jweToken")
}
```
{% /tab %}
{% /tabs %}

## 3. Sending encrypted data to Figure's API

A JWE request requires a specific request body:

`{ "encrypted": "<your-jwe-encrypted-request>" }`

### Example API request

```bash {% title="Example request with JWE request and token" %}
curl -X POST https://api.figure.com/example \
  -H "apikey: <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{ "encrypted": "<your-jwe-encrypted-request>" }'
```

## 4. Decrypting a JWE (for reference)

{% tabs %}
{% tab label="Java" %}

```java {% title="JWE header and payload decryption" %}
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.crypto.RSADecrypter;

import java.security.interfaces.RSAPrivateKey;

public class JWEDecryptionExample {
  
    public static void main(String[] args) {

        // The JWE token to decrypt
        String jweToken = "your-jwe-token-here";

        // Parse the JWE token
        JWEObject jweObject = JWEObject.parse(jweToken);

        // Extract and verify the JWE header
        System.out.println("JWE Header: " + jweObject.getHeader());

        // Load the private key
        String privateKeyString = "-----BEGIN PRIVATE KEY-----\n" +
          "MIIEvgIBADANBgkq ... your private key here ...\n" +
          "-----END PRIVATE KEY-----";
  
        String privateKeyFormatted = privateKeyString
          .replace("-----BEGIN PRIVATE KEY-----", "")
          .replace("-----END PRIVATE KEY-----", "")
          .replaceAll("\\s", "");
  
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyFormatted);
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory privatekeyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKey privateKey = (RSAPrivateKey) privatekeyFactory.generatePrivate(privateKeySpec);

      // Decrypt the encrypted data using the private key
        RSADecrypter decrypter = new RSADecrypter(privateKey);
        jweObject.decrypt(decrypter);
        
        // Retrieve the payload
        String payload = jweObject.getPayload().toString();
        System.out.println("Decrypted Payload: " + payload);
    }
}
```
{% /tab %}

{% tab label="Kotlin" %}

```kotlin {% title="JWE header and payload decryption" %}
import com.nimbusds.jose.JWEObject
import com.nimbusds.jose.crypto.RSADecrypter
import java.security.interfaces.RSAPrivateKey

fun main() {
    // The JWE token to decrypt
    val jweToken = "your-jwe-token-here"
    
    // Parse the JWE token
    val jweObject = JWEObject.parse(jweToken)
    
    // Extract and verify the JWE header
    println("JWE Header: ${jweObject.header}")

  // Load the private key
    val privateKeyString = """
          -----BEGIN PRIVATE KEY-----
          MIIEvgIBADANBgkq ... your private key here ...
          -----END PRIVATE KEY-----
          """
  
    val privateKeyFormatted = privateKeyString
      .replace("-----BEGIN PRIVATE KEY-----", "")
      .replace("-----END PRIVATE KEY-----", "")
      .replace("\\s".toRegex(), "")
    val privateKeyBytes = Base64.getDecoder().decode(privateKeyFormatted)
    val privateKeySpec = PKCS8EncodedKeySpec(privateKeyBytes)
    val privatekeyFactory = KeyFactory.getInstance("RSA")
    val privateKey = privatekeyFactory.generatePrivate(privateKeySpec) as RSAPrivateKey
    
    // Decrypt the encrypted data using the private key
    val decrypter = RSADecrypter(privateKey)
    jweObject.decrypt(decrypter)
    
    // Retrieve the payload
    val payload = jweObject.payload.toString()
    println("Decrypted Payload: $payload")
}

```
{% /tab %}
{% /tabs %}

## 5. Best practices
### Security considerations
- **Key Management**: Store keys securely and rotate them regularly.
- **Encryption Algorithms**: Use strong, industry-standard algorithms (e.g., RSA-OAEP-256, A256GCM).
- **Regular Updates**: Keep your libraries and tools up to date to benefit from the latest security patches.

### Debugging tips
- Verify the correctness of your JWE header and payload.
- Ensure the recipient's public key is correctly configured for encryption.

## 6. Additional resources
- [Nimbus JOSE+JWT Documentation](https://connect2id.com/products/nimbus-jose-jwt)
- [JSON Web Encryption (JWE) Specification](https://tools.ietf.org/html/rfc7516)

## Conclusion
By following this guide, you will help us maintain the highest standards of security for data exchanged with Figure's API. We appreciate your commitment to protecting sensitive information and look forward to successful and secure integrations.
If you need further assistance or specific examples, feel free to ask!
