Encrypt Data at Rest
Use this guide to set up, configure, and verify Transparent Disk Encryption (TDE) for KDB-X.
Overview
- Check system requirements: Verify hardware and software prerequisites
- Generate the master key: Create a localized encryption key
- Start KDB-X with the master key: Initialize the process securely
- Set encryption defaults: Configure automatic encryption defaults
- Verify data encryption: Confirm data is written securely
- Rotate the master key: Maintain security through key rotation
- Measure performance: Benchmark the encryption overhead
- Review security risks: Understand metadata visibility risks
- Explore advanced encryption topics: Read the white paper
Check system requirements
First, verify that your environment supports these essential requirements:
- Hardware: A CPU with the AES-NI instruction set
- Software: OpenSSL 1.1.1 or later
Check for AES-NI support
Run the command for your OS to check for aes support:
grep -m1 -o aes /proc/cpuinfo
sysctl -a | grep machdep.cpu.features | grep AES
# Windows has no native command to check AES-NI.
# Download Coreinfo from Microsoft Sysinternals, then run:
./coreinfo.exe -f | Select-String "AES"
Performance impact
Hardware acceleration speeds up encryption. Without the AES-NI instruction set, database operations on encrypted data are significantly slower.
Check OpenSSL version
Next, ensure you have the correct software. You need OpenSSL 1.1.1+ to generate secure keys.
# Check installed OpenSSL version
openssl version
OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
Verify KDB-X OpenSSL linkage
You can also check the version KDB-X uses from within the process:
q)// Check the OpenSSL version KDB-X is using
q)(-26!)[]
SSLEAY_VERSION | OpenSSL 3.0.13 30 Jan 2024
SSL_CERT_FILE | /usr/lib/ssl/server-crt.pem
SSL_CA_CERT_FILE | /usr/lib/ssl/cacert.pem
SSL_CA_CERT_PATH | /usr/lib/ssl
SSL_KEY_FILE | /usr/lib/ssl/server-key.pem
SSL_CIPHER_LIST | ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RS..
SSL_VERIFY_CLIENT| NO
SSL_VERIFY_SERVER| YES
Generate the master key
With requirements met, you need a master key to encrypt data. This master 256-bit AES key encrypts the unique Data Encryption Keys (DEKs) for each file.
-
Use OpenSSL to generate a secure key:
openssl rand 32 | openssl aes-256-cbc -md SHA256 -salt -pbkdf2 -iter 50000 -out testkek.key -pass pass:"MySecurePassword!"Command breakdown
rand 32: Generates 32 random bytesaes-256-cbc: Uses the AES cipher with a 256-bit key-md SHA256: Uses SHA-256 for key derivation-salt: Adds a random salt to protect against dictionary attacks-pbkdf2: Uses the newer Password-Based Key Derivation Function 2-iter 50000: Performs 50,000 iterations to slow down brute-force attacks-pass ...: Automates password entry (Avoid this in production command history)
-
Protect the key file: The
testkek.keyfile is critical. Therefore, you must:- Save it outside your database directory
- Back up the key and its password securely
- Restrict file permissions to the KDB-X process owner
Start KDB-X with the master key
Once the key is generated, initialize KDB-X with encryption support by loading the master key at startup.
-
Set the environment variable: Store the password in an environment variable to avoid hardcoding it.
export KDB_MASTER_KEY_PW="MySecurePassword!" q$env:KDB_MASTER_KEY_PW = "MySecurePassword!" q -
Load the key: Then, use the
-36!function to read and decrypt the key file.q)// Load master key using the environment variable q)-36!(`:testkek.key; getenv `KDB_MASTER_KEY_PW) q)show $[-36!(::);"Master key loaded"; "Failed to load master key"] "Master key loaded"
Set encryption defaults
The process can now decrypt data. However, to encrypt new data automatically, you must configure the .z.zd handler.
Set .z.zd to (blockSize; algorithm; compressionLevel):
q)// Block size 17 (128kb), Algo 16 (AES256CBC), Level 0 (No compression)
q).z.zd:17 16 0;
Supported Algorithms
| ID | Description | Usage |
|---|---|---|
16 |
AES-256-CBC | Encryption only. Best for data where compression adds overhead |
18 |
Gzip + AES-256-CBC | Compression then encryption. Warning: Risk of side-channel attacks (CRIME/BREACH) |
1 |
IPC | No encryption |
Verify data encryption
After configuring the defaults, verify your configuration by writing and inspecting a test file.
Write a simple table to disk:
q)// Enable encryption
q).z.zd:17 16 0;
q)// Save an encrypted table
q)`:secure_table set([]time:10?.z.t;sym:10?`3;price:10?100f);
`:secure_table
q)// 1. Verify file signature
q)header:first system "head -c 8 secure_table";
q)show signature:$[header like "kxzippEd*";"Matched";"Failed"];
"Matched"
q)// 2. Verify compression stats
q)stats:-21!`:secure_table;
q)show algorithm:$[stats[`algorithm]=16i;"AES-256 Encrypted";"Unencrypted"];
"AES-256 Encrypted"
File signatures
| Signature | Status | Description |
|---|---|---|
kxzippEd |
Encrypted | File is encrypted |
kxzipped |
Unencrypted | File is compressed but not encrypted |
Rotate the master key
In addition to initial setup, rotate your master key regularly. This re-encrypts the key file, not your data, so it is safe and fast.
Decrypt the key with the old password, pipe it to a new encryption command, and replace the file:
OLD_PW='MySecurePassword!'
NEW_PW='NewRotatedPassword2026!'
# Decrypt -> Pipe -> Encrypt
openssl aes-256-cbc -md SHA256 -d -iter 50000 -in testkek.key -pass pass:"$OLD_PW" | openssl aes-256-cbc -md SHA256 -salt -pbkdf2 -iter 50000 -out testkek.key.new -pass pass:"$NEW_PW"
# Replace key file
mv testkek.key.new testkek.key
# Update session variable
export KDB_MASTER_KEY_PW="$NEW_PW"
echo "Key rotation complete."
$OLD_PW = 'MySecurePassword!'
$NEW_PW = 'NewRotatedPassword2026!'
# Decrypt -> Pipe -> Encrypt
openssl aes-256-cbc -md SHA256 -d -iter 50000 -in testkek.key -pass pass:"$OLD_PW" | openssl aes-256-cbc -md SHA256 -salt -pbkdf2 -iter 50000 -out testkek.key.new -pass pass:"$NEW_PW"
# Replace key file
Move-Item -Path "testkek.key.new" -Destination "testkek.key" -Force
# Update session variable
$env:KDB_MASTER_KEY_PW = $NEW_PW
Write-Host "Key rotation complete."
Measure performance
Finally, be aware that encryption adds overhead. Measure the impact on your hardware with a benchmark.
-
Create
ebench.q:/ Load master key -36!(`:testkek.key;getenv`KDB_MASTER_KEY_PW) / Write an encrypted table (`:etest;20;16;0) set 100000000?10000 / Time the read operation system "ts max get`:etest" -
Run with acceleration (AES-NI):
q ebench.q -
Run without acceleration to see the difference:
# Disable AES-NI for OpenSSL
OPENSSL_ia32cap="~0x200000200000000" q ebench.q
# Disable AES-NI for OpenSSL
$env:OPENSSL_ia32cap = "~0x200000200000000"
q ebench.q
$env:OPENSSL_ia32cap = $null
Review security risks
Visible metadata
The file content is encrypted, but file system metadata remains visible:
- Directory names: Table names
- Filenames: Column names (in splayed directories)
- .d files: Column ordering files
Explore advanced encryption topics
This guide covers standard encryption setup. For deeper technical details and architectural considerations, read the Data At Rest Encryption white paper, which covers:
- TDE vs. Full Disk Encryption (FDE): Comparison of security models and PCI-DSS compliance
- File locking: Managing concurrency for encrypted enumeration domains
- Compression risks: Understanding side-channel attacks when combining compression and encryption
- Cryptographic internals: Technical details on AES256CBC, PBKDF2, and HMAC-SHA256 implementation
Summary
In this guide, you learned how to:
- Verify requirements: Ensure CPU support (AES-NI) and OpenSSL versions
- Generate keys: Create secure master keys using OpenSSL
- Enable encryption: Start KDB-X with a master key and configure defaults
- Verify protection: Confirm file signatures and encryption status
- Rotate keys: Securely update master keys without re-encrypting data
- Measure performance: Benchmark the encryption overhead