> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/classic-tokenization/get-started/api-basics/data-encryption-and-security.md).

# Data encryption and security

### Application-level encryption of sensitive data <a href="#application-level-encryption-of-sensitive-data" id="application-level-encryption-of-sensitive-data"></a>

PCI-sensitive fields in inbound and outbound API messages are encrypted using the PKCS#7 enveloped-data format. This is in addition to the mutual TLS (mTLS) connection.

<figure><img src="/files/f9hqua90P7LiXR0BmOJx" alt=""><figcaption><p>PKCS#7 application-level encryption on top of mutual TLS (mTLS).</p></figcaption></figure>

### Keys and certificates <a href="#keys-and-certificates" id="keys-and-certificates"></a>

Use the TSH portal during TSH onboarding to manage PKCS#7 certificates:

* Upload your Issuer certificate (`ISSUER_PKCS7_CERT`). Thales TSH uses it to encrypt PCI-sensitive fields sent to the issuer backend. Thales TSH also sends the certificate identifier so you can select the right private key (for example, in `RequestCardDigitalization`).
* Download the Thales certificate. Use it to encrypt PCI-sensitive fields sent from the issuer backend to Thales TSH. Include the certificate identifier in your request so Thales TSH can select the right private key (for example, in `UpdateCard`).

### Encryption parameters <a href="#encryption-parameters" id="encryption-parameters"></a>

PKCS#7 and CMS are defined in RFC 2315 and RFC 5652. Most cryptographic libraries support the required operations.

Encryption parameters:

* Content encryption algorithm: `AES-256-CBC` with `PKCS7Padding`.
* Key encryption algorithm: `RSA/None/OAEPWithSHA256AndMGF1Padding` (MGF1 uses SHA-256), with a 2048- or 4096-bit RSA public key.
* Output encoding: hexadecimal string representation.

#### PKCS#7 encryption examples <a href="#pkcs7-encryption-examples" id="pkcs7-encryption-examples"></a>

These code samples show how to generate and process PKCS#7 enveloped-data. In the TSH API, the encrypted bytes are encoded as a hexadecimal string.

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

```java
package com.gemalto.test.pkcs7;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.MGF1ParameterSpec;
import java.util.Collection;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

import org.bouncycastle.cms.CMSAlgorithm;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.KeyTransRecipientInformation;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.bc.BcCMSContentEncryptorBuilder;
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.jcajce.JcaAlgorithmParametersConverter;
import org.bouncycastle.util.encoders.Hex;

public class TpcEncryptPkcs7 {

    private static final String DATA_TO_ENCRYPT = "{\"fpan\":\"987654321123456789\",\"issuerCardRefId\":\"abc1245784219\",\"exp\":\"1223\",\"cardholderName\":\"John\""
            + ",\"postalAddress\":{\"line1\":\"address1\",\"line2\":\"address2\",\"city\":\"City1\",\"postalCode\":\"12345\",\"state\":\"state1\",\"country\":\"Country1\"}}";

    private static final String KEY_IDENTIFIER = "a_key_id";

    private static final BouncyCastleProvider bcProvider;
    private static PrivateKey privKey;
    private static PublicKey pubKey;

    static {
        bcProvider = new BouncyCastleProvider();
        Security.addProvider(bcProvider);
    }

    public static void main(String[] args) throws Exception {

        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(2048);
        KeyPair kp = kpg.generateKeyPair();
        privKey = kp.getPrivate();
        pubKey = kp.getPublic();

        // Encrypt
        byte[] encData = encryptPKCS7(DATA_TO_ENCRYPT.getBytes("UTF-8"), pubKey);
        System.out.println("Encrypted data = " + Hex.toHexString(encData));

        // Decrypt
        byte[] result = decryptPKCS7(encData, privKey);
        System.out.println("Decrypted data = " + new String(result));

    }

    private static byte[] encryptPKCS7(byte[] plainData, PublicKey pubKey) throws Exception {

        CMSEnvelopedDataGenerator gen = new CMSEnvelopedDataGenerator();

        JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
        OAEPParameterSpec oaepParamSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
        AlgorithmIdentifier algoId = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepParamSpec);

        JceKeyTransRecipientInfoGenerator recipInfo = new JceKeyTransRecipientInfoGenerator(KEY_IDENTIFIER.getBytes(), algoId, pubKey)
                .setProvider(bcProvider);

        gen.addRecipientInfoGenerator(recipInfo);

        CMSProcessableByteArray data = new CMSProcessableByteArray(plainData);
        BcCMSContentEncryptorBuilder builder = new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC);

        CMSEnvelopedData enveloped = gen.generate(data, builder.build());

        return enveloped.getEncoded();
    }

    private static byte[] decryptPKCS7(byte[] encryptedData, PrivateKey privKey) throws Exception {
        CMSEnvelopedData enveloped = new CMSEnvelopedData(encryptedData);
        Collection<RecipientInformation> recip = enveloped.getRecipientInfos().getRecipients();
        KeyTransRecipientInformation rinfo = (KeyTransRecipientInformation) recip.iterator().next();
        return rinfo.getContent(new JceKeyTransEnvelopedRecipient(privKey).setProvider(bcProvider));
    }

}
```

{% endtab %}

{% tab title="C#" %}

```csharp
AsymmetricCipherKeyPair keyPair;

using (var txtreader = new StringReader(privateKey))
{
    keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
}

var bytesToDecrypt = Convert.FromBase64String(base64Input);

CmsEnvelopedData env = new CmsEnvelopedData(bytesToDecrypt);

KeyTransRecipientInformation recip = (KeyTransRecipientInformation)new System.Collections.ArrayList(env.GetRecipientInfos().GetRecipients())[0];

var message = recip.GetContent(keyPair.Private);

return System.Text.Encoding.GetEncoding("ISO-8859-1").GetString(message);
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/classic-tokenization/get-started/api-basics/data-encryption-and-security.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
