VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
MD5(), SHA1(), and SHA2() built in. They work, but they return hex strings — 64 characters for a SHA-256 hash, when the underlying data is 32 bytes. Storing hashes in binary cuts that in half and is more efficient to index. digest() from VillageSQL’s vsql_crypto extension returns raw binary and gives you a single function for every algorithm.
The MySQL Default: Scattered Functions, Hex Output
MySQL provides three separate functions for hashing:UNHEX(SHA2('hello', 256)), which works but is awkward to type consistently.
There’s also no sha224 or sha384 option — you’re limited to what MySQL exposes.
The Standard Workaround: UNHEX + SHA2
For compact binary storage, developers wrapSHA2() in UNHEX():
With VillageSQL: digest()
VillageSQL’svsql_crypto extension adds digest(data, algorithm), which returns a VARBINARY hash directly — no UNHEX() wrapper needed.
HEX() when you need a readable string for logging or display:
Supported algorithms
Don’t use MD5 or SHA-1 for new applications — both have known collision vulnerabilities. SHA-256 is the practical default for most uses.
For password storage specifically,
digest() is the wrong tool — see Password Hashing in MySQL for crypt() and gen_salt().
When to Use Each Approach
For new projects on VillageSQL,
digest() is the cleaner choice. For existing MySQL-only applications, UNHEX(SHA2()) is equally correct.
Frequently Asked Questions
What’s the difference between digest() and SHA2()?
SHA2('hello', 256) returns a 64-character hex string. digest('hello', 'sha256') returns a 32-byte VARBINARY. They compute the same hash — the difference is encoding. Binary storage is more compact and faster to index.
Can I use digest() to detect duplicate rows?
Yes. Storedigest(content, 'sha256') in an indexed column, then query WHERE sha256 = digest(incoming_content, 'sha256'). This is a common pattern for deduplicating uploaded files, detecting changed records, or building content-addressable lookups.
Is digest() safe for passwords?
No.digest() is a fast hash — it computes in microseconds. Password hashing requires a slow, iterated algorithm. Use crypt() and gen_salt() from the same extension. See Password Hashing in MySQL.
Does digest() support HMAC?
No —digest() is a plain hash with no key. For keyed authentication codes, use hmac(). See HMAC Signatures in MySQL.
Troubleshooting
See also
- Password Hashing in MySQL — slow adaptive hashing designed specifically for credentials
- HMAC Signatures in MySQL — keyed hashing for integrity verification and webhook validation
- Symmetric Encryption in MySQL — when you need the data back, not just a fingerprint

