How symmetric encryption works in MySQL — AES key sizes, CBC vs ECB mode, MySQL’s AES_ENCRYPT limitations, and when to encrypt in SQL vs the application layer.
Use this file to discover all available pages before exploring further.
VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
Symmetric encryption uses the same key to encrypt and decrypt. It’s the right tool when you need to store sensitive data and retrieve the original value later — unlike hashing, which is one-way. MySQL has AES_ENCRYPT() built in, but it defaults to an insecure mode. This guide covers the trade-offs, how to use AES correctly in MySQL, and when to do encryption in SQL versus the application layer.
MySQL’s AES_ENCRYPT(data, key) uses 128-bit AES with the key derived from the key string. The default mode is ECB — Electronic Codebook — where each 16-byte block is encrypted independently. ECB is deterministic: the same 16-byte input always produces the same 16-byte output. That makes patterns visible in the ciphertext.
-- ECB default: identical inputs → identical outputsSELECT HEX(AES_ENCRYPT('same data', 'key')) AS first, HEX(AES_ENCRYPT('same data', 'key')) AS second;-- Both columns are identical
CBC mode (Cipher Block Chaining) fixes this by XOR-ing each block with the previous ciphertext before encrypting, using a random initialization vector (IV) for the first block. The same plaintext produces a different ciphertext on every call.MySQL supports CBC, but you have to opt in by changing block_encryption_mode and managing the IV yourself:
VillageSQL’s vsql_crypto extension provides encrypt() and decrypt(), which use AES-CBC with a random IV generated per call. The IV is prepended to the ciphertext — no extra column, no extra parameter.
INSTALL EXTENSION vsql_crypto;
SET @key = 'my-32-byte-key-here-padded-to-32'; -- exactly 32 bytes for AES-256-- Different ciphertext every call — CBC with random IVSELECT HEX(encrypt('same data', @key, 'aes-256')) AS first, HEX(encrypt('same data', @key, 'aes-256')) AS second;-- Both columns differ-- Round-tripSET @enc = encrypt('sensitive data', @key, 'aes-256');SELECT decrypt(@enc, @key, 'aes-256');-- Returns: sensitive data
256-bit — use for regulated data (PII, HIPAA, PCI)
Key length is enforced by the byte count of the key string — shorter keys are zero-padded, longer are truncated. Check LENGTH(@key) if you’re getting unexpected behavior.
Encrypting in SQL is convenient but has trade-offs:
SQL-layer encryption
Application-layer encryption
Key location
In queries/triggers (risky if visible in logs)
In secrets manager, not in SQL
Searchability
Can’t filter on encrypted values
Same limitation
Bulk operations
Encryption happens in DB
Must go through app code
Key rotation
Requires re-encrypting all data in SQL
Can decrypt with old key, re-encrypt with new key in app
Audit trail
Query logs may expose plaintext
App controls what’s logged
SQL-layer encryption is useful for protecting data at rest when you trust the application but worry about database-level access (backups, read replicas, compromised DB credentials). Application-layer encryption gives you more control over keys and avoids putting plaintext anywhere near SQL logs.For column-level patterns and schema design, see Encrypting Columns in MySQL.
What’s the difference between symmetric and asymmetric encryption?
Symmetric encryption (AES) uses the same key to encrypt and decrypt. It’s fast and well-suited for bulk data. Asymmetric encryption (RSA) uses a public key to encrypt and a private key to decrypt — useful for key exchange, but too slow for bulk data. For storing sensitive column data, symmetric AES is the right choice.
Not directly. To find rows by an encrypted value, you’d have to decrypt every row — a full table scan. A common workaround: store a keyed hash (HMAC) of the plaintext in a separate indexed column for equality lookups. This leaks that two rows have the same value but not what the value is.
Read every row, decrypt with the old key, re-encrypt with the new key, write back. For large tables, do this in batches. This is the main operational cost of SQL-layer encryption. Envelope encryption (encrypting the data key with a master key) lets you rotate the master key without touching the data.
Does AES encryption protect against SQL injection?
No. Encryption protects the stored values. SQL injection is an input validation problem — an attacker who can run arbitrary SQL can call decrypt() directly.