Encrypt a field value

View as Markdown

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},