Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement end-to-end auditable encryption and new user login methods. #147

Merged
merged 10 commits into from
May 24, 2022

Conversation

Reckless-Satoshi
Copy link
Collaborator

@Reckless-Satoshi Reckless-Satoshi commented May 22, 2022

Objective.
Seamless and auditable E2E encryption using OpenPGP.

Users should only need to store one thing: the high entropy token. With it, users should be able to 1) generate an avatar or login into an existing one 2) encrypt/decrypt/sign/verify messages in the chat conversation in a fully transparent and auditable way using any third party OpenPGP implementation (the frontend component should facilitate the export of armored ASCII for messages and encrypted private key).

The SHA256 hash of the high entropy token (base62, 36 characteres long by default) is used to generate an avatar and for login. The hash of the hash of the token (second hash, computed in the server) is used to generate the Robot nickname and avatar image. Only the first hash of the token is ever sent to the server, yet the token itself should always remain on the client side (must never be share!). The highEntropyToken is used as passphrase of a PGP privateKey, the encrypted privKey is sent for storage to the server. This key will be needed to encrypt/decrypt the chat messages in a fully auditable manner by the user.

While by default the highEntropyToken is 36 characteres long and base62, the user can create it's token however they please. However, the frontend will submit 3 parameters about the token: length, number of unique characters, and count of characters. The token should satisfy >0.7 Shannon entropy and >128 bits of entropy. However, if the user prefers not to be checked for stupidity low entropy, the request for robot generation will go through for any token if the 3 parameters are not submitted.

For retrocompatibility with existing accounts, although identity reuse is highly not recommended, the old way to login with tokens via GET will still work. But new robot avatars cannot be created this way. The frontend will not support login with the old method. So users will have to login by visiting /api/user/?token=<token> endpoint on their browsers.

PGP setup:

  1. User generates a highEntropyToken
  2. User generates a keyPair. The privKey is encrypted with the highEntropyToken
key = openpgp.generateKey({
   type: 'ecc', // Type of the key, defaults to ECC
   curve: 'curve25519', // ECC curve name, defaults to curve25519
   userIDs: [{name: 'RoboSats avatar'}],
   passphrase: highEntropyToken,
   format: 'armored'
})
  1. User generates/requests credentials: by sending his sha256(highEntropyToken) . The client sends in the same payload his pubKey and encryptedPrivKey.
  2. Server hashes the hash, and replies with Robot nickname and avatar image. An active SessionID is given, also the pubKey encryptedPrivKey are returned (very important if this is not the first time the user logs in, so he needs to recover a previous privKey and rejoin an existing chat)
  3. User encrypts/decrypts/signs/verifies every chat message with his decryptedPrivKey.
  4. In future logins, the user only introduces the highEntropyToken. After server replies, he decrypts his privKey, ready to chat!

TODO:

  • Implement new login / credential method using sha256(token). Server stores encryptedPrivKey and PubKey. Deprecate but keep old token login method.
  • Implemet Utils: genKeyPair(), encryptMessage(), decryptMessage()
  • Implement recovery of privKey and pubKey for existing robots using a backed-up highEntropyToken.
  • Exchange public keys via Chat WS as armored ASCII.
  • PGP encrypt and sign every message before sending them over chat WS.
  • On message received, use own encryptedPrivKey and passphrase(highEntropyToken) to convert the received message to plainText.
  • Store an array in app state with all previous messages encrypted/decrypted. By default the chat will look just as it does now. The array must contain for all messages: messageId:int, messagePlainText:string, messageArmored:string, time:DateTIme, verified:boolean
  • By clicking the "Audit" button, users will see all of the messageArmored in the array (the chat will be full with many "---- BEGIN PGP MESSAGE----(...)"). While the button is not pressed, users only see the list of messagePlainText.
  • Implement a Dialog pop up with the pieces required to independently audit the E2E encryption: 1) passphrase (highEntropyToken), 2) user encryptedPrivKey (armored ASCII an easy to export format) and 3) counterpart pubKey.
  • Add Download Button for "keys.txt" and "messages.txt"
  • Pop up dialog has a link to a doc on how to audit the RoboSats' chat e2e encryption using OpenKeychain or OpenPGP on CLI. The doc could be a simple extension on what already exists on https://learn.robosats.com/docs/pgp-encryption/
  • ... Optional: now the backend can safely store the chat logs and serve them back once a robot connects to the chat room.

@Reckless-Satoshi Reckless-Satoshi mentioned this pull request May 22, 2022
9 tasks
@Reckless-Satoshi
Copy link
Collaborator Author

It's ready. It works. It's nerd. And it's beautiful!

@Reckless-Satoshi
Copy link
Collaborator Author

Merging as is. Some more testing will be needed. Messages cannot be sent unless the 2 peers are online (otherwise one pubkey is missing).

For a future PR: server stores and serves the encrypted messages (great for a conversation when both peers cannot be online at once!, server must also serve pubkeys).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant