VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
hmac() lets you do it in SQL.
The Problem: No Built-In HMAC
MySQL hasSHA2() and MD5() for hashing, but nothing that takes a key. HMAC (Hash-based Message Authentication Code) uses a shared secret to produce an authentication code — it’s fundamentally different from a plain hash because someone without the key can’t reproduce it.
The typical approach is to compute HMACs in the application before writing to the database:
With VillageSQL: hmac() in SQL
VillageSQL’svsql_crypto extension adds hmac(data, key, algorithm), which returns a VARBINARY authentication code computed entirely in MySQL.
Signing rows in a trigger
Use a trigger to sign every row at write time, regardless of which application path created it:Verifying webhook payloads
If your application stores incoming webhook payloads, you can verify signatures directly in SQL before processing:Supported algorithms
| Algorithm | Call | Use when |
|---|---|---|
| HMAC-SHA256 | hmac(data, key, 'sha256') | General-purpose — recommended default |
| HMAC-SHA512 | hmac(data, key, 'sha512') | Higher security margin required |
| HMAC-SHA1 | hmac(data, key, 'sha1') | Legacy system compatibility only |
| HMAC-MD5 | hmac(data, key, 'md5') | Legacy system compatibility only |
HMAC vs. Plain Hash
Plain hash (digest()) | HMAC (hmac()) | |
|---|---|---|
| Takes a key | No | Yes |
| Forgeable without the key | Yes — anyone can hash the same data | No |
| Use for | Checksums, deduplication, fingerprinting | Authentication, tamper detection, signatures |
| Verifiable by | Anyone | Only holders of the key |
Frequently Asked Questions
Is storing the HMAC key in the trigger safe?
No — it’s hardcoded in the trigger definition, visible to anyone withSHOW CREATE TRIGGER access. For production, retrieve the key from a secure configuration path or pass it as a session variable set by the application on connection. Treat the key as a credential.
Can I use HMAC to verify query results haven’t been altered in transit?
HMAC protects against unauthorized modifications, not eavesdropping. For in-transit protection, use TLS for your MySQL connection. HMAC is useful for detecting tampering after data reaches the database.How do I rotate the HMAC key?
Re-sign all existing rows with the new key before switching:Does hmac() return the same output for the same inputs?
Yes — HMAC is deterministic. The same data + same key + same algorithm always produce the same result. This is what makes verification work.Troubleshooting
| Problem | Solution |
|---|---|
FUNCTION hmac does not exist | Run INSTALL EXTENSION vsql_crypto |
hmac() returns NULL | Check for NULL in data or key argument, or an unsupported algorithm name |
| Verification always returns 0 | Check that the data string is byte-for-byte identical to what was signed — whitespace, encoding, and NULL handling all matter |
| Signature column fills with NULLs | The trigger is running but key or data is NULL — add COALESCE around nullable fields |

