Skip to main content

Webhook Security

Branch uses AES with CBC mode and PKCS5 padding to encrypt sensitive data.

All sensitive data is prepended with a random initialization vector(IV) to avoid dictionary attacks.

Decryption mechanism needs to be implemented on the client side in order to read sensitive data.

Configuration#

Branch provides the AES key in BASE64 format. Clients need to be sure that they have the key provided by Branch before implementing the solution on their end.

Implementation#

Implementation can be summed up in two steps.

Decryption service#

This service accepts the BASE64 encrypted sensitive data and the BASE64 key. The service eventually calls the AES Utility function after getting the byte values.

public class DecryptionService {
/**
* Decrypts a user provided encrypted value with a user provided key
*
* @param base64EncryptedValue is the user provided base64 encrypted value
* @param base64Key is the base64 encoded key string
* @return UTF8 encoded value string
*/
public String decrypt(String base64EncryptedValue, String base64Key) {
byte[] encryptedByteValue = Base64.getDecoder().decode(base64EncryptedValue);
byte[] key = Base64.getDecoder().decode(base64Key);
byte[] decryptedValue = AESUtil.decrypt(encryptedByteValue, key);
return new String(decryptedValue, UTF_8);
}
}

AES Utility function#

This utility function is used to decrypt the value provided by the service function.

public class AESUtil {
private final String ALGORITHM = "AES";
private final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
@SneakyThrows
public byte[] decrypt(byte[] value, byte[] key) {
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
// Get the random iv from value
byte[] iv = ArrayUtils.subarray(value, 0, cipher.getBlockSize());
byte[] encryptedValue = ArrayUtils.subarray(value, cipher.getBlockSize(), value.length);
IvParameterSpec ivParam = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, ALGORITHM), ivParam);
return cipher.doFinal(encryptedValue);
}
}