For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Dashboard
GuidesAPI ReferenceSDKs
GuidesAPI ReferenceSDKs
  • Get Started
    • Overview and Solutions
    • Choose an Integration
    • Quickstart
    • Branding Guidelines
    • Get Support
  • Accept Payments
    • Instant Payments
    • Trustly Pay
    • Recurring Payments
    • Scan and Pay
    • Remember Me
    • Payment Integration Checklist
  • Send Money
    • Send Payouts Using Online Banking
    • Send Payouts Using Account Information
    • International Transfers
  • Retrieve Data
    • Verify Accounts Using Online Banking
    • Verify Accounts Using Micro-Deposits
    • Retrieve Bank and User Information
    • Tokenize Bank Information
    • Trustly ID
    • Insights Data
  • Core Concepts
    • Key Concepts
    • The Establish Data Object
    • Transactions and Transaction IDs
    • Tokens and Account Security
    • Redirect URLs and Return Flow
    • Webhooks and Events
    • Content Strings
  • API Fundamentals
    • Authentication and OAuth
    • Secure Requests and Signature Validation
      • Generate request signatures
      • Validate the redirect signature
      • Validate the notification signature
      • Encrypt a field value
    • Idempotency
    • Testing
    • Status codes and type definitions
  • Manage Your Integration
    • Go-Live Checklist
    • Merchant Portal
    • Reports and Reconciliation
    • Refresh Bank Authorization
    • Override Risk Declines
    • VIP Tiers
    • Financial Institution Status
Dashboard
Products
PaymentsDataPayouts
Company
AboutCareersContact Sales

Terms of Use | Privacy Policy | © 2026 Trustly, Inc.

Developer-friendly docs for your API
GitHub|Contact Support|Business Help Center|Merchant Portal
Terms of Use|Privacy Policy|© 2026 Trustly, Inc.
Developer-friendly docs for your API
LogoLogo
North AmericaEurope
North AmericaEurope
API FundamentalsSecure Requests and Signature Validation

Encrypt a field value

|View as Markdown|Open in Claude|
Was this page helpful?
Previous

Validate the notification signature

Next

Idempotency

Built with

It is also possible to encrypt specific attributes sent on the establish data object to Trustly. The encryption is done using the AES-256-CBC algorithm and your Trustly accessKey as the encryption key. The encrypted attributes start with the prefix crypt2: and the full encrypted value (including the prefix) must be used when calculating the request signature.

Example code snippet:

1const Crypto = require('crypto');
2
3const accessKey = 'YOUR_ACCESS_KEY';
4const attributeValue = '123123456'; //can be any PII or other sensitive data
5
6const algorithm = 'aes-256-cbc';
7const encoding = 'base64';
8
9const iv = Buffer.from(Crypto.randomBytes(16)).toString('hex').slice(0, 16);;
10
11const keyHash = Crypto.createHash('sha256').update(accessKey).digest();
12
13const cipher = Crypto.createCipheriv(algorithm, keyHash.slice(0, 32), iv);
14cipher.setAutoPadding(true);
15
16let encrypted = cipher.update(iv + attributeValue, 'utf8', encoding);
17encrypted += cipher.final(encoding);
18
19console.log('response', 'crypt2:' + encrypted);
1public class EncryptedAttribute {
2 public static final String AES_ECB_PKCS_5_PADDING = "AES/ECB/PKCS5Padding";
3 private static volatile SecureRandom numberGenerator = new SecureRandom();
4 public static byte[] salt(byte[] data) {
5 byte[] salt = new byte[4];
6 numberGenerator.nextBytes(salt);
7 byte[] salted = new byte[data.length + salt.length];
8 System.arraycopy(salt, 0, salted, 0, salt.length);
9 System.arraycopy(data, 0, salted, salt.length, data.length);
10 return salted;
11 }
12 public static byte[] unsalt(byte[] data) {
13 byte[] unsalted = new byte[data.length - 4];
14 System.arraycopy(data, 4, unsalted, 0, unsalted.length);
15 return unsalted;
16 }
17 public static String encodeBase64(byte[] binary) {
18 return Base64.getEncoder().encodeToString(binary);
19 }
20 public static byte[] decodeBase64(String str) {
21 try {
22 return Base64.getDecoder().decode(str);
23 } catch (Exception e) {
24 return new byte[0];
25 }
26 }
27 public static String encryptAttribute(String attribute, String accessKey) throws Exception {
28 if (attribute == null || attribute.length() == 0) {
29 return attribute;
30 }
31 Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
32 cipher.init(Cipher.ENCRYPT_MODE, buildKey(accessKey));
33 return "crypt:" + encodeBase64(cipher.doFinal(salt(attribute.getBytes("UTF-8"))));
34 }
35 public static String decryptAttribute(String attribute, String accessKey) {
36 if (attribute == null || accessKey == null || !attribute.startsWith("crypt2:")) { //If attribute is not
37 encrypted
38 return it
39 return attribute;
40 }
41 try {
42 Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
43 cipher.init(Cipher.DECRYPT_MODE, buildKey(accessKey));
44 return new String(unsalt(cipher.doFinal(decodeBase64(attribute.substring("crypt2:".length())))), "UTF-
45 8 ");
46 }
47 catch (Exception e) {
48 return attribute;
49 }
50 }
51 private static SecretKeySpec buildKey(String accessKey) throws Exception {
52 MessageDigest digester = MessageDigest.getInstance("SHA-256");
53 digester.update(accessKey.getBytes("UTF-8"));
54 byte[] key = Arrays.copyOf(digester.digest(), 32);
55 SecretKeySpec spec = new SecretKeySpec(key, "AES");
56 return spec;
57 }
58 }
1using System;
2using System.Linq;
3using System.Security.Cryptography;
4using System.Text;
5
6public class Program
7{
8 public static void Main()
9 {
10 const string accessKey = "YOUR_ACCESS_KEY";
11 const string attributeValue = "123123456";
12
13 var random = new Byte[16];
14 RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
15 rng.GetBytes(random);
16 var iv = BitConverter.ToString(random).Replace("-", "").Substring(0, 16);
17
18 var keyHash = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(accessKey));
19
20 Aes aes = Aes.Create();
21 aes.Key = keyHash;
22 aes.IV = UTF8Encoding.UTF8.GetBytes(iv);
23 aes.Mode = CipherMode.CBC;
24 ICryptoTransform cipher = aes.CreateEncryptor(aes.Key, aes.IV);
25
26 var inputBuffer = aes.IV.Concat(UTF8Encoding.UTF8.GetBytes(attributeValue)).ToArray();
27 var resultArray = cipher.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
28
29 var encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);
30 Console.WriteLine("crypt2:" + encrypted);
31 }
32}
  1. Create an initialization vector (iv) containing 16 random characters.
  2. Create a SHA256 hash of your accessKey.
  3. Using the first 32 characters of your accessKey hash (from step 2) and the initialization vector (from step 1), create a cipher.
  4. Using the cipher key (from step 3), the initialization vector (from step 1), and the attribute value to encrypt, update the cipher.
  5. Create an encrypted string by finalizing the cipher using base64 encoding.
  6. Concatenate crypt2: and your encrypted string, and pass the value in the establishData value that is passed to the SDK:
1customer: {
2 name: 'John Smith',
3 taxId: 'crypt2:uFVg4qGHj7ZtwSv1tkFAL7pBJ5x8zsehYgNdU51w5yA=',
4 address: {
5 country: 'US',
6 }
7},