Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples in this guide work on VillageSQL. Install Now →
A hash tells you what data looks like. An HMAC tells you that the data came from someone who knows the secret key. The difference matters when you’re verifying that a row wasn’t tampered with, that a webhook payload is authentic, or that a token was generated by your system and not forged. MySQL has no built-in HMAC function — the standard answer is to compute it in application code. VillageSQL’s hmac() lets you do it in SQL.

The Problem: No Built-In HMAC

MySQL has SHA2() 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:
This works, but it means every write path — every language, service, and bulk loader — must replicate the signing logic. A migration script that bypasses the application will write unsigned rows.

With VillageSQL: hmac() in SQL

VillageSQL’s vsql_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

Use HMAC-SHA256 for new code. The HMAC construction doesn’t inherit the collision vulnerabilities of the underlying hash, so HMAC-SHA1 isn’t broken the way plain SHA-1 is — but SHA-1 is deprecated and regulators treat it as legacy. Don’t use it for new code.

HMAC vs. Plain Hash

If the data you’re protecting is public, a plain hash doesn’t prove anything. Use HMAC when you need to prove the data was produced by someone who knows the secret. For hashing without a key, see Hashing Data in MySQL.

Frequently Asked Questions

Is storing the HMAC key in the trigger safe?

No — it’s hardcoded in the trigger definition, visible to anyone with SHOW 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

See also