online_security_project/protocol.md

4.7 KiB

The Protocol

All encryptions are made using RSA (key size to be determined), no symmetric encryptions are used due to messages being short.

a. Encryption will be a-symmetric because we can assume messages are short b. See "Registration" below c. Server keeps public keys for everyone, and gives them to a user when they want to send a message to someone (only the relevant key) d. Every e2e message is both signed and encrypted aka, message M from A to B EM = E_Bpub(E_Apriv(N)) e. message is sent to the server in a E_server(E_Apriv(metadata + EM from d)), message ack is sent to the server as a MessageAck(msg_id), which will be retrieved by the user when it pulls for messages. f. TODO: properly explain the different api structs g. TODO: properly explain how the server handles data

Key Derivation Function

as there is no use of symmetric keys (at least for this scope), I dont believe there is a need to use KDF, it will reduce the keyspace and we already have the public key of the server in the clients

Registration:

  • User sends a register request to server (phone number, RSA public key), giving them a public key and encrypting using the server's public key
  • Server sends the user a VerificationRequired message & a 6-digit code (Secure channel)
  • User sends the server the 6-digit code, signed using the key provided at stage 1 (this message is very short and funny, because its a 6-digit code, signed using the user's private key, and encrypted using the server's public key)
  • Server sends a last Confirm and the registration process is done

"Login"

The users dont need to login, as they dont really need to hold a conenction to the server, only thing that matters is that every message to the server should be signed with the user's private key, thus the key acts as a form of credentials

Passing messages

In order to send a message from A to B, A will ask the server for B's key, A will then encrypt the message using B's key, signed with A, wrapped in a SendMessage request and ultimately signed by A and encrypted using the server's key.

The server will hold on to the message until B will send a GetMessages request to the server.

"Control" requests

  • Register: data: Phone - 8 bytes, RSA key size (payload length) - 2 bytes
  • ConfirmRegister (signed & encrypted 6 digit code) data: 6 bytes for the 6 digit code (can use less but it will be padding otherwise)
  • Login (signed hash): data: 8 bytes of user's phone, signed SHA length - 2 bytes
  • GetMessages: data: EMPTY
  • GetUserKey (dont think it needs any signing or encryption technically, as it is very simple registering and "stealing" a key outside the system, keys are assumed to be unbreakable) extra data: 8 bytes (4 bits per digit) of whoever we want to get the key of
  • SendMessage (to_user, msg_id, EM from d above) extra data: 8 bytes (4 bits per digit) of who to send the data, 4 bytes (32bit) for length in bytes I think it all can go into a:
{
	Version byte (0) - 1 byte
	RequestType - 1 byte,
	looping counter - 1 bytes (long), could be replaced by a counter, that can be 1 looping byte, thus 
	data - up to 13,
} = 16 bytes = 128 bits

and we can just append encrypted payloads to it (in SendMessage and SendAck)

To each message we also append a sha3-256 signed hash, this shit really feels like overkill and im not sure about it, on the other i do want to have a bigger key size and 512 seems like an okay-ish thing to have, as 256 is short and 1024 is amusingly long for the amount of data the server needs to encrypt

enc_server( request - 256 bits, signed sha3-256 )

which means: public keys: RSA-2048/1024 (not sure what i need here honestly) Hashes: SHA3-256 symmetric keys: AES-256

scrape that... seems it wouldnt work as expected since it doesnt work that way with RSA i think maybe not im not sure...

thinking right now about an RSA-2048 key (for sEcUrItY), then starting a connection will be whatever the user wants, and optionally an AES-128 (because its only for 1 session) key to use for subsequent messages, this allows the user to NOT encrypt everything with RSA keys, it still means the server has to decrypt and verify a signature for the first message (and either return an error or force close the connection if the sig is invalid and all)

this somewhat applies for the register messages, you send a payload with an AES key and a public RSA key, then in ConfirmRegister the key is still being signed with the user's RSA, but then encrypted using the AES session key.

Messages between users will still be done using public RSA keys, which honestly can be both 1024, or 2048 as far as im aware, prob should also be 2048, that means the server needs to do 2 RSA encryptions per session (or 2 for the registration itself, which is then auto-validating the session)