> 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-push-provisioning/developer-guide/data-encryption-and-authentication/card-data-encryption-pkcs-7-format.md).

# Card data encryption (PKCS#7 format)

Card details passed to the Push Provisioning SDK are encrypted. Use the TSH Issuer Gateway certificate provided during onboarding.

### Encrypted data payload <a href="#encrypted-data-payload" id="encrypted-data-payload"></a>

The payload is the JSON object serialized as a string before encryption. The JSON structure contains the following fields:

| JSON field name         | Description                                                                                                                                                                              | MOC | Comment                                                                                                 |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | ------------------------------------------------------------------------------------------------------- |
| issuerCardRefId         | <p>A unique identifier of the physical card.<br>This value is the same as the value provided in <code>authorizationCode</code> (JWT 'sub' claim).</p>                                    | M   | Note: This is not the PAN value.                                                                        |
| fpan                    | Funding card primary account number.                                                                                                                                                     | M   |                                                                                                         |
| exp                     | The expiry date in MMYY format.                                                                                                                                                          | M   |                                                                                                         |
| cardHolderName          | The cardholder name as printed on the card. For MasterCard, the maximum length for the name is 27 characters.                                                                            | M   |                                                                                                         |
| postalAddress           | <p>Object representing the postal address of the cardholder.<br><em>See the following definition.</em></p>                                                                               | C   | It is **required** for Click to Pay.                                                                    |
| phoneNumber             | <p>The cardholder's phone number.<br>Maximum lenght is 16.</p>                                                                                                                           | C   | <p>Note: It does not contain the country code.<br>It is <strong>required</strong> for Click to Pay.</p> |
| phoneNumberCountryCode  | <p>The country code of the phone number.<br>Example: "1" for USA, "33" for France, "44" for UK.<br>Maximum lenght is 4.</p>                                                              | C   | It is **required** for Click to Pay.                                                                    |
| email                   | <p>The cardholder's email.<br>Maximum lenght is 48.</p>                                                                                                                                  | C   | It is **required** for Click to Pay.                                                                    |
| issuerClientInformation | <p>The object representing the client information shared from issuer to token requestor as per information captured in the issuer systems.<br><em>See the following definition</em>.</p> | C   | It is **required** for Click to Pay.                                                                    |
| termsAndConditionsId    | This ID represents the unique ID associated to the “Terms and conditions” generated by Discover TSP during the onboarding process.                                                       | C   | It is **required** for Discover – push to Google/Samsung Pay.                                           |

#### postalAddress structure <a href="#postaladdress-structure" id="postaladdress-structure"></a>

| JSON field name | Description                                                                                                           | MOC |
| --------------- | --------------------------------------------------------------------------------------------------------------------- | --- |
| line1           | <p>First line of the billing address.<br>Maximum lenght is 64.</p>                                                    | M   |
| line2           | <p>Second line of the billing address.<br>Maximum lenght is 64.</p>                                                   | O   |
| city            | <p>The city of the billing address.<br>Maximum lenght is 32.</p>                                                      | M   |
| postalCode      | <p>The postal code (for example, zipcode in the U.S.) of the billing address.<br>Maximum lenght is 10.</p>            | M   |
| country         | <p>The country of the billing address.<br>Expressed as a 3-letter (alpha-3) country code as defined in ISO 3166-1</p> | M   |

#### issuerClientInformation structure <a href="#issuerclientinformation-structure" id="issuerclientinformation-structure"></a>

| JSON field name | Description                                                                                                                                                                                  | MOC | Comment                                                                              |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | ------------------------------------------------------------------------------------ |
| issuerAccountID | <p>Identifier of the customer account captured from issuer systems.<br>Maximum length allowed is 24 characters.</p>                                                                          | C   | <p>Note: This is not the card's PAN.<br>It is <strong>required</strong> by VISA.</p> |
| firstName       | <p>Customer first name captured from issuer systems<br>Maximum length allowed is 80 characters.</p>                                                                                          | M   |                                                                                      |
| middleName      | <p>Middle name of customer captured from the issuer systems<br>Maximum length allowed is 80 characters.</p>                                                                                  | O   |                                                                                      |
| lastName        | <p>Last name of customer captured from the issuer systems<br>Maximum length allowed is 80 characters.</p>                                                                                    | M   |                                                                                      |
| country         | Country code of the customer in ISO 3166-1 alpha-2 format.                                                                                                                                   | O   | If not provided, default is "US"                                                     |
| locale          | <p>Language in which the app communicates with the customer.<br>This is the ISO639-1 language code followed by "\_" separator then ISO 3166-1 alpha-2 country code.<br>xample: "en\_US".</p> | O   | If not provided, default is "en\_US".                                                |

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

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

A TSH certificate is provided to the issuer during onboarding. Use it to encrypt the JSON payload that contains card credentials and personal data.

#### PKCS7 format <a href="#pkcs7-format" id="pkcs7-format"></a>

PCI-sensitive data and personal information are encrypted using PKCS#7 enveloped-data format. This ensures confidentiality.

The PKCS#7 encryption scheme is defined in [RFC 2315](https://tools.ietf.org/html/rfc2315) and [RFC 5652](https://tools.ietf.org/html/rfc5652). It is supported by major cryptographic libraries.

Use these encryption parameters:

* The content encryption algorithm used is `AES256/CBC/PKCS7Padding` which uses a randomly generated AES key.
* The key encryption algorithm is `RSA/NONE/OAEPWithSHA256AndMGF1Padding` (Note: `MGF1` padding uses `SHA256`) using the TSH certificate provided during the onboarding process.
* The encryption result is then provided 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 %}

Encrypted payload example:

```
308006092A864886F70D010703A0803080020102318201513082014D0201028006497373756572303C06092A864886F70D010107302FA00F300D06096086480165030402010500A11C301A06092A864886F70D010108300D060960864801650304020105000482010014B297DCE72EBA08152514FE422FC66D7F1E216F685C1DF38E8335B4921098BB0FBFDCA33D0B7936F9810FD8E042DC2BED366B699351E0E4A55139504A469DCBA7E826C9E6C2FCB4766CC58E83C4DC21E2F5368D6FBB048354ADBAC2F121C9956E1CFDA5CE400D07D0088F847E32A2DFAD3A9BDC98A298EF78BF76262ECA387149BD9AA99C6C1B9875AD07828F00EE091F8F8598292F3A723B31FD1125F0B391595C08D249BEA1CF9F66E543CD69EB4509C191562EF6C96CF6FDDF6594B2B8EB1560C79F843FF1E16FB1313D9959605F3B99F2F18F56197D20501DED5311764FEE4E23E2F9A1CB1E9D7B507A536B254B7D8E3F50A642B73A4B2E73D4F045B2A7308006092A864886F70D010701301D060960864801650304012A041044581CF583193FD8E155FAAD73E3D817A080048180798EC2C1B0EFB6A6160B033DAED79FADBDD0DAB7139384A2CF85A85D309939744C36FE20868231C3EDEB9CE9DF3BA481344026838E65E9729519D6353472E2CE04871212FA68BFF57F2E86BD7718FCD4107E60F97170579982E129573652F7F8D7144825D1B22282305A0FA342F207641C7A2A0FE7FA9AEF5E4DA2CA718BFFAA00000000000000000000
```


---

# 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:

```
GET https://docs.payments.thalescloud.io/classic-push-provisioning/developer-guide/data-encryption-and-authentication/card-data-encryption-pkcs-7-format.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
