Glossary

HMAC signature

An HMAC signature is a short value computed from a message and a shared secret key, used to prove that the message came from someone who holds that secret and that it was not altered in transit. HMAC stands for hash-based message authentication code: the sender hashes the message together with the secret to produce the signature and sends both; the receiver, who also holds the secret, recomputes the same hash over the message it received and checks that the two values match. A match means the message is authentic and intact; a mismatch means it was forged or tampered with.

01

What an HMAC signature is

HMAC combines a cryptographic hash function with a secret key. A plain hash, on its own, only detects accidental changes — anyone can recompute it, so anyone can forge a message and a matching hash. HMAC fixes that by folding a secret into the computation: only a party that holds the key can produce a signature that verifies, and only a party that holds the key can check one. The secret never travels with the message; it is shared once, out of band, and both sides keep their own copy.

The signature is what the sender attaches to a message. To sign, the sender runs the HMAC construction over the exact bytes of the message using the shared key, producing a fixed-length value, and sends that value alongside the message — typically in a header when the message is an HTTP request. To verify, the receiver runs the identical computation over the bytes it actually received and compares its result to the signature it was given. Because the key is required on both ends, a third party who can see the message in transit still cannot produce a valid signature for a message of their own.

Two properties make HMAC suitable for authenticating messages. It is keyed, so a valid signature is evidence the sender knew the secret — it authenticates origin, not just integrity. And it is sensitive to every byte of the input, so changing even one character of the message, or re-encoding it so whitespace or field order shifts, changes the signature and causes verification to fail. HMAC proves who sent a message and that it arrived unchanged; it does not encrypt or hide the message, which stays readable to anyone who intercepts it.

02

Why it matters for crypto payments

A payment system has to tell a merchant's backend when money moves — an invoice was paid, a payout completed — and it usually does that by sending an event to a URL the merchant registered. That URL is reachable by anyone, so the question on every incoming request is the same: did this really come from the payment provider, or did someone forge it to trick the backend into fulfilling an order or releasing funds? An HMAC signature answers that question. The provider signs each event with a secret shared only with that merchant, and the backend rejects anything whose signature does not verify.

The discipline is to verify first and act second. The signature, not the look of the payload, is the source of truth — a forged request can carry a perfectly plausible-looking body. Verification has to run over the exact raw bytes received, before any JSON parsing or framework middleware re-encodes the body, because a re-encoded body changes whitespace and key order and will fail an otherwise-valid signature. The comparison of the two values should be constant-time, meaning it does not return early at the first differing byte; a comparison that short-circuits leaks timing information an attacker can use to guess a valid signature one byte at a time. Only after the signature checks out does the backend deserialize and trust the message.

Because the protection rests entirely on the secret, the secret is handled like any credential that can move value. It is stored server-side in a secret manager, never shipped to a browser or committed to source control, and rotated if it is ever exposed. Anyone who learns the secret can forge events the backend will accept, so guarding it is as important as the verification step itself.

03

HMAC signatures on halfin

halfin signs every webhook it sends with HMAC. Each event — invoice.confirming, invoice.paid, invoice.overpaid, invoice.underpaid, invoice.expired, invoice.late_deposit, invoice.deposit_reversed, balance.credited, payout.completed, payout.failed — is a JSON envelope whose signature travels in a request header, computed with the signing secret tied to your endpoint. Your handler's job on receipt is short and strict: recompute the HMAC over the exact raw request body, compare it to the header in constant time, and only then deserialize and act on the event.

Treat an unsigned or mismatched request as hostile. The endpoint URL is public the moment you register it, so anyone can POST arbitrary JSON to it; the signature is the only thing that separates a genuine halfin event from a forgery. Return a 4xx and do nothing else when verification fails — never fulfil an order, credit a balance, or release a payout on the strength of the payload alone. You configure the endpoint and its signing secret from the dashboard or the API, and you store that secret the way you store any other credential.

  • An HMAC signature is a keyed hash that proves a message came from a holder of the shared secret and was not altered in transit.
  • It authenticates origin and integrity, but does not encrypt — the message stays readable; only forgery and tampering are caught.
  • Verify before acting: recompute the HMAC over the exact raw bytes, then compare in constant time before parsing or trusting the body.
  • halfin signs every webhook with HMAC; reject any request whose signature does not verify, and guard the signing secret like any credential that can move value.