I have an unsubscribe link, which needs to be passed a customer id, and a product id, producing a query string something like:


I would like to ensure the customer is the one doing the unsubscribing, and that they are unsubscribing from the exact product. HMAC seems like a logical choice:

?cid=100&pid=2&hmac=<HMAC generated from secret key and cid=100&pid=2>

...and I can validate the HMAC to guarantee authenticity and integrity.

BUT I would also like to keep the customer id and product id confidential if the link is passed around in email, for example. I can't do that if the HMAC is based off of them. For example if I just passed the HMAC:

?hmac=<HMAC generated from secret key and cid=100&pid=2>

In this case I cannot not infer the customer id and product id in question (without brute forcing the hash).

Is there a standard way to return encrypted/hashed query parameters?

No, I can't use SSL/TLS.

  • $\begingroup$ HMAC is not encryption, but works for your purpose of authentication. I suppose you can also encrypt (AES+Base64) the cid and pid, and append do the hash, then validate on server? Or you can have unique random ids for unsubscribe links and keep a database of customers and products on the server? $\endgroup$ Nov 4, 2013 at 19:52
  • $\begingroup$ Even if you are using TLS, there are good reasons in schemes like this to authenticate the parameters being passed to the resource (e..g to prevent customers unsubscribing other customers etc.) $\endgroup$
    – archie
    Nov 4, 2013 at 20:07

2 Answers 2


Not using cryptography on URI:

  • If you store subscribers on a database, maybe you could also store additional (say) 128-bit random value on some column when there somebody about to unsubscribe. This way there is no meaning for the value beyond this transaction and it cannot e.g. leak anything about the key.

If you cannot use additional data on the database, then use e.g.:

  • Your favorite AEAD scheme (or Encrypt+HMAC scheme) to encrypt cid+pid pair and to attach authentication tag. Maybe e.g. GCM using 96 bit random IV and 96 bit authentication tag. If there is less than four billion customers and less than four billion product, that would fit in around 256 bits or the same size than (non-truncated) HMAC-SHA256. You may use some variant of base64 to encode the value in URI to 43 characters.

The HTTP standard does not specify how to encrypt or hash parameters. The TLS/SSL is the standard way to apply confidentiality and other security properties.


There is an RFC-compliant way to do things like this now, using the JWT JSON Web Token specification.

The JWT algorithm generates a little bit of JSON-encoded HMAC-protected output, which is character-safe for HTTP headers, URL parameters, POST bodies, etc.

In Python, this is implemented by the package PyJWT.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.