Encrypt a field value

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:

const Crypto = require('crypto');

const accessKey = 'YOUR_ACCESS_KEY';
const attributeValue = '123123456'; //can be any PII or other sensitive data

const algorithm = 'aes-256-cbc';
const encoding = 'base64';

const iv = Buffer.from(Crypto.randomBytes(16)).toString('hex').slice(0, 16);;

const keyHash = Crypto.createHash('sha256').update(accessKey).digest();

const cipher = Crypto.createCipheriv(algorithm, keyHash.slice(0, 32), iv);
cipher.setAutoPadding(true);

let encrypted = cipher.update(iv + attributeValue, 'utf8', encoding);
encrypted += cipher.final(encoding);

console.log('response', 'crypt2:' + encrypted);
public class EncryptedAttribute {
    public static final String AES_ECB_PKCS_5_PADDING = "AES/ECB/PKCS5Padding";
    private static volatile SecureRandom numberGenerator = new SecureRandom();
    public static byte[] salt(byte[] data) {
        byte[] salt = new byte[4];
        numberGenerator.nextBytes(salt);
        byte[] salted = new byte[data.length + salt.length];
        System.arraycopy(salt, 0, salted, 0, salt.length);
        System.arraycopy(data, 0, salted, salt.length, data.length);
        return salted;
    }
    public static byte[] unsalt(byte[] data) {
        byte[] unsalted = new byte[data.length - 4];
        System.arraycopy(data, 4, unsalted, 0, unsalted.length);
        return unsalted;
    }
    public static String encodeBase64(byte[] binary) {
        return Base64.getEncoder().encodeToString(binary);
    }
    public static byte[] decodeBase64(String str) {
        try {
            return Base64.getDecoder().decode(str);
        } catch (Exception e) {
            return new byte[0];
        }
    }
    public static String encryptAttribute(String attribute, String accessKey) throws Exception {
        if (attribute == null || attribute.length() == 0) {
            return attribute;
        }
        Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, buildKey(accessKey));
        return "crypt:" + encodeBase64(cipher.doFinal(salt(attribute.getBytes("UTF-8"))));
    }
    public static String decryptAttribute(String attribute, String accessKey) {
        if (attribute == null || accessKey == null || !attribute.startsWith("crypt2:")) { //If attribute is not
            encrypted
            return it
            return attribute;
        }
        try {
            Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
            cipher.init(Cipher.DECRYPT_MODE, buildKey(accessKey));
            return new String(unsalt(cipher.doFinal(decodeBase64(attribute.substring("crypt2:".length())))), "UTF-
                8 ");
            }
            catch (Exception e) {
                return attribute;
            }
        }
        private static SecretKeySpec buildKey(String accessKey) throws Exception {
            MessageDigest digester = MessageDigest.getInstance("SHA-256");
            digester.update(accessKey.getBytes("UTF-8"));
            byte[] key = Arrays.copyOf(digester.digest(), 32);
            SecretKeySpec spec = new SecretKeySpec(key, "AES");
            return spec;
        }
    }
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

public class Program
{
	public static void Main()
	{
		const string accessKey = "YOUR_ACCESS_KEY";
		const string attributeValue = "123123456";

		var random = new Byte[16];
		RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
		rng.GetBytes(random);
		var iv = BitConverter.ToString(random).Replace("-", "").Substring(0, 16);
		
		var keyHash = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(accessKey));
		
        Aes aes = Aes.Create();
        aes.Key = keyHash;
        aes.IV = UTF8Encoding.UTF8.GetBytes(iv);
        aes.Mode = CipherMode.CBC;
        ICryptoTransform cipher = aes.CreateEncryptor(aes.Key, aes.IV);
		
		var inputBuffer = aes.IV.Concat(UTF8Encoding.UTF8.GetBytes(attributeValue)).ToArray();
		var resultArray = cipher.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
		
        var encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);
		Console.WriteLine("crypt2:" + encrypted);
	}
}
  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:
customer: {
  name: 'John Smith',
  taxId: 'crypt2:uFVg4qGHj7ZtwSv1tkFAL7pBJ5x8zsehYgNdU51w5yA=',
  address: {
    country: 'US',
  }
},