some protocol cleanup and update
This commit is contained in:
parent
2a3be450be
commit
84d9bd0ef0
1 changed files with 19 additions and 68 deletions
87
protocol.md
87
protocol.md
|
@ -1,108 +1,59 @@
|
|||
# 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
|
||||
doesnt seem to be any reason to use a key derivation function.
|
||||
|
||||
## 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
|
||||
- User sends a `Register` requset giving them a public key and encrypting using the server's public key
|
||||
- Server sends the user a `VerificationRequired` (not in current code, as the 6 digit code does that for now) message & a 6-digit code (Secure channel)
|
||||
- User sends the server a `ConfirmRegister` with the 6-digit code, signed using the key provided at previous stage
|
||||
- Server verifies the signature and code, and if both are valid it sends a last `Confirm` and the registration process is done
|
||||
|
||||
## "Login"
|
||||
## 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
|
||||
Login is done by a challenge, the user sends a `Login` request, the server sends a random block of 16 bytes for the user to sign,
|
||||
then the server validates the signature with the known saved key.
|
||||
|
||||
## 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.
|
||||
A will then encrypt the message using B's key, append a signature, and send a `SendMessage`
|
||||
request with the payload having the structure of `Enc_b(Message object) + Signature_A(Message object)`.
|
||||
|
||||
The server will hold on to the message until B will send a `GetMessages` request
|
||||
to the server.
|
||||
|
||||
## "Control" requests
|
||||
## 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)
|
||||
data: 6 bytes for the 6 digit code, 4 bytes for signature length
|
||||
- Login:
|
||||
data: 8 bytes of user's phone
|
||||
- ConfirmLogin (signed hash):
|
||||
data: hash length
|
||||
- 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)
|
||||
- GetUserKey:
|
||||
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)`
|
||||
- SendMessage:
|
||||
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
|
||||
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
|
||||
looping counter - 1 byte,
|
||||
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)
|
||||
Encryption and Hashes used:
|
||||
public keys: RSA-1024 (can be of somewhat arbitrary length)
|
||||
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)
|
||||
|
||||
symmetric keys: AES-CFB-256 with PCKS7 padding (when needed as most stuff are made to fit in 1 block)
|
||||
|
|
Loading…
Add table
Reference in a new issue