# Use HMAC or encryption for deep links?

On a few occasions I've converted URLs with authentication via a session cookie to deep link URL's with no cookie authentication. These are URL's with simple id's like /download/pdf/1.

I convert them to deep links either by appending a HMAC of the ID (/download/pdf/1/7e3aefd25fb9…) or encrypting the ID using AEAD and omitting the id from the url (/download/pdf/7e3aefd25fb9…).

In both cases I store a longterm key on the server which is used for all deep links.

I was wondering: which (if any) of these approaches is best practice?

1. I like the HMAC approach because it clearly states the intent.

2. I like the AEAD approach because the programmer cannot read the ID from the url and then accidentally forget the authentication.

(I realize there is a third option which is to use an entirely random number for the deeplink. This is the simplest cryptographically speaking, and the best practice I suspect. But it has downsides because you must store these numbers and references to which resources they belong. Generating the URLs can't be done "on the spot" any more, you must push to the centralized storage.)

Usage scenarios:

• The URL must work inside an iframe where cookies cannot be used in some browsers
• The URL is automatically opened by another application such as Androids PDF reader which has no access to your browser cookies
• We send an email with the resource URL and the recipient has no account in the system
• We wants the users to be able to share the resource without sharing their credentials

Description of the attacker:

• he uses HTTP
• he might have access to the website as a cookie-authenticated user but NOT to all resources
• he might have some valid deep links in his possession
• he can easily guess a valid ID
• he should not be able to create a valid URL from an ID unless it was provided to him
• he should not be able access the resource
• @ErikvanVelzen so the server has some sort of long-term secret key it uses to generate the HMAC or the authenticated encryption? If using AEAD, the ciphertext will grow with the plaintext. – mikeazo Dec 8 '16 at 18:25
• Where does the original id (1 in your example) come from? Why can't you just replace that with a sufficiently long random number? – otus Dec 8 '16 at 18:30
• @mikeazo yes there is a long-term secret key, I have added this information – Erik van Velzen Dec 8 '16 at 18:45
• @otus the id is from a relational database. I mention the use of a random number in the post. It is certainly a good (the best?) option but I prefer to avoid extending my database schema with data that is not relevant to the problem domain of the application. – Erik van Velzen Dec 8 '16 at 18:45
• I'm not sure if there is such a thing as "best practice" given the rather specific usage scenario. PS if you ever want to change protocol you might want to include some protocol identifier in your URL. – Maarten Bodewes Dec 8 '16 at 19:52

## 2 Answers

In my opinion your choice should come down to whether you want to hide the ID or not. If not, the use of encryption is just extra complexity and not useful. Most AEAD schemes allow decryption without authentication if the programmer really tries, so even that benefit is not very convincing to me.

A MAC, on the other hand, fits the problem perfectly well.

(Of course HTTP and plaintext email mean that your system has holes. Especially the former, since any eavesdropper to the connection will get to know both the URL and the content if you do not use TLS.)

In general passphrase based authentication is weak enough that the ID and password in unison are used for authentication purposes. You can see that when you get a response "invalid username or password" when trying to log into a service. So including the ID in plain is not a good idea in my opinion.

This reasoning pleads for using AEAD encryption of the ID field. That ID field must be (converted into a) statically sized field; if the ID is one ASCII encoded digital number then guessing the number won't be hard. So the ID should be hard to guess by an attacker.

It should be assumed that the attacker has information such as the email address of the person holding the account. There is a reason for random UID schemes, that decouple the ID from other information of the account holder.

Any browser based security operation that is performed without TLS is very likely to be broken in one way or the other. Regardless of the rest of your scheme, TLS should be offered to be anywhere near secure, especially against active attacks (e.g. attacks using a public WiFi access point).

• Disclaimer: this is just about the information you've provided in your question, I haven't looked at any other possibilities. Your scheme could be insecure even when using the information provided in my answer. – Maarten Bodewes Dec 8 '16 at 19:51
• There's nothing about passwords in the question and in the comments a long term secret key is mentioned. – otus Dec 9 '16 at 15:28
• @otus Well, there's "authenticated URL's" at the start of the question. I'm not sure how you'd get to that point without some kind of authentication. But sure, that's an assumption that I made. – Maarten Bodewes Dec 9 '16 at 15:30