0
$\begingroup$

I'm writing a web service that gives a unique token per client connection. And the following are the desired properties. I'm assuming server's issued token db is lost and untrustable client presents the token to the server.

  • Server should be able to tell if the token is previously issued by the server or not.
  • Server should be able to tell when the token was issued.

So I'm thinking generating tokens based on timestamp & count using Poly1305 so that server can see the timestamp without maintaining token db. For example:

  • token1 = Poly1305("2017-04-25T21:12:32Z 1")
  • token2 = Poly1305("2017-04-25T21:12:40Z 2")
  • token3 = Poly1305("2017-04-30T22:12:32Z 3")

My questions are:

  • Is this safe? (including reusing key & nonce for all the tokens)
  • Am I doing something dumb or is there a better way?

Thank you.

$\endgroup$
  • 1
    $\begingroup$ The common term for what you're describing is "stateless session tokens". This is so common in the web application space there is even a standardized format for them called JWT. Ignore all the JWT variants but the the one which uses HMAC-SHA256 for authentication; the rest of the optional algorithms are insecure or use insecure padding modes. The IETF must always keep bad 1990s crypto alive. tools.ietf.org/html/rfc7519 $\endgroup$ – rmalayter Apr 28 '17 at 2:28
0
$\begingroup$

Is this safe? Am I doing something dumb?

Well, I don't think it's actually safe; however why it's not safe would depend on the details of what your library has implemented within the Poly1305 function.

Straight Poly1305 isn't a MAC; it's actually a universal hash. That is, it takes a message and a key and produces a value; however (unlike a MAC) it's sole guarrantee is that, for two different messages $M, M'$, we'll have $\text{Poly1305}_K(M) = \text{Poly1305}_K(M')$ for only a tiny fraction of the keys (and so if the key $K$ is selected randomly, this is quite improbable.

What this doesn't guarantee is that someone looking at $\text{Poly1305}_K(M)$ values for various $M$'s would have any difficulty whatsoever about recovering $K$, and for the Poly1305 function itself, recovering $K$ is easy. Hence, if your Poly1305 function implements only the universal hash function itself, well, it's broken that way.

Now, this use of Poly1305 doesn't actually use a nonce, and so I'm not sure if you're using it straight.

To use Poly1305 as a MAC, what we do is compute the Poly1305 of the message, and then encrypt the tag with the nonce, using some cipher (AES or ChaCha, most typically). This is safe; the Poly1305 prevents someone from producing two messages that will have the same MAC (because with an unknown Poly1305 key, that's unlikely), and the AES/ChaCha cipher will prevent someone from seeing the Poly1305 output directly (and so recovering things that way).

However, we do this encryption by taking the nonce, sending that through the cipher, and then adding that to the Poly1305 output; if we use the same nonce repeatedly, that means that we'll be adding a constant value to the Poly1305, and the attacker can adjust to that.

On the other hand, things doing this generally call out the cipher being used, say, as Poly1305-AES or Poly1305-ChaCha

So, I'm not sure why what you're doing isn't safe; but it doesn't look good.

Is there a better way?

If you find it inconvenient to use a different nonce for every token, might I suggest using HMAC (based on some reasonable hash function, say SHA256)? That doesn't need a nonce, and hence you're secure (or, at least, as long as you can keep the key secret). It's not as fast as Poly1305; it wouldn't appear you care about that.

$\endgroup$
  • $\begingroup$ Thanks a lot for the comprehensive answer! And yeah, I was thinking Poly1305+a cipher, but didn't mention that. My bad. I guess then something like HMAC+SHA256 is more appropriate as you mentioned. Thanks again for the answer! $\endgroup$ – Kibeom Kim Apr 26 '17 at 0:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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