Introduction to Sending Secure Data
ImportantChanges to the keys used for sending secure data need to be made in both UAT and Production environments.
Thredd enables customers to be able to send secure data to a cardholder. This is available to customers with or without PCI DSS compliance.
ImportantThredd does not authenticate the device or the identity of the device holder. We strongly recommend that you implement policy-based controls to identify cardholders.
Two keys will be provided by Thredd during onboarding. You must convert them to byte arrays to use the encrypted data endpoint.
- A RSA-4096 public key used as a wrap key for encrypting the request.
- A RSA-4096 public key used as a sign key to verify the response of the request.
NoteThredd provide the keys as a certificate or a raw key. Contact your Implementation Manager to let them know which you would prefer.
To use the encryption endpoints, combine the Wrap RSA key with an encrypted AES key. The AES key must first be created, then encrypted.
The following diagram describes how to use the Sending Secure Data endpoint.

Creating an AES Key
When creating an AES key, ensure that the key:
- Is uniquely generated for each request.
- Has a length that is no smaller than 256 bits.
- Is encrypted with your RSA-4096 wrap key, provided to you in Hex format by Thredd.
See the below examples on how to generate an AES key using Python and NodeJs.
import os, json, base64
from cryptography.hazmat.primitives import hashes, serialization, padding as sym_padding
from cryptography.hazmat.primitives.asymmetric import padding as asym_padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.exceptions import InvalidSignature
def get_card_data(public_token, wrap_pub_pem, sign_pub_pem, send_request):
# 1. Fresh AES-256 session key
aes_key = os.urandom(32)const crypto = require('crypto');
async function getCardData(publicToken, wrapPubPem, signPubPem, sendRequest) {
const aesKey = crypto.randomBytes(32);
}The script returns an unencrypted AES Key, used to decrypt the response.
Encrypt the Key
When you have the unencrypted key, you need to encrypt it so that it can be used in the body of the Get Card Data endpoint. See the below examples on how to encrypt an AES key using Python and NodeJs.
ImportantThe key must be encrypted in the following way:
- The algorithm must be SHA256 hash
- The padding must be MGF1 with SHA56
We recommend validating the libraries and your code language to ensure there are no default values.
wrap_pub = serialization.load_pem_public_key(wrap_pub_pem)
encrypted_key = wrap_pub.encrypt(
aes_key,
asym_padding.OAEP(
mgf=asym_padding.MGF1(hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None,
),
)const encryptedKey = crypto.publicEncrypt(
{
key: wrapPubPem,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256',
},
aesKey,
);The script returns an encrypted AES Key, use to populate the body of the Get Card Data endpoint.
ImportantIf you do not have PCI DSS certification, all key generation encryption, and decryption must happen on the device. You must send only encrypted data to your backend systems. Thredd is only responsible for ensuring the data is encrypted as it leaves our estate. Thredd clients are responsible for ensuring they are not breaching PCI DSS rule.
Updated 12 days ago
