PowerShell to iRule AES-CBC conversation using random IV values

Problem this snippet solves:

Hi Folks,

I saw recently on the DevCentral boards that people are struggeling to securely exchange AES encrypted information between a Windows System and LTM.

Although some DevCentral members already managed it by using static IV (Initialization Vectors) on both sites, this approach should be considered as a very bad practise, since it allows an adversary to pulloff certain crypto analyses/attacks which could already lead to a security breach.

The snippets below will outline how to implement AES-CBC decryption/encryption with dynamic IV values on Windows using PowerShell and on LTM using iRules. The outlined snippets are alligned to each other by using the same AES crypto settings (Key-Size, Block-Size, CBC-Mode and Padding-Mode) and IV exchange techniques to become interoperable.

The implemented IV exchange technique will generate a fresh and random IV on each single encryption and simply prepended the AES-IV to the AES-Ciphertext before passing it to the receiver. The receiver then splits the received AES-Cipherstring into the contained AES-IV and AES-Ciphertext values and finally decrypt the AES-Ciphertext by using the shared AES-Key.

From Windows to LTM

1. Import the follwing PS functions on the Windows side

function Create-AesKey($KeySize) {
    $AesManaged = New-Object "System.Security.Cryptography.AesManaged"
    $AesManaged.KeySize = $KeySize
    $AesManaged.GenerateKey()
    [System.Convert]::ToBase64String($AesManaged.Key)
}
function Encrypt-Data($AesKey, $Data) {
    $Data = [System.Text.Encoding]::UTF8.GetBytes($Data)
    $AesManaged = New-Object "System.Security.Cryptography.AesManaged"
    $AesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
    $AesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
    $AesManaged.BlockSize = 128
    $AesManaged.KeySize = 256
    $AesManaged.Key = [System.Convert]::FromBase64String($AesKey)
    $Encryptor = $AesManaged.CreateEncryptor()
    $EncryptedData = $Encryptor.TransformFinalBlock($Data, 0, $Data.Length);
    [byte[]] $EncryptedData = $AesManaged.IV + $EncryptedData
    $AesManaged.Dispose()
    [System.Convert]::ToBase64String($EncryptedData)
}
function Decrypt-Data($AesKey, $Data) {
    $Data = [System.Convert]::FromBase64String($Data)
    $AesManaged = New-Object "System.Security.Cryptography.AesManaged"
    $AesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
    $AesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
    $AesManaged.BlockSize = 128
    $AesManaged.KeySize = 256
    $AesManaged.IV = $Data[0..15]
    $AesManaged.Key = [System.Convert]::FromBase64String($AesKey)
    $Decryptor = $AesManaged.CreateDecryptor();
    $DecryptedData = $Decryptor.TransformFinalBlock($Data, 16, $Data.Length - 16);
    $aesManaged.Dispose()
    [System.Text.Encoding]::UTF8.GetString($DecryptedData)
}

2. Generate a fresh 256bit AESKey on your Windows System and store it locally as well as on your F5.

Create-AesKey 256
iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU=

3. Encrypt some data using the AES-Shared-Key

$encrypted = Encrypt-Data " iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU=" "Hello World!" 
$encrypted
W5xFrWz72U/vt95HG6fHWIuDDHpuhj2HB42E4SIrNwo=

Note: Every single encryption should have a different outcome. Thanks to the random IV!

4. Pass the AES-Cipherstring to your LTM and decrypt it using the snippet below

set aes_key [b64decode "iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU="]
set aes_cipherstring [b64decode "W5xFrWz72U/vt95HG6fHWIuDDHpuhj2HB42E4SIrNwo="]
binary scan $aes_cipherstring a16a* aes_iv aes_ciphertext
set aes_plaintext [CRYPTO::decrypt -alg aes-256-cbc -key $aes_key -iv $aes_iv $aes_ciphertext]
log local0.debug "Plaintext = $aes_plaintext"

Log Output : Plaintext = Hello World!

From LTM to Windows

1. AES encrypt some data on your LTM using the snippet below

set aes_key [b64decode "iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU="]
set aes_plaintext "Hello World!!"
set aes_iv [CRYPTO::keygen -alg random -passphrase "MyIVSeed" -len 128]
set aes_ciphertext [CRYPTO::encrypt -alg aes-256-cbc -key $aes_key -iv $aes_iv $aes_plaintext]
set aes_cipherstring [b64encode [binary format a*a* $aes_iv $aes_ciphertext]]
log local0.debug "Cipherstring = $aes_cipherstring"

Log Output : Cipherstring = vCIizWalo4KWO+3bLuTUp5iD0J3kArrcZS1fKDue89M=

Note: Every single encryption should also have a different outcome. Thanks to the random IV!

2. Pass the AES-Cipherstring to your Windows system and decrypt it using the snippet below

$decrypted = Decrypt-Data "iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU=" "vCIizWalo4KWO+3bLuTUp5iD0J3kArrcZS1fKDue89M="
$decrypted
Hello World!!

Cheers, Kai

How to use this snippet:

See above...

Code :

See above...
Updated Jun 06, 2023
Version 2.0
No CommentsBe the first to comment