Skip to content

Instantly share code, notes, and snippets.

@jbis9051

jbis9051/idea.md Secret

Last active April 27, 2021 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbis9051/e045db43979d171b3128894a924115db to your computer and use it in GitHub Desktop.
Save jbis9051/e045db43979d171b3128894a924115db to your computer and use it in GitHub Desktop.

Use Case

The app I am developing is an end-to-end screensharing and remote control software. There are three components

  1. Host - The user that wants to share their screen
  2. Client - The user that wants to view and control the Host's screen
  3. Server - The server used for authentication and to proxy information between the Host and the Client

The goal is to create a cryptographical protocol that allows the host and the client to communicate end to end encrypted, using the server as a proxy. The host and the server should both be able to authenticate the client.

The system should still be secure even if the server is compromised.

In reality, the Host and the Client will usually be talking to each other over the phone or have some external means of communication. For purposes of this protocol we don't care whether the external means of communication is secure or not.

Protocol

  1. Host requests an ID from the server. The server responds with a 10 digit code, N, used for identification/routing

When a Client is ready to connect, the Host will communicate N externally (probably over the phone) to the Client. For purposes of this protocol we don't care how secure of a method is used for this exchange.

  1. Client sends N to the server over TLS. Server proxies data over TLS between the Client and the Host. Host <-TLS-> Server <-TLS-> Client
  2. Client sends "auth" to Host
  3. Host generates a short (10 character) securely random alphanumeric (lowercase + numbers) code, X. (~52 bits of entropy)
  4. Host generates a key pair, where PKH is the Host's PublicKey
  5. Host communicates X externally to Client
  6. Once the Client has X, the Client generates a keypair, where PKC is the Client's PublicKey
  7. The Client sends "exchange" to Host
  8. Host records a unix timestamp, TH, generates an exchange package, containing [HMAC(TH || PKH, X), TH, PKH], and sends it to the Client, where HMAC is HMAC-bcrypt with a cost value of 10
  9. Once the Client receives the Host's exchange package, it compares the current time with TH. If time difference exceeds 10 seconds, the Client hard fails and follows the disconnect procedure (not listed).
  10. The Client verifies the MAC
  11. The Client performs Diffie Hellman with PKH and their own private key to produce a secret key, S
  12. The Client records a unix timestamp TC and sends it's exchange package, [HMAC(TC || PKH, X), TC, PKC], to the Host
  13. The Host compares TH with the current timestmap. If time difference exceeds 5 minutes, the Host hard fails and follows the disconnect procedure (not listed).
  14. The Host compares TH and TC. If time difference exceeds 10 seconds, the Host hard fails and follows the disconnect procedure (not listed).
  15. The Host verifies the MAC
  16. The Host performs Diffie Hellman with PKC and their own private key to produce the same secret key, S
  17. Client and Host now use S to encrypt all communication
@alipha
Copy link

alipha commented Apr 19, 2021

Host requests an ID from the server. The server responds with a 10 digit code, N, used for identification/routing
When a Client is ready to connect, the Host will communicate N externally (probably over the phone) to the Client. For purposes of this protocol we don't care how secure of a method is used for this exchange.

Client sends N to the server over TLS. Server proxies data over TLS between the Client and the Host. Host <-TLS-> Server <-TLS-> Client

  1. Host and Client both generate ephemeral public/private keypairs and send each other their public keys over the proxied TLS connection.
  2. Host and Client both perform Diffie-Hellman with their private key and the other's public key. They now both have the same symmetric key, X.
  3. Host UI displays the first 4 characters of H(X).
  4. The Host User communicates these 4 characters to the Client User.
  5. The Client User enters in these 4 characters into the Client UI. The Client Program confirms they match the first 4 digits H(X).
  6. The Client UI now displays the next 4 characters of H(X).
  7. The Host User enters in these 4 characters into the Host UI. The Host Program confirms they match the second 4 digits of H(X).
  8. Both users click an "ok" button to signal to the programs that it's okay to proceed. The Host and Client programs both send an encrypted message (with symmetric key X) of "Proceed" to the other party.
  9. The Host and Client can now use the symmetric key X to encrypt all communication.

@marksteward
Copy link

marksteward commented Apr 21, 2021

Instead of just splitting the fingerprint into two, you can derive two keys from the shared key and the role (e.g. 0 for host, 1 for client) and truncate those. Then ask each side to enter the value for the other (or even just one side if you want to be brave). This maximises the chance that you'll catch a malicious server.

Additional things you should call out:

  • clients and hosts must end the connection immediately if the fingerprints don't match, and you should have a way to surface when this is happening, with perhaps a check digit to prevent false alarms.
  • encryption must be authenticated in all cases
  • use a proper KDF instead of describing one from first principles
  • make sure input length is specified when concatenating

@alipha
Copy link

alipha commented Apr 22, 2021

  1. Host requests an ID from the server. The server responds with a 10 digit code, N, used for identification/routing

When a Client is ready to connect, the Host will communicate N externally (probably over the phone) to the Client. For purposes of this protocol we don't care how secure of a method is used for this exchange.

  1. Client sends N to the server over TLS. Server proxies data over TLS between the Client and the Host. Host <-TLS-> Server <-TLS-> Client
  2. Host generates a random 8-digit code (called p) and displays it to the user.
  3. The Host User communicates p to the Client User out of band (over the phone, probably).
  4. After the Client User enters p, Host and Client perform SRP (using p as the password), which produces a key K.

https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol

  1. Host and Client can now communicate using authenticated symmetric encryption using K.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment