Is PGP for user authentication a good idea?

You should never try to secure a "real" web application with a scheme that you invented on your own. As such we shouldn't discuss practicalities on how you would actually implement or use such a method.

Will it work?

Your scheme does not send a password over the wire. What immediately jumps out is that you send the private key to the server, which never does anything with it, for no reason. Yes, it is supposedly still protected by the password, but why?

As others have pointed out, the private key is supposed to remain with the owner.

Even if you consider the private key's password encryption, there is the following problems (at least):

  • Handing out the private key in your scheme is essentially the same as making the password hash public: Anyone can now do an offline dictionary attack against the key's password; and nobody can stop that.
  • Even worse, they can get the key for a given login, meaning that they can check if a user exists and then attack the password for the user name.

With a small modification, your scheme would be a very simple form of public key authentication:

  • The client creates a key pair, and sends the public key to the server
  • To log in, the server sends out a random string.
  • The client signs the string and sends it back to the server.
  • The server verifies the signature to make sure the client has the private key

Something like this is actually already possible in https using client certificates. The same thing is used for ssh.

The Challenge-Response mechanism mentioned by ThoriumBR is another way of authenticating, although the implementation described there assumes that the server stores the password in cleartext -- which is much more dangerous than sending it over an encrypted connection.

Will it be "better"?

No. The scenario that you want to defend against is supposedly that someone gets inside the encrypted https connection. If you assume that this is the case, they would not only be able to read the password but also steal your session cookie and all the data that is shown in your session. In that case, the attacker has already won, regardless of whether they read the password or not.

You could of course roll your own encryption and authentication, but the question is why you'd think that this will be better than the https connection?

The realistic scenario isn't that someone breaks the https connection, it is that someone breaks into the server's database and tries to "recover" the passwords in an offline attack. This is what most authentication schemes try to defend against.

The danger with passwords is not that they are interceptable, but that they can be guessed.

What should you do in real life?

For a "real" web application, use an established framework and a well-known authentication library. Don't write it yourself, because it is easy to get wrong and very hard to get right.

Don't use SHA-anything for hashing the passwords, use a dedicated password-hashing function such as bcrypt or PBKDF2 to make attacks more difficult (see this answer also). You can also use or add some TOTP mechanism for your app, which is better than just a password.

Addendum

You added the following after I wrote my answer:

My requirement is that the only thing users ever need to provide for successful authentication is their username/password and nothing else, regardless of what device they are using or whether they were logged in on that device before.

This explains why you want to send the private key back to the server, although it doesn't change the reason why it is a bad idea.

You could still use a challenge-response mechanism, like ThoriumBR suggested. There are even advanced challenge-repsonse mechanisms such as SRP which use clever math to avoid storing the password on the server.

However, all those mechanisms, and also client-side hashing (see this answer), have one thing in common:

They need to execute code on the client side.

In a web app, this can only be Javascript sent by the server. Implementing the client side is not the problem (there is even a OpenPGP library), but since you worry about the security of the https connection, you have another problem:

Any man in the middle could therefore simply inject malicious client side code to steal the password, rendering your whole clever mechanism obsolete.


As the others said, private keys aren't shared. full stop. Otherwise, they are called public keys.

But: Cryptographically signing on is pretty standard. HTTPS supports that:

Authentication using HTTPS client certificates; and all modern browsers have the built-in means to generate the necessary keys when asked to.

Your problem has already been solved; the user generates a key pair, gives you its public key, keeps the private key, and upon connection, the server asks the client to prove they own the private key (essentially, by letting them sign something).

Done!

Other cryptographically established methods include at least one method I'm aware of:

Single-sign on via Kerberos ticket – this is extremely wide-spread in intranets that use Active Directory. Again, modern browsers (at least Edge, Internet Explorer, and Firefox) support this out of the box – on both windows and Linux (haven't tried on OS X or FreeBSD)


While I like the idea of PGP for login, this is not the way it's supposed to work. The private key should remain on the client side, always, and never be shared with anyone. This setup encourages bad practices and provide incorrect education about PGP.

What you could do is, have users upload their public key to the server, and then you present them a challenge (basically, an encrypted string) upon login, that requires the private key and of course the associated passphrase..

The problem is that few people know PGP or have a serious inclination to use it. If you can do it, go for it.