online_security_project/protocol.md
2024-12-14 19:10:09 +02:00

87 lines
No EOL
3.8 KiB
Markdown

# 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 `(phone, pub RSA key)`
extra data: RSA key size (payload length)
- ConfirmRegister (signed & encrypted 6 digit code)
extra data: 6 bytes for the 6 digit code (can use less but it will be padding otherwise)
- GetMessages (signed & encrypted to not allow someone to "flush" someone else's msgs)
extra 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
- SendAck `(to_user, msg_id - signed and encrypted)`
- server doesnt know if the msg itself is indeed valid and not tempered with
extra data: 8 bytes (4 bits per digit) of who to send the data, 4 bytes (32bit) for length
I think it all can go into a:
```
{
Version byte (0) - 1 byte
RequestType - 1 byte,
Phone number - 8 bytes (every 4 bits is a number, so we have 16 numbers),
UTC timestamp - 8 bytes (long),
extra data (based on the request given) - up to 18 bytes
} = 32 bytes = 256 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:
Keys: RSA-512
Hashes: SHA3-256