Skip to main content

External Adapter Encryption and Decryption

To protect the content of data sent to an External Adapter, The message body content is first encrypted using the AES-CBC Algorithm. This uses both an Encryption Key along with a random Initialization Vector (IV). A separate Authentication Key is used to calculate a hash on the encrypted message body. The random IV and the Hash are sent along with the message as a header. This allows the message to be both decrypted and then validated as coming from a trustworthy source.

Securing a Custom External Adapter

Decrypting a Message

Your adapter implementation (or wherever you relay the messages to if your interface is acting as a proxy) must implement the ability to Decrypt and Authenticate messages received from the Fenergo Saas platform. The process for decryption is illustrated below, all languages support AES and HASH algorithms

Click Here for HQ PDF

C# Code to Decrypt and Authenticate Message

C# Code to Decrypt Data
public string dencryptAESBody()
{
//KEYS are NOT Shown but are referred to as "base64EncryptionKey" and "base64AuthKey"
//Assume they are defined elsewhere in the code.

string passedIVinBase64 = "NF/xcZ21LhFIwA31q5oMzw==";
string passedMAC = "DEL/vVP8qD8feLtJCptnyI4ZYHRMDZ8zjkZk3AZRAnw=";
string cipherText = "UE30wHm2NrYnKkXBO4TLWdxxxp/QQLY1t1qFyJb3juEIZ+kh00z" +
"uQ68k8HiPxdlFX9wrrQWgCgjJ/kDhZcnYqTTADXWCzgLH9KCVGf19nz8Yn0XNbzeKiL" +
"QCvPeIq92UJIIDbon+3eMdOcQ7TOg54jaI6A/2U7A8qWXPbxkEhkd12kKJ4xq4Kg/jf" +
"lnhDzyKjmhYKzC46CIbk9AecRIvla1oowqqzNKAOdDbu+Vqr9A=";

using var aesAlgorithm = Aes.Create();

aesAlgorithm.Key = Convert.FromBase64String(base64EncryptionKey); //Reading a key from your Keystore
aesAlgorithm.IV = Convert.FromBase64String(passedIVinBase64); //passed in from the header x-encryption-iv

Console.WriteLine($"Aes Cipher Mode : {aesAlgorithm.Mode}");
Console.WriteLine($"Aes Padding Mode: {aesAlgorithm.Padding}");
Console.WriteLine($"Aes Key Size : {aesAlgorithm.KeySize}");
Console.WriteLine($"Aes Block Size : {aesAlgorithm.BlockSize}");

//Passed in from the Message Body - Convery to byte[] for decryption
byte[] cipherTextinByteArrayFormat = Convert.FromBase64String(cipherText);
var encryptor = aesAlgorithm.CreateDecryptor();
var cipherTextConvertedFromBase64 = Convert.FromBase64String(cipherText);

using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

cryptoStream.Write(cipherTextConvertedFromBase64, 0, cipherTextConvertedFromBase64.Length);
cryptoStream.FlushFinalBlock();
var plaintext = memoryStream.ToArray();

//Authenticate the Sender by calculating the HMAC from the ciphertext
using var hmacSha = new HMACSHA256(Convert.FromBase64String(base64AuthKey)); //Decode Base64 Auth Key
var calculatedHMAC = hmacSha.ComputeHash(cipherTextinByteArrayFormat);

Console.WriteLine("Calculated Mac : " + Convert.ToBase64String(calculatedHMAC));
Console.WriteLine("Recieved Mac : " + passedMAC); //Passed in from the header x-authentication-mac
//Decrypted Data made readable with UTF8 Encoding
Console.WriteLine("Decrypted : " + Encoding.UTF8.GetString(plaintext));

//Send back plaintext
return Encoding.UTF8.GetString(plaintext);
}

The message which was sent was a Test from the Legal Entity Screening Domain. The output from the above code block is as follows:

C# Output from Code Above
Aes Padding Mode: PKCS7
Aes Key Size : 256
Aes Block Size : 128
Calculated Mac : DEL/vVP8qD8feLtJCptnyI4ZYHRMDZ8zjkZk3AZRAnw=
Recieved Mac : DEL/vVP8qD8feLtJCptnyI4ZYHRMDZ8zjkZk3AZRAnw=
Decrypted : {
"Data":
{
"AdditionalSettings":[]
},
"Id":"d4b89b85-827c-4d09-bc3e-1cbb39d52a4c",
"Tenant":"45bf62ac-e4b1-4c16-ae32-d774cd18db6d",
"ProviderId":"TestScreening",
"Type":"Test"
}

Python Code to Decrypt and Authenticate Message

Python Code to Decrypt Data
import base64
from Crypto.Cipher import AES
from Crypto.Hash import HMAC
from Crypto.Util.Padding import unpad
from io import BytesIO

def decrypt_AES_body():
# KEYS are NOT Shown but are referred to as "base64EncryptionKey" and "base64AuthKey"
# Assume they are defined elsewhere in the code.

passed_IV_in_Base64 = "NF/xcZ21LhFIwA31q5oMzw=="
passed_MAC = "DEL/vVP8qD8feLtJCptnyI4ZYHRMDZ8zjkZk3AZRAnw="
cipher_text = "UE30wHm2NrYnKkXBO4TLWdxxxp/QQLY1t1qFyJb3juEIZ+kh00z" \
"uQ68k8HiPxdlFX9wrrQWgCgjJ/kDhZcnYqTTADXWCzgLH9KCVGf19nz8Yn0XNbzeKiL" \
"QCvPeIq92UJIIDbon+3eMdOcQ7TOg54jaI6A/2U7A8qWXPbxkEhkd12kKJ4xq4Kg/jf" \
"lnhDzyKjmhYKzC46CIbk9AecRIvla1oowqqzNKAOdDbu+Vqr9A="

# Reading a key from your Keystore
encryption_key = base64.b64decode(base64EncryptionKey)
iv = base64.b64decode(passed_IV_in_Base64) # passed in from the header x-encryption-iv

aes_algorithm = AES.new(encryption_key, AES.MODE_CBC, iv)

printf("AES Cipher Mode: {aes_algorithm.mode}")
printf("AES Padding Mode: {aes_algorithm.padding.name}")
printf("AES Key Size: {aes_algorithm.key_size}")
printf("AES Block Size: {aes_algorithm.block_size}")

# Convert cipher text from base64 to bytes for decryption
cipher_text_bytes = base64.b64decode(cipher_text)

# Decrypt cipher text
plaintext = aes_algorithm.decrypt(cipher_text_bytes)
plaintext = unpad(plaintext, AES.block_size)

# Authenticate the Sender by calculating the HMAC from the ciphertext
hmac_sha = HMAC.new(base64.b64decode(base64AuthKey)) # Decode Base64 Auth Key
calculated_hmac = hmac_sha.digest()

print("Calculated Mac:", base64.b64encode(calculated_hmac).decode())
print("Received Mac:", passed_MAC) # Passed in from the header x-authentication-mac
print("Decrypted:", plaintext.decode())

# Send back plaintext
return plaintext.decode()

Encrypting and Signing a Message

Click Here for HQ PDF

C# Code to Encrypt and Sign Message

C# Code to Encrypt Data
public async Task encryptAESBody()
{
//STEP - 1 Prepare The Message
var plaintext = "{ \"response\":{ }, \"id\":\"d4b89b85-827c-4d09-bc3e-1cbb39d52a4c\", " +
"\"tenant\":\"xxxxxxx-Your-Tenant-Id-xxxxxx\", \"providerId\":\"TestScreening\", " +
"\"type\":\"Test\", \"status\":\"Success\", \"errorDetails\":null }";
byte[] plaintextAsByteArray = Encoding.UTF8.GetBytes(plaintext);

//STEP - 2 Gnerate IV and Encrypt Message Bodye
using var aesAlgorithm = Aes.Create();

aesAlgorithm.Key = Convert.FromBase64String(base64EncryptionKey); //Reading a key from your Keystore
aesAlgorithm.GenerateIV();
aesAlgorithm.Mode = CipherMode.CBC;
var encryptor = aesAlgorithm.CreateEncryptor();

using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plaintextAsByteArray, 0, plaintextAsByteArray.Length);
cryptoStream.FlushFinalBlock();
var cipherText = memoryStream.ToArray();

//STEP - 3 Calculate the Authentication Hash
using var hmacSha = new HMACSHA256(Convert.FromBase64String(base64AuthKey));
var calculatedHMAC = hmacSha.ComputeHash(cipherText);

Console.WriteLine("Base64 IV : " + Convert.ToBase64String(aesAlgorithm.IV));
Console.WriteLine("Base64 MAC : " + Convert.ToBase64String(calculatedHMAC));
Console.WriteLine("Base64 Body : " + Convert.ToBase64String(cipherText));

//STEP - 4 & 5 Add the Headers and Send The Message
//Your Code Implementation to Send Encrypted Message
}

The output from the above code block is as follows:

C# Output from Code Above
Base64 IV   : /O0hpcmWjzWrCxpvwAp1fA==
Base64 MAC : NfXp/n8vpevd+V7uc/ORKSZ7HIqUo2fQwIebCATb7Mg=
Base64 Body : tnktn65X7Niu6ZU7nn8W/O4gFq1fd+EUk9uMzbqMLB7DOfisUMGkXtxuhFd+PYTaTk2+LNss8tn50AC5K1cONVDRJylyAffMGmG2ihRNNYIZk+UU2ch3NLve5ZDqiH6xXJoOaVTfqgPvSuWyu96gDTpohqSTobtc/CItO473ioQnrOkwxKIzjDcP+c8rb5mE8pSTYpI10+NuaEzKUGwEVULRp+wCBvWdxwHfF7786Ad6lqpGfpqvOOut0gelLoEYWvQOQy0tWgsR8Ez49UBxOg==

Python Code to Encrypt and Sign Message

Python Code to Encrypt Data
import base64
import hashlib
from Crypto.Cipher import AES
from Crypto.Hash import HMAC
from Crypto.Util.Padding import pad
from io import BytesIO

async def encrypt_AES_body():
# STEP - 1 Prepare The Message
plaintext = "{ \"response\":{ }, \"id\":\"d4b89b85-827c-4d09-bc3e-1cbb39d52a4c\", " \
"\"tenant\":\"xxxxxxx-Your-Tenant-Id-xxxxxx\", \"providerId\":\"TestScreening\", " \
"\"type\":\"Test\", \"status\":\"Success\", \"errorDetails\":null }"
plaintext_as_byte_array = plaintext.encode('utf-8')

# STEP - 2 Generate IV and Encrypt Message Body
aes_algorithm = AES.new(base64.b64decode(base64EncryptionKey), AES.MODE_CBC)
iv = aes_algorithm.iv
encryptor = aes_algorithm.encryptor()

# Encrypt plaintext
cipher_text_bytes = encryptor.update(pad(plaintext_as_byte_array, AES.block_size)) + encryptor.finalize()

# STEP - 3 Calculate the Authentication Hash
hmac_sha = HMAC.new(base64.b64decode(base64AuthKey), digestmod=hashlib.sha256)
hmac_sha.update(cipher_text_bytes)
calculated_hmac = hmac_sha.digest()

print("Base64 IV :", base64.b64encode(iv).decode())
print("Base64 MAC :", base64.b64encode(calculated_hmac).decode())
print("Base64 Body :", base64.b64encode(cipher_text_bytes).decode())

# STEP - 4 & 5 Add the Headers and Send The Message
# Your Code Implementation to Send Encrypted Message