I want to create a secure messaging application such that you don't have to trust the server.

  1. Register with username and password. ->
  2. Generate a pair of PGP keys (RSA). ->
  3. Encrypt the private key with the password. ->
  4. Hash the password

This is what the server knows:

  • username
  • pubKey
  • AES/CBC(SHA256(pass), privKey)
  • SHA256(SHA256(pass))

I double hash the password so that the server can't use it to decrypt the privKey.

This works: after the login the user receives his private key and unread messages, he can query the server for somebody's public key and send them a message.

However, the server could generate a PGP pair and send his public key to Bob instead of Alice's when Bob wants to send a message to her. Decrypt the message and then encrypt it with Alice's actual public key and then send it to her.

How can I prevent this?

  • 1
    You either need a PKI system with trusted CA's (like we have on the web); or a web of trust model, like PGP uses; or a Trust On First Use (TOFU) model, like SSH uses; or a way of exchanging public keys out-of-band, like Signal does with its 'safety numbers'. See security.stackexchange.com/questions/254727/… and security.stackexchange.com/questions/139596/… for similar questions.
    – mti2935
    Jan 3 at 14:40
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer.
    – Community Bot
    Jan 4 at 3:52
  • Just checking: why do you want to develop a new zero-trust messaging service? We aren't short on them. If you must do so, though, why not just adopt one of the high-quality open standards / open source implementations, such as the Signal protocol? Also, using a single round, or even a double round, of any SHA for passwords is not at all secure. Nor does your design (using OpenPGP keys) allow for forward secrecy. You should ask another question concerning the whole design of this system if you actually want to do this, though be aware that the answer will mostly be "don't roll your own".
    – CBHacking
    Jan 4 at 6:57

Your question boils down to the subject of authentication. In other words, how can Bob authenticate that the public key that he has received for Alice through the untrusted network does in fact belong to Alice, and is not the public key of a Man in the Middle (MITM) attacker? This question has vexed security researchers since the advent of public key cryptography, and this question crops up whenever a public key must be sent from one party to another through an untrusted network or untrusted server.

There are several solutions to this problem, but none of them are perfect:

  1. Public Key Infrastructure (PKI). This is the model used on the world wide web. We rely on trusted certificate authorities (CA's) to authenticate the certificates (which contain public keys) of web servers on the web.

  2. Web of Trust (WoT). David has authenticated Alice's public key. Carol trusts David, and Bob trusts Carol. So, Bob figures that the public key for Alice that he has received from Carol, who received it from David, must be authentic. PGP relies on a Web of Trust model.

  3. Trust on First Use (TOFU). When Bob contacts Alice for the first time, he stores Alice's public key. Then, on each subsequent connection, he checks that the public key that he sees for Alice matches the one that he has stored for her. This method is also sometimes referred to as 'public key pinning'. SSH relies on this model.

  4. Out of band verification. Bob receives Alice's public key through the untrusted network, then Bob calls Alice (or texts her, or faxes her, or sends a telegram to her, etc.) to verify that the public key that he has received for her is authentic. Signal has come up with a clever way of simplifying this process, using 'safety numbers' (see Signal protocol implementations: pub key authentication and inspectability? (Allo, WhatsApp, FB messenger, Signal) for more info).

  • 1
    PKI is also used for end-to-end message encryption in S/MIME, and for TLS servers other than web servers. WoT seems, in practice, almost never used and also for two levels of separation you'd often want multiple indications of trust. Pinning can in theory be done using TOFU but us usually done by having the client pre-configured for its peer(s); if you say "public key pinning" I don't expect anybody will think you mean TOFU. TOFU also sucks when you have to rotate keys. Out of band verification often actually just means meeting in person. But aside from that, big +1.
    – CBHacking
    Jan 4 at 6:52
  • All excellent points. Thank you for adding these @CBHacking.
    – mti2935
    Jan 4 at 12:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.