Complete reference for MariaDB encryption and security functions covering AES_ENCRYPT, AES_DECRYPT, MD5, SHA1, SHA2, PASSWORD, COMPRESS, RANDOM_BYTES, and KDF. Every function includes syntax, security notes, and deprecation warnings. Updated for MariaDB 11.x.
MariaDB encryption functions provide hashing and symmetric encryption directly in SQL. AES_ENCRYPT() and AES_DECRYPT() implement AES-128/256 encryption, SHA2() supports SHA-224 through SHA-512, and RANDOM_BYTES() generates cryptographically secure random bytes. Note that MD5() and SHA1() are considered cryptographically broken for security purposes and should only be used for checksums or non-security hashing. The PASSWORD() function used for MariaDB authentication is deprecated in favour of the native password plugin.
AES_ENCRYPT
The init_vector parameter and block_encryption_mode support were added in MariaDB 10.0.15.→ VARBINARY
Encrypts a string using the AES (Advanced Encryption Standard) algorithm. The key and optional initialization vector determine the ciphertext. The encryption mode is controlled by the @@block_encryption_mode session variable (default: aes-128-ecb).
Signature
AES_ENCRYPT(str, key_str[, init_vector])
Parameters
Parameter
Type
Description
str
VARCHAR
The plaintext string to encrypt
key_str
VARCHAR
The encryption key; padded or truncated to the required key length
init_vector
VARCHAR
Optional initialization vector required for CBC/CFB/OFB modes; must be 16 bytes
The default block_encryption_mode is aes-128-ecb which is deterministic — identical plaintexts produce identical ciphertexts, leaking patterns and enabling frequency analysis.
✓ Instead: Set block_encryption_mode to 'aes-256-cbc' and always generate a fresh IV with RANDOM_BYTES(16). Store IV in a separate column alongside the ciphertext.
⇄ vs MySQL: Identical in MySQL 5.6+. The block_encryption_mode variable was added in MySQL 5.6.17.
⇄ vs PostgreSQL: PostgreSQL provides pgp_sym_encrypt() via the pgcrypto extension; no native AES_ENCRYPT equivalent.
The init_vector parameter was added in MariaDB 10.0.15.→ VARCHAR
Decrypts a ciphertext that was encrypted with AES_ENCRYPT() using the same key and mode. Returns the original plaintext string, or NULL if decryption fails (wrong key or corrupt data).
Signature
AES_DECRYPT(crypt_str, key_str[, init_vector])
Parameters
Parameter
Type
Description
crypt_str
VARBINARY
The encrypted binary string produced by AES_ENCRYPT()
key_str
VARCHAR
The decryption key; must match the key used for encryption
init_vector
VARCHAR
Initialization vector required when CBC/CFB/OFB mode was used for encryption; must match the IV used during encryption
AES_DECRYPT returns NULL both for NULL input and for decryption failures (wrong key, wrong mode, corrupt data). Treating NULL as 'empty' hides decryption errors silently.
✓ Instead: Check that the decrypted value is NOT NULL before using it, and ensure block_encryption_mode matches what was used during encryption.
⇄ vs MySQL: Identical in MySQL 5.6+.
⇄ vs PostgreSQL: PostgreSQL pgcrypto provides pgp_sym_decrypt(); no native AES_DECRYPT equivalent.
Computes the MD5 128-bit checksum of a string and returns a 32-character lowercase hexadecimal string. MD5 is a one-way hash function — it cannot be reversed. WARNING: MD5 is cryptographically broken and must NOT be used for password hashing or security-sensitive integrity checks.
Signature
MD5(str)
Parameters
Parameter
Type
Description
str
VARCHAR
The input string to hash; treated as a binary string for the computation
Computes the SHA-1 160-bit hash of a string and returns a 40-character lowercase hexadecimal string. SHA1 is a one-way hash — it cannot be reversed. WARNING: SHA-1 is cryptographically broken (collision attacks demonstrated) and should not be used for security purposes.
⚠Anti-Pattern— Using SHA1 for certificate or password hashing
SHA-1 collision attacks have been publicly demonstrated (SHAttered, 2017). It must not be used for digital certificates, code signing, or password storage.
✓ Instead: Use SHA2(str, 256) for general hashing and a proper KDF (bcrypt/argon2) for passwords.
⇄ vs MySQL: Identical in MySQL.
⇄ vs PostgreSQL: PostgreSQL does not have a native SHA1() function; use pgcrypto's digest(str, 'sha1').
Synonym for SHA1(). Computes the SHA-1 160-bit hash of a string and returns a 40-character lowercase hexadecimal string. Maintained for compatibility; prefer SHA1() or SHA2() in new code.
Signature
SHA(str)
Parameters
Parameter
Type
Description
str
VARCHAR
The input string to hash
Examples
SHA is identical to SHA1
sql
SELECTSHA('test');
→-- 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
Confirms SHA is a synonym
sql
SELECTSHA('test') =SHA1('test');
→-- 1 (true)
NULL returns NULL
sql
SELECTSHA(NULL);
→-- NULL
Column fingerprinting
sql
SELECTSHA(CONCAT(col1, col2)) FROMt;
→-- per-row SHA-1 hashes
Always 40 hex characters
sql
SELECTLENGTH(SHA('x'));
→-- 40
⚠Anti-Pattern— Assuming SHA means something newer
Developers unfamiliar with MariaDB may assume SHA() refers to a modern SHA-2 variant. It is purely SHA-1.
✓ Instead: Be explicit: use SHA2(str, 256) for SHA-256 and SHA2(str, 512) for SHA-512.
⇄ vs MySQL: Identical in MySQL.
⇄ vs PostgreSQL: No native SHA() in PostgreSQL; use pgcrypto's digest().
Computes an SHA-2 family hash (SHA-224, SHA-256, SHA-384, or SHA-512) of a string and returns it as a lowercase hexadecimal string. The hash_length parameter selects the algorithm. SHA-256 and SHA-512 are currently considered cryptographically secure for hashing purposes.
Signature
SHA2(str, hash_length)
Parameters
Parameter
Type
Description
str
VARCHAR
The input string to hash
hash_length
INT
Bit length of the desired hash: 224, 256, 384, or 512. A value of 0 is treated as 256.
⚠Anti-Pattern— Using SHA2 alone for password storage
Even SHA-512 is a fast hash, making it feasible to brute-force with GPU clusters. Passwords stored as raw SHA2 hashes can be cracked quickly.
✓ Instead: Hash passwords with bcrypt or argon2 in the application layer. If you must hash in SQL, add a random per-user salt and consider stretching with multiple iterations.
⇄ vs MySQL: Identical in MySQL 5.5.5+.
⇄ vs PostgreSQL: PostgreSQL pgcrypto provides digest(str, 'sha256') and digest(str, 'sha512').
Hashes a plaintext password string using the MySQL/MariaDB native password hashing scheme (a double-SHA1 variant prefixed with '*'). Used internally by MariaDB for the mysql_native_password authentication plugin. Returns a 41-character string starting with '*'.
⚠Anti-Pattern— Using PASSWORD() for application user passwords
PASSWORD() uses a double-SHA1 scheme that is fast and not designed as a KDF. It is only suitable for MariaDB's own auth tables, not for storing user passwords in application tables.
✓ Instead: Store application passwords as bcrypt or argon2 hashes generated in application code, not in SQL.
◆MariaDB Note
MariaDB still supports PASSWORD() for the legacy mysql_native_password plugin. When using ed25519 or other modern auth plugins the function is not used.
⇄ vs MySQL: PASSWORD() was deprecated in MySQL 5.7 and removed in MySQL 8.0. MariaDB retains it for mysql_native_password compatibility.
⇄ vs PostgreSQL: PostgreSQL has no PASSWORD() function; user authentication uses pg_hba.conf and system-level password management.
Returns the pre-MySQL-4.1 16-character password hash. Used only for compatibility with very old MySQL 3.x/4.0 clients that cannot handle the new 41-character hash format. This algorithm is extremely weak and must not be used in any new code.
Signature
OLD_PASSWORD(str)
Parameters
Parameter
Type
Description
str
VARCHAR
The plaintext password to hash using the old algorithm
Examples
16-char old-style hash
sql
SELECTOLD_PASSWORD('test');
→-- '378b243e220ca493'
Always 16 characters
sql
SELECTLENGTH(OLD_PASSWORD('x'));
→-- 16
NULL returns NULL
sql
SELECTOLD_PASSWORD(NULL);
→-- NULL
Empty password hash
sql
SELECTOLD_PASSWORD('') ;
→-- '0000000000000000'
Deterministic (no salt)
sql
SELECTOLD_PASSWORD('test') =OLD_PASSWORD('test');
→-- 1
⚠Anti-Pattern— Using OLD_PASSWORD for any new functionality
OLD_PASSWORD uses a trivially broken custom hash algorithm with no salt. It offers essentially no security.
✓ Instead: Use PASSWORD() for MariaDB native auth, or application-level bcrypt/argon2 for application user tables.
◆MariaDB Note
Retained in MariaDB for backward compatibility only.
⇄ vs MySQL: Present in MySQL for legacy reasons; behavior is identical. Removed from MySQL 8.0 along with PASSWORD().
⇄ vs PostgreSQL: PostgreSQL has no equivalent function.
Encrypts a string using the Unix crypt() system call with the provided salt. On platforms where crypt() is not available (notably Windows), ENCRYPT() always returns NULL. The output depends on the underlying system's crypt() implementation. Deprecated — use AES_ENCRYPT() for portable encryption.
Signature
ENCRYPT(str[, salt])
Parameters
Parameter
Type
Description
str
VARCHAR
The string to encrypt
salt
VARCHAR
Optional two-character salt; if omitted, a random salt is chosen by the system
Encrypts a string str using password as the key with a simple XOR-based cipher and returns a binary string the same length as str. This is a weak, non-standard symmetric cipher — it provides minimal security. Deprecated in MariaDB. The counterpart function is DECODE().
Signature
ENCODE(str, password)
Parameters
Parameter
Type
Description
str
VARCHAR
The plaintext string to encrypt
password
VARCHAR
The key string used to generate the cipher stream
Examples
Basic encryption
sql
SELECTHEX(ENCODE('hello', 'mykey'));
→-- hex ciphertext (same length as 'hello')
Round-trip
sql
SELECTDECODE(ENCODE('hello', 'key'), 'key');
→-- 'hello'
NULL input returns NULL
sql
SELECTENCODE(NULL, 'key');
→-- NULL
Output length equals input length
sql
SELECTLENGTH(ENCODE('hello', 'k'));
→-- 5
Empty key — avoid
sql
SELECTENCODE('msg', '');
→-- same as ENCODE with empty key (weak)
⚠Anti-Pattern— Using ENCODE for sensitive data
ENCODE's cipher is easily reversible by an attacker who knows the algorithm. It does not provide cryptographic security.
✓ Instead: Replace all ENCODE usage with AES_ENCRYPT() using aes-256-cbc mode.
◆MariaDB Note
Deprecated in MariaDB; may be removed in a future major version.
⇄ vs MySQL: Identical in MySQL. Deprecated in MySQL 5.7, removed from MySQL 8.0.
⇄ vs PostgreSQL: PostgreSQL has no ENCODE() encryption function (there is an encode() for base64/hex encoding, which is different).
Decrypts a string that was encrypted with ENCODE() using the same password. Returns the original plaintext. Uses the same weak XOR-based cipher as ENCODE(). Deprecated — use AES_DECRYPT() for real encryption.
Signature
DECODE(crypt_str, password)
Parameters
Parameter
Type
Description
crypt_str
VARBINARY
The encrypted binary string produced by ENCODE()
password
VARCHAR
The key string; must match the key used with ENCODE()
⚠Anti-Pattern— Trusting non-NULL output as successful decryption
DECODE always returns a non-NULL result (when input is non-NULL) even if the wrong password is given, because it is XOR-based — there is no authentication tag to detect failure.
✓ Instead: Use AES_DECRYPT() in CBC mode with an HMAC or authenticated encryption (AES-GCM via application layer) so decryption failures are detectable.
◆MariaDB Note
Deprecated in MariaDB.
⇄ vs MySQL: Identical in MySQL. Deprecated in MySQL 5.7, removed in MySQL 8.0.
⇄ vs PostgreSQL: PostgreSQL has no DECODE() encryption function (decode() in PostgreSQL handles base64/hex, not encryption).
Compresses a string using zlib compression and returns the result as a binary string. The returned value stores the uncompressed length in the first four bytes. COMPRESS is not encryption — the data is not secret, only smaller. Use UNCOMPRESS() to restore the original data.
Signature
COMPRESS(string_to_compress)
Parameters
Parameter
Type
Description
string_to_compress
VARCHAR
The string to compress; binary strings are also accepted
Uncompresses a string that was compressed with COMPRESS(). Returns the original uncompressed string, or NULL if the argument was not a valid compressed value or is NULL. The input must be a value produced by COMPRESS().
⚠Anti-Pattern— Using UNCOMPRESS on arbitrary binary columns
Calling UNCOMPRESS on data not produced by COMPRESS() returns NULL and generates a warning that is easy to miss in production.
✓ Instead: Track which columns contain COMPRESS()-compressed data with a naming convention (e.g., suffix _compressed) and validate before decompressing.
⇄ vs MySQL: Identical in MySQL.
⇄ vs PostgreSQL: PostgreSQL has no UNCOMPRESS() function.
Returns the length that the compressed string would be after decompression. It reads the 4-byte length header stored at the start of a COMPRESS() result without actually performing decompression, making it fast for size checks.
⚠Anti-Pattern— Calling UNCOMPRESSED_LENGTH on non-compressed data
UNCOMPRESSED_LENGTH reads the first 4 bytes of any binary input and interprets them as a little-endian integer. Non-COMPRESS() input will return a random, meaningless number with no error.
✓ Instead: Only call UNCOMPRESSED_LENGTH on columns that were explicitly stored using COMPRESS().
⇄ vs MySQL: Identical in MySQL.
⇄ vs PostgreSQL: PostgreSQL has no equivalent function.
Returns a binary string of the requested length filled with cryptographically random bytes sourced from the operating system's secure random number generator. Useful for generating initialization vectors, salts, nonces, and temporary secrets. Length must be between 1 and 1024.
Signature
RANDOM_BYTES(length)
Parameters
Parameter
Type
Description
length
INT
Number of random bytes to return; must be between 1 and 1024
Examples
Generate a 128-bit random value
sql
SELECTHEX(RANDOM_BYTES(16));
→-- 32 hex chars of random data
Generate IV for AES-CBC
sql
SET @@session.block_encryption_mode='aes-256-cbc';
SELECTHEX(AES_ENCRYPT('msg', 'key', RANDOM_BYTES(16)));
→-- random hex ciphertext
Create a password salt
sql
SELECTHEX(RANDOM_BYTES(32)) ASsalt;
→-- 64-char hex salt
Zero length returns NULL
sql
SELECTRANDOM_BYTES(0);
→-- NULL (or error)
Over 1024 returns NULL
sql
SELECTRANDOM_BYTES(1025);
→-- NULL (out of range)
⚠Anti-Pattern— Using RAND() or UUID() for cryptographic randomness
RAND() is a pseudo-random number generator seeded with the current time; it is predictable. UUID() also uses time-based components. Neither is suitable for security-sensitive random values.
✓ Instead: Use RANDOM_BYTES(n) for all cryptographic randomness requirements (IVs, salts, tokens, nonces).
⇄ vs MySQL: Identical in MySQL 5.6.17+.
⇄ vs PostgreSQL: PostgreSQL pgcrypto provides gen_random_bytes(n); also available as gen_random_uuid() for UUIDs.
Encrypts a string using DES (Data Encryption Standard) with a key from the DES key file, or with an explicitly provided key string. Returns a binary string. DES uses only 56-bit keys and is completely broken by modern standards. Deprecated — use AES_ENCRYPT() instead. Requires the server to have been started with --des-key-file.
Signature
DES_ENCRYPT(str[, {key_num|key_str}])
Parameters
Parameter
Type
Description
str
VARCHAR
The plaintext string to encrypt
key_num
INT
Optional key number (0–9) referencing an entry in the DES key file
key_str
VARCHAR
Optional explicit key string to use instead of the key file
⚠Anti-Pattern— Using DES_ENCRYPT for any new application
DES has a 56-bit key space that was exhaustively searched in 1998. Triple-DES (3DES) is also deprecated. There is no valid reason to use DES_ENCRYPT in any system built after 2000.
✓ Instead: Use AES_ENCRYPT() with block_encryption_mode set to 'aes-256-cbc' and RANDOM_BYTES(16) for the IV.
◆MariaDB Note
Deprecated in MariaDB. Requires the server to be started with --des-key-file for key-number mode. Returns NULL if SSL is not initialized or the key file is not loaded.
⇄ vs MySQL: Identical in MySQL. Deprecated in MySQL 5.7, removed in MySQL 8.0.
⇄ vs PostgreSQL: PostgreSQL has no DES_ENCRYPT; pgcrypto historically supported 3DES but it is also deprecated there.
Decrypts a string encrypted with DES_ENCRYPT() using the same key. Returns the original plaintext, or NULL if decryption fails. DES is completely broken by modern standards. Deprecated — use AES_DECRYPT() instead.
Signature
DES_DECRYPT(crypt_str[, key_str])
Parameters
Parameter
Type
Description
crypt_str
VARBINARY
The encrypted binary string produced by DES_ENCRYPT()
key_str
VARCHAR
Optional key string; required if DES_ENCRYPT was called with an explicit key string rather than a key number
⚠Anti-Pattern— Leaving DES-encrypted data in production
Data encrypted with DES is effectively unencrypted by any attacker with moderate compute resources.
✓ Instead: Schedule an immediate migration: decrypt with DES_DECRYPT(), re-encrypt with AES_ENCRYPT() using aes-256-cbc, and update the column type to VARBINARY.
◆MariaDB Note
Deprecated in MariaDB.
⇄ vs MySQL: Identical in MySQL. Deprecated in MySQL 5.7, removed in MySQL 8.0.
⇄ vs PostgreSQL: PostgreSQL has no DES_DECRYPT function.