Cribl has the fantastic ability to encrypt data at the field level as it passes through. To do this we often use the Mask function with the replace value referencing C.Crypto:

-
I had previously created a key in Group Settings → Security → Encryption Keys
-
AND copied the key value for safe keeping. You only have 1 chance to do this!
-
-
I reference the key ID in the above C.Crypto call - B1QQsz
-
I’m applying the encryption to the entire secret_field value: (.*)
-
g1 references that matched data
-
This is cool. But what do we do when we need to recover the value and we don’t have the same Workergroup to run it back through? Let’s go through the whole process.
Create the Key and Keep the Value
Visit Settings → Security → Encryption Keys and click add. I used the aes-256-cbc algorithm, the local KMS, and specified a key class of 0. I did not specify an Expiration time, nor did I use an initialization vector. With no vector specified, the default value is 16 hex 0s.
Important: When you click save you will be presented with the encryption key. This is your only chance to save this key. Without it, you won’t be able to extract encrypted values outside of this worker group. Save the key value in a safe place.
Note the key ID after saving as well. We’ll need to reference that. (But it will be available any time, unlike the value.)
Create Some Test Data
To make this easy, I created sample encrypted data by popping up a filter edit screen. You can do this in many places. In this case, I went to routes, chose the first one, and popped out the filter editor. Then I added the C.Crypto call as mentioned above to test the output:

Decode the Encrypted String
Using the pycryptodome python library, and Chad Gippity’s help, I created the below script. Key stumbling points:
-
Getting the Crypto module installed. Had to use pycryptodome library.
-
The encrypted value is not padded. Had to add a little if function to do that.
-
The default IV is all zeroes, and had to account for that.
from base64 import b64decode
from binascii import unhexlify
from Crypto.Cipher import AES
def decrypt_aes_cbc(encrypted_base64, key_hex, iv):
# Decode inputs from hex/base64 formats
# before we can unb64 the encrypted data, make sure we're padded correctly
missing_padding = len(encrypted_base64) % 4
if missing_padding:
encrypted_base64 += '=' * (4 - missing_padding)
# then unhexify and unb64
key = unhexlify(key_hex)
encrypted = b64decode(encrypted_base64)
# Create cipher object and decrypt
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(encrypted)
# Remove PKCS7 padding (commonly used in AES-CBC)
pad_len = plaintextb-1]
if isinstance(pad_len, str):
pad_len = ord(pad_len) # Py2 compat, rarely needed
plaintext = plaintext :-pad_len]
return plaintext.decode('utf-8')
# Example usage
if __name__ == "__main__":
# Replace with your actual Cribl values:
encrypted_base64 = "VPuxLjf4ByJgja2GLwsXXQ"
key_hex = "0a31961cfbb20966bc2931b38788a07a86a845b6fb4f2c2398d54b9c2618a43f"
iv_hex = b'\x00' * 16
result = decrypt_aes_cbc(encrypted_base64, key_hex, iv_hex)
print("Decrypted plaintext:\n", result)
And the output:
bash-3.2$ python3 test.py
Decrypted plaintext:
test
Hurray! We got the “test” string. Obviously this isn’t very useful as it is, but as a POC and sample of the mechanism, it should provide a starting point to create a more robust tool.
Hope this helps!