I’m interested in using public-key cryptography for stateless authentication on websites.
The current authentication standard is email + password. Passwords are bad because they can often be guessed, forgotten, stolen, divulged etc. Passkeys are better because they rely on public-key cryptography and no one can (realistically) guess your private key.
But AFAIK, passkeys only use public-key cryptography during login. Afterwards, the server sets a cookie or returns a bearer token or something along those lines. Those can still be stolen.
Why not go all the way: imagine a website that lets you sign up just by submitting your public key. It can extract your name and email. (I’m told some sites take this approach during signup, but then they revert to traditional cookies or bearer tokens for subsequent HTTP requests.) Once signed up, you include a detached signature in the Authorization header of any subsequent HTTP request of your session. It could be, say, a signature of the request body. The server verifies the signature and knows that it must have come from you, thus authenticating you. Assuming your clock is synced, you could include a timestamp in the signed text for the server to minimize room for replay attacks.
This approach is fully stateless, password-less, and remains secure even if requests are intercepted in plain text. Signature verification is cheap and fast. Public-key cryptography is battle-hardened technology – much more so than plain-old passwords. The approach also puts session management completely in the control of end users since all they need to do to ‘log out’ is stop signing their requests. And to switch profiles, they just switch to a different keypair.
Features built into public-key cryptography such as key revocation and rotation further increase security (eg to disable or update an account). End-to-end encryption is available out of the box if desired. (HTTPS connections are already encrypted, but it’s a bonus for added security – Heartbleed comes to mind, or maybe it’s a useful fallback when something goes wrong with the server’s certificate.)
To generate and use key pairs, I’m picturing a browser extension that interfaces with a native app. This app would call out to gpg to generate a key pair for a given domain, share the resulting public key with the browser, and sign subsequent requests to that domain automatically. The private key would never touch the browser. Access to the native app could be guarded with biometrics, a similar approach to passkeys.
I want to know what challenges this approach may face in terms of security. Also, surely I can’t be the first person to think of this approach. At the risk of embarrassing myself: I’m an experienced full-stack web developer but a cryptography noob.
I’m guessing attackers would be most interested in trying to gain access to the native app since it holds private keys.