> ## Content Index
> Fetch the complete content index at: https://securinglaravel.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Security Tip: Use HMAC Hashes To Verify Data
- URL: https://securinglaravel.com/security-tip-use-hmac-hashes-to-verify/
- Published: 2023-12-21T03:11:58.000Z
- Updated: 2025-08-25T00:15:18.000Z
- Description: [Tip#66] For those situations where you need to generate a repeatable hash or signature, reach for HMAC, rather than MD5 or SHA1.
- Author: Stephen Rees-Carter
- Tags: Security Tips, HMAC, Cryptography, Hashing, Signed URLs

Let’s pick up from last week’s [Security Tip: Do You Really Need a Hash for That?](https://securinglaravel.com/security-tip-do-you-really-need-a/) *(Go read that first, if you haven’t yet!)*

We’ve talked about situations where you don’t need to reach for hashes, **but what if you do need a hash?**

There are a few reasons why you’d want to hash some data, and today we’re going to cover the use case of verifiable signatures or repeatable hashes. These are hashes generated from a known piece of data, and then compared to another hash generated from a different piece of data. If the hashes match, then the data is the same and unmodified.

The simplest example of this are [Laravel’s Signed URLs](https://laravel.com/docs/urls?ref=securinglaravel.com#signed-urls). These work by generating the full URL, hashing that URL (using HMAC), and adding the hash signature onto the URL. When the user uses the URL, the application extracts the signature, hashes the provided URL and checks if the signature matches the new hash. If they match, the URL hasn’t been modified and can be trusted. If they don’t match, the URL cannot be trusted.

This sounds great, but how do we generate a hash like this? Also, how can we use this between different apps to protect things like API payloads? Using a raw hashing algorithm won’t prevent someone else from generating a hash of the modified data. Instead, we need to use a shared secret key known only to the servers which are generating and verifying the signatures, and then use this as part of generating our hash.

💡

****Shared Secret** → This is the term used to describe a secret value known on both sides of a cryptographic operation, such as when you use HMAC hashes to generate signatures of API payloads to prevent tampering. Unlike public/private key pairs, a shared secret is the same on both sides.

While you could just add a shared secret into the plaintext value you’re hashing *(please don’t do this)*, a secure method is to use a Hash-based Message Authentication Code (HMAC) with PHP’s [hash\_hmac()](https://www.php.net/manual/en/function.hash-hmac.php?ref=securinglaravel.com) function:

```
hash_hmac(
    string $algo,
    string $data,
    string $key,
    bool $binary = false
): string
```

We can use it like this:

```
> $algo      = 'sha256';
> $plaintext = 'One ring to rule them all';
> $secretKey = 'secret';

> hash_hmac($algo, $plaintext, $secretKey);
= "f1ae7cb307846761e8c42d2b12c8c400328e8fd692996c5fb65e722e703d3825"
```

An attacker can control both the `$plaintext` and hash output, but without knowing the `$secretKey`, they cannot generate a hash that matches the modified `$plaintext`.

If you’re generating hashes within your application only, you could use `config('app.key');` directly as the HMAC key, but I would recommend generating and using a separate key for this. This allows you to rotate keys independently, as well as share keys if needed.

💡

Using separate keys for all of the different cryptographic operations in your app is a good idea. Laravel lets you override the keys for each of them. 

As you’d expect, HMAC signatures are often used in APIs and especially webhooks, to prevent tampering and forging values. If you can verify the signature, you can trust the API & webhook payloads. Many API SDKs handle this component automatically for you.

*If you’ve used HMACs or other forms of signatures and repeatable hashes before, I’d love to hear what you’re doing with them. Leave a comment below with the details!*

## How secure is your app?

Sign up for ****Securing Laravel** to learn the essential security skills you need to keep your Laravel apps secure! You'll receive [weekly security tips](https://securinglaravel.com/tag/tips/) (like this one!), and upgrade to receive [monthly In Depth articles](https://securinglaravel.com/tag/in-depth/) that teach you so much more. You'll also be supporting Stephen's security work within the Laravel & PHP Community!

Subscribe 

Email sent! Check your inbox to complete your signup. 

No spam. Unsubscribe anytime.

---

***If you found this security tip useful?* 👍**  
[*Subscribe now*](#/portal/signup) *to get weekly* [***Security Tips***](https://securinglaravel.com/tag/tips/) *straight to your inbox, filled with practical, actionable advice to help you build safer apps.*

***Want to learn more?* 🤓**  
*Upgrade to a* [*Premium Subscription*](#/portal/signup) *for exclusive monthly* [**In Depth* articles*](https://securinglaravel.com/tag/in-depth/)*, or support my work with a* [*one-off tip*](#/portal/support) *or* [*recurring Sponsorship*](https://securinglaravel.com/sponsor/)*! Your support directly funds my security work in the Laravel community.* 🥰

**Need a second set of eyes on your code?** 
*Book in a* [*Laravel Security Audit and Penetration Test*](https://stephenreescarter.net/laravel-security-audits-and-pentesting/?utm%5Fsource=securinglaravel.com) *today! I also offer budget-friendly* [*Security Reviews*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com) *too.*

*Finally, connect with me on* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*, or* [*other socials*](https://pinkary.com/@valorin?ref=securinglaravel.com)*, and check out* [*Practical Laravel Security*](https://practicallaravelsecurity.com/?utm%5Fsource=securinglaravel.com)*, my interactive course designed to boost your Laravel security skills.*