online_security_project/protocol.md

107 lines
4.7 KiB
Markdown
Raw Permalink Normal View History

2024-12-01 17:40:08 +00:00
# The Protocol
All encryptions are made using RSA (key size to be determined), no symmetric encryptions
are used due to messages being short.
2024-12-14 15:17:58 +00:00
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
2024-12-01 17:40:08 +00:00
## 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
2024-12-14 15:17:58 +00:00
- Server sends the user a `VerificationRequired` message & a 6-digit code (Secure channel)
2024-12-01 17:40:08 +00:00
- 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.
2024-12-14 15:17:58 +00:00
## "Control" requests
2024-12-17 18:41:30 +00:00
- Register:
data: Phone - 8 bytes, RSA key size (payload length) - 2 bytes
2024-12-14 15:17:58 +00:00
- ConfirmRegister (signed & encrypted 6 digit code)
2024-12-17 18:41:30 +00:00
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
2024-12-17 18:41:30 +00:00
- GetMessages:
data: EMPTY
2024-12-14 15:17:58 +00:00
- 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)`
2024-12-17 18:41:30 +00:00
extra data: 8 bytes (4 bits per digit) of who to send the data, 4 bytes (32bit) for length in bytes
2024-12-14 15:17:58 +00:00
I think it all can go into a:
```
{
Version byte (0) - 1 byte
RequestType - 1 byte,
2024-12-17 18:41:30 +00:00
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
2024-12-14 15:17:58 +00:00
```
2024-12-17 18:41:30 +00:00
2024-12-14 15:17:58 +00:00
and we can just append encrypted payloads to it (in SendMessage and SendAck)
2024-12-14 17:10:09 +00:00
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
2024-12-14 15:17:58 +00:00
enc_server( request - 256 bits, signed sha3-256 )
which means:
2024-12-17 18:41:30 +00:00
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)