NOTE this is work-in-progress writing. Anything below may be incomplete.
TODO in progress
Invariants derived from the processes: ratcheting (rotating public keys), rotating chainkeys, sending/receiving messages.
- Perform ratchet
<==>
"first"- Ratchet with sender keys
<==>
send first message after receiving - Ratchet with receiver keys
<==>
receive first message after sending
- Ratchet with sender keys
- For each participant:
Ratchet i <==> (ECDH public key, DH public key )
,
with:DH public key is present <==> i % 3 == 0
. - DH ratchet every third brace key rotation. (
i % 3 == 0
) i
of Alice andi
of Bob are mutually dependent due to send/receive events triggering the ratchet. (increment in lock-step)max_remote_i_seen
value can be derived from knowledge of locali
(ratcheting state), given dependency of ratcheting to sending/receiving.- Double Ratchet has period of
6
ratchets: 2 consecutive periods of 3, each with one DH ratchet ("every third brace-key"). Each period provides a single DH ratchet for each participant. FIXME this needs checking, IIRC i-1 should be used.
When sending:i
is sender ratchet ID,i-1
is receiver ratchet ID. When receiving vice-versa.
Criticisms:
- It only adds complexity to describe two separate
i
values, one for each participant. As mentioned above, these are mutually dependent. - No data in a data message is reliable or trustworthy before authentication (including
i
, public keys). There is a short period where this data needs to be handled without making lasting state changes. - Resetting
i
to0
seems to have no relevance in terms of functionality or security, as we already usei % 3
where appropriate. The data-type is sufficiently large. i
, ECDH public keys, DH public keys are all equally untrustworthy before messages are authenticated and equally trustworthy afterwards (assuming no protocol violations). Therefore, no reason not to use incrementingi
as indicator for ratchet and message keys, as key inskipped_MKenc
store.- Even if
i
keeps incrementing, it is not an indicator of number of messages sent/received, any ratio between sent/received, or frequency.
- Even if
- Resetting
i
necessitates use of ECDH public key as identifier where necessary. However, the key does not offer any benefits. - Incorrect assumption: if any (delayed) message with pair
(ECDH public key, j)
was received and does not have a key in theskipped_MKenc
store, it must be duplicate.
This is not correct, as you cannot yet trust that the ECDH public key is reliable, trustworthy. Therefore, it either is duplicate or malicious or corrupted. However, this is not a big problem as we can authenticate and then we either discover that public key is correct and it is delayed/duplicate, or the message is corrupted/malicious and must be discarded. However, ECDH public key is at best useful, at worst redundant information.
Proposal 1: embrace (monotonically increasing) i
as identifier
- Drop
max_remote_i_seen
variable. (No benefit, derivable, superfluous.) - Drop resets of
i
. (No benefit, derivable when necessary withi % 3
.) - Have single notion of
i
for Alice and Bob, with understanding that semantics are swapped: anyi
that is Alice's sender ratchet, is Bob's receiver ratchet.- Is there a risk in ever-incrementing
i
value?
- Is there a risk in ever-incrementing
- Depends on monotonically incrementing value of
i
to determine ratcheting and whether messages are received next in sequence or delayed/out-of-order. - No longer use ECDH public key as identifier for ratchet. (Only as public key.)
- Cannot conclude duplicate messages: for any duplicate message, the Message Keys (if even previously stored) would now be gone. Without ability to authenticate, message could be: duplicate, corrupted or malicious.
- Would only need to track past public keys to detect reuse.
- Relying on
i
makes logic more complicated due to need to take into accounti-1
if sender next for rotation ori-2
if receiver next for rotation but message is from earlier ratchet therefore rotation is not yet required.
Proposal 2: embrace ECDH public key as (arbitrary) identifier
- Use ECDH public key as identifer for ratchet. (non-monotonic, not strictly increasing, ..)
- Drop
i
variable. (No benefit, not identifying, save 4 bytes OTRv4 Data message) - Need to keep a record of every past ECDH public key:
- unless all messages in corresponding ratchet are received and processed successfully. (The public key is no longer of use. And even then you would want to avoid reusing that keypair.)
- to determine whether message is part of next (receiving) ratchet, one would need to rotate and attempt to decrypt with assumption that embedded ECDH public key is part of next ratchet, and if that fails (because we fail to generate the appropriate
MKenc
andMKmac
secrets) then the message (evidently) wasn't part of the next ratchet. (Conversely, one first check presence of ECDH public key inskipped_MKenc
.) - in order to determine if message is part of next ratchet or received out-of-order from past ratchet.
- NOTE argument may be invalid: spec wants to keep track of public keys regardless, to prevent reuse.
- …