For a web service, I am considering generating random 25-49 recovery codes as a kind of pass that can be stored in a pass manager (no usernames).

Instead of pass(word) hashing on the server, I consider hashing the pass on the client with pbkdf2 to a seed and using the seed to generate ECDSA key pairs.

The public key would be the anonymous user ID, stored on the server with the internal uid instead of password hashes. By authentication, client would be providing the public key and signing over a random server challenge with the private key, server verifying presence of public key and signature in one step.

This seems to be better than the traditional password hashing system, since the server load is minimal (since the cpu intensive pass hashing happens on the client side). In addition, the secret will not travel. If the public keys leak on the server, it is similar to when the password hashes leak: a brute force attack has to perform the intensive pbkdf2 hashing process (that is why I would use password hashing to get the seed).

I am not really aware of anybody using this for pass management. I discovered that HD wallets use something similar by bitcoin (bip32): https://en.bitcoin.it/wiki/BIP_0032

I think we had both the same idea: let people have a human readable code to manage, backup etc. instead of private key management. Only bitcoin uses 12-24 english words and I think it is better to use like 25-49 base32 tokens (26 letters + 10 numbers - I,O,1,0).

Does this system a good/better replacement for password hashing? If so, how should I create ECDSA key pairs from the seed, since the web crypto API subtle.crypto does not support this. Should we go for a web crypto extension? Or copy the bitcoin implementation?

I came to the idea being not really happy with the new passkey system that use ECDSA key pairs per default too. I think there will always be people who resist pass managers and it is better for humans to get a human readable code in general. An ECDSA private key is too long to manage not programatically.

However, I find ECDSA math cool and the secret will not travel, but I do not want 2 systems: one for autofilling-syncing-cloud-pass-manager users and one for people with "local" pass management (brain, paper, local disk etc). This system would work for both types and with the same security as passkeys for pass manager users.

In addition, we could consider to remember the key pair on browser or pass manager level too. It is possible on Apple, Google, Microsoft systems to require biometrics / PIN before accessing the secrets in the pass manager (Linux not so...).

I think it is fairly safe to "register" a browser on the trusted device by saving the private key in indexed db unextractable and the public key in a secure cookie that is not accessible via js. If we get access to biometrics from the web more broadly, people who do not use pass managers should only enter the code once on each trusted device and then they could sign in with biometrics / PIN without synced pass managers too.

I am really curious what people with more security knowledge think about this.

  • How does one change their password? Commented Aug 18, 2023 at 14:41
  • If you have the ability to store a generated private key in a secure key store, why bother with generating a potentially weak key pair from user input?
    – Shireheart
    Commented Aug 18, 2023 at 14:53
  • There is no "ability" to handle private keys by users who opt out of a pass manager. And the recovery key is not user input, 125-245 bit strong by 25-49 chars. An ECDSA private key is much longer in text representation.
    – r j
    Commented Aug 18, 2023 at 15:07
  • Changing password... generate new one and replace?
    – r j
    Commented Aug 18, 2023 at 15:07
  • In addition, please chat-gpt following: why does bitcoin use mnemonics? (accessible, general, human friendly, traditional backup, cross device, balance between security and usability, non-technical users etc...)
    – r j
    Commented Aug 18, 2023 at 15:16


You must log in to answer this question.