0

I'm designing a web service meant for storing data for users, but these users don't have proper server-side accounts, just a random master key the user generated and stores on their device (a bip39 mnemonic) so they can derive some public-private keypair from it and use the public key as their "id" on the server to aggregate their data by.

The server should allow accessing/modifying the data stored only to the user that created the records. I believe this can be achieved by the user signing their request payloads with their private key and sending alongside the public key under which the server would store the records.

This looks to me almost like HMAC authentication, just the secret isn't a shared symmetric key between the server and the client, but rather an assymetric one. At the same time, I couldn't find any specification that would deal with asymmetric keys, perhaps WebAuthn comes close but the existing specs/implementations seem to be restricted to hardware devices (FIDO2) which doesn't apply to my use-case (the secret key would be stored on user's computer)

Can you point me at some web authentication standard that would be suitable for my usecase, removing the need to specify the solution/address potential issues like replay protection/etc. from scratch?

  • 1
    You might want to consider using client-side certificates, which are intended to solve this very problem. – mti2935 Oct 28 '21 at 12:56
  • can you point me at any specific, ideally javascript-based, but not necessarily, implementation of it? – Rafael Korbas Oct 28 '21 at 13:57
  • 1
    With client certificates, there is no javascript coding involved. The user simply loads the client cert in his/her web browser, then TLS handles the rest. Then, on the server side, you authenticate the user based on the cert. See https://security.stackexchange.com/questions/251826/can-mutual-tls-work-with-a-self-signed-client-certificate and https://cweiske.de/tagebuch/ssl-client-certificates.htm for more info. – mti2935 Oct 28 '21 at 14:04
  • I see, the user having to generate/load the certificate manually/outside the app unfortunately isn't a viable user experience in my case. I need a way for the web app to generate and use the keys to authenticate against the server internally, without user's involvement – Rafael Korbas Oct 29 '21 at 05:56
  • 1
    In that case, this sounds very much like Secure Remote Protocol (SRP), where in your case, the user's key would be the 'random master key the user generated and stores on their device (a bip39 mnemonic)'. See my answer at https://security.stackexchange.com/questions/242811/alternatives-for-sending-plaintext-password-while-login for more info. – mti2935 Oct 29 '21 at 11:24

1 Answers1

1

A "secret" for signing HMAC is not necessarily a symmetric key, it's only requirement is that the secret is 'secret' and never communicated/shared.

The best way to be secure for an API is to avoid at all costs sending secrets in any request. Make sure that any 'secret' is communicated to the user no more than 1 time, and the user sends the secret exactly 0 times, but in your case this is simply reversed. so a HMAC or HMAC based solution is perfect for API Authn when it meets this requirement in one direction. A simple user UUID or whatever ID you have in a header can be identity, or something more sophisticated, as long as the secret is not in the requests the 'identity' will be used to lookup the secret on the server-side and will have to reproduce the HMAC and match the user's resultant HMAC they sent you for the identity+authn combination to validate, so the UUID is fine for this purpose.

Once the user has generated the secret, and the server end has recieved it once, all subsequent requests do not send it at all if HMAC is used, but instead they use the secret to derive the HMAC that proves they have the secret.

The server can verify the request with the HMAC because it too has the secret stored and can reproduce the same HMAC as the client did, but the secret was never sent in the requests.

I've implemented HMAC in various methods, some used the symmetric key scenario as that was the vendor's choice, other vendors (like AWS/GCP) use HMAC to make API requests to their service (but nobody knows it if all they use is the SDK that does all the API Authn and calling for them). Azure uses HMAC because JWT uses HMAC, so it is quite common and not usually based on a symmetric key.

I have even used HMAC for a login form, so the user never sends the password once created! Their password is typed in and the client-side generates a HMAC from it, the server then reproduces the HMAC on the server-side to verify the user knows the secret (password) too.

HMAC is versatile, and secrets used for signing only need to be secret.

Stof
  • 151
  • 9