For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

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