106 lines
4.7 KiB
Markdown
106 lines
4.7 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:
|
|
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)
|
|
|