End-to-End encryption for a chat application

I am trying to build an android chat application just for educational purpose. I would like to try implementing end-to-end encryption so that my messages are secure. I thought of using RSA as the encryption scheme (I'm new to the field of cryptography)

This is how I thought I should do it,

Step 1: Generate public and private key in the Client and Server sides.

Step 2: Exchange the public keys. (This means that server will have the public key of each and every client).

Step 3: Encrypt the message using the public key of the Server and send to Server or vice-versa.

Step 4: The Server can then use its private key to decrypt the message.

So my questions are,

  1. How am I to store the private keys?
  2. What are the drawbacks of this approach?
  3. How should this actually be implemented?

Please help me clear this concept

1 answer

  • answered 2018-01-14 13:10 Saketh Katari

    What are the drawbacks of this approach?

    1. Using RSA, you can't encrypt huge data. If your RSA key size is k bits then it can only encrypt a message whose length is <= (k/8)-11 bytes
    2. How do you verify the other party's public key? An intruder in the middle of server and client can send his/her own public key which you may assume as client's public key.

    How should this actually be implemented?

    I guess there's no single correct method to implement it. My approach is as follows -

    1. Generate RSA keys (at least 2048-bit keys - due to security concerns).

    2. Exchange the public keys. Verify the public key of the other party. How?

    . Certifying Authorities (or)

    . Credentials from a client (or)

    . Bind client's public key to his/her email ID

    1. Use Diffie-Hellman (DH) key exchange to establish a shared secret between server and the client. Use previously generated RSA keys while exchanging DH data -

    To send DH_data from source to destination,

    . encrypt_with_destination_public_key(DH_data) --- Ensures confidentiality (a)

    . hash(DH_data) --- Ensures integrity (b)

    . encrypt_with_source_private_key(hashed_DH_data i.e b) --- Ensures non-repudiation (c)

    Transfer a & c to the destination

    1. Generate symmetric Key, say AES (atleast 128-bit key) from the shared secret on both sides. Also, generate 2 other strings inner_pad and outer_pad, each of same length (128-bit) as the generated symmetric key and make sure that these 2 are different from each other at least by 1 bit. Note that using HMAC ensures integrity and non-repudiation (because you know whom you've shared your symmetric key with) without Asymmetric Keys

    2. Now, to transfer data from source to destination -

      . encrypt_with_symmetric_key(data) --- Ensures confidentiality (x)

      . Hash( (symmetric_key XOR innerpad) + x) --- MAC (y)

      . Hash( (symmetric_key XOR outer_pad) + y ) --- HMAC, Ensures integrity & Non-repudiation (z)

      Send x & z to the destination.

    3. At destination,

      . Decrypt_with_symmetric_key(x) --- Ensures confidentiality (P)

      . hash( (symmetric_key XOR inner_pad) + encrypt_with_symmetric_key(P) ) --- MAC, Q

      . hash( (symmetric_key XOR outer_pad) + Q ) --- HMAC, R

      . R == z ensures integrity and non-repudiation.

    I recommend using SHA3 for hashing

    How am I to store the private keys?

    Click here

    I've worked on a similar project recently, you can find it here