0
$\begingroup$

This is a machine-to-machine authentication proposal with the following requirements:

  • Avoid replay attacks. Leaked or intercepted auth tokens cannot be reused at all.
  • Impersonation resistant. The server shouldn't have any client secrets or password-equivalent data in any form, if compromised.

For reasons why, see this answer.

Registration

Occurs out-of-band.
The client generates an Ed25519 key pair and gives the public key to the server.
The server generates a random key ID and gives this to the client.

Client creates a unique signed auth token for every HTTP request

Increments nonce (monotonically increasing integer).
Signs key ID and nonce with private key.
Auth token = key-id|nonce|sign_Ed25519(key-id|nonce, privateKey)
This auth token is sent as a http header, using HTTPS.

Server verifies auth token

Extracts key ID and nonce from the token.
Gets the stored public key and last_nonce by key ID.
Verifies the signature with the public key.
Checks that nonce > last_nonce.
If successful, saves the current nonce as last_nonce and processes the request.

Questions:

  1. Most importantly: Is this secure? Does it fulfill the requirements?
  2. Any downsides compared with API keys, a similar HMAC header, access tokens, or mTLS? I don't care about message integrity or mutual authentication. I've identified two disadvantages so far: both the client and server are stateful (nonce) and the client cannot send concurrent requests (correct?). Performance is fine, ie. orders of magnitude faster than the request processing time.
  3. Any existing standard? I don't want to use a too complex PAKE protocol, but maybe there's a simpler one? Found this draft but it seems to sign the whole request (too slow).
$\endgroup$
4
  • $\begingroup$ I am very confused by your protocol definition. Is http or https used? Is the key_id sent in plaintext? Is key-id and nonce for Auth token masked, e.g. by Sign_sk(key-id)? How is Ed25519(key-id|nonce) computed? Do you only want to be secure against replay attacks or do you also want to prohibit forgeries? $\endgroup$ Commented May 21, 2024 at 10:12
  • $\begingroup$ It seems like you want client-only authentication. If you want to do one-message authentication, you somehow need some kind of state. If you want parallel sessions, you could record which counters have been seen, possibly with a window to bound storage requirements. If you can manage two-message flows, use challenge-response (server sends challenge, client responds with signature on challenge). Of course, you may be able to use client certificates in HTTPS, which seems more appropriate if you are not already familiar with the basic theory of authentication protocols. $\endgroup$ Commented May 21, 2024 at 18:56
  • $\begingroup$ Clarified the auth-token part a bit. Yes, all client-server communication uses HTTPS. Auth token is sent as a header. It is the concatenation of plaintext key-id, plaintext nonce, and the signature of key-id + nonce. No anti-forgery needed. Client only authentication. Parallel sessions not strictly needed but would be nice. Client certificates/mTLS is definitely an alternative. $\endgroup$ Commented May 21, 2024 at 19:25
  • 1
    $\begingroup$ "If successful, saves the current nonce as last_nonce and processes the request." This is dangerous. It's better to store it first and then remove it (if that's required at all) before checking, otherwise you'd get problems if storing is not successful. Not a direct attack, but it is a weakness. $\endgroup$ Commented May 21, 2024 at 21:02

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.