From 06db4135caa99ba2beac0846db777159161fa021 Mon Sep 17 00:00:00 2001 From: ramsesfv Date: Fri, 22 Mar 2024 16:18:32 +0100 Subject: [PATCH] Add files via upload --- vac/raw/Decentralized messaging Ethereum.md | 639 ++++++++++++++++++++ 1 file changed, 639 insertions(+) create mode 100644 vac/raw/Decentralized messaging Ethereum.md diff --git a/vac/raw/Decentralized messaging Ethereum.md b/vac/raw/Decentralized messaging Ethereum.md new file mode 100644 index 000000000..0d72714c2 --- /dev/null +++ b/vac/raw/Decentralized messaging Ethereum.md @@ -0,0 +1,639 @@ +--- +title: VAC-Decentralized Key and Session Setup for Secure Messaging over Ethereum +name: Decentralized Key and Session Setup for Secure Messaging over Ethereum +status: Raw +category: Informational +editor: Ramses Fernandez-Valencia +contributors: +--- +# Abstract +This document introduces a decentralized group messaging protocol using Ethereum adresses as identifiers. It is based in the proposal [DCGKA](https://eprint.iacr.org/2020/1281) by Weidner et al. It includes also approximations to overcome limitations related to using PKI and the multi-device setting. + +# Motivation + +The need for secure communications has become paramount. +Traditional centralized messaging protocols are susceptible to various security threats, including unauthorized access, data breaches, and single points of failure. +Therefore a decentralized approach to secure communication becomes increasingly relevant, offering a robust solution to address these challenges. + +Secure messaging protocols used should have the following key features: +1. **Asynchronous Messaging:** Users can send messages even if the recipients are not online at the moment. +2. **Resilience to Compromise:** If a user's security is compromised, the protocol ensures that previous messages remain secure through forward secrecy (FS). +This means that messages sent before the compromise cannot be decrypted by adversaries. +Additionally, the protocol maintains post-compromise security (PCS) by regularly updating keys, making it difficult for adversaries to decrypt future communication. +3. **Dynamic Group Management:** Users can easily add or remove group members at any time, reflecting the flexible nature of communication within the app. + +In this field, there exists a *trilemma*, similar to what one observes in blockchain, involving three key aspects: +1. security, +2. scalability, and +3. decentralization. + +For instance, protocols like the [MLS](https://messaginglayersecurity.rocks) perform well in terms of scalability and security. +However, they falls short in decentralization. + +Newer studies such as [CoCoa](https://eprint.iacr.org/2022/251) improve features related to security and scalability, +but they still rely on servers, which may not be fully trusted though they are necessary. + +On the other hand, older studies like [Causal TreeKEM](https://mattweidner.com/assets/pdf/acs-dissertation.pdf) exhibit decent scalability (logarithmic) +but lack forward secrecy and have weak post-compromise security (PCS). + +The creators of [DCGKA](https://eprint.iacr.org/2020/1281) introduce a decentralized, asynchronous secure group messaging protocol that supports dynamic groups. +This protocol operates effectively on various underlying networks without strict requirements on message ordering or latency. +It can be implemented in peer-to-peer or anonymity networks, accommodating network partitions, high latency links, and disconnected operation seamlessly. +Notably, the protocol doesn't rely on servers or a consensus protocol for its functionality. + +This proposal provides end-to-end encryption with forward secrecy and post-compromise security, even when multiple users concurrently modify the group state. + +# Theory +## Protocol overview + +This protocol makes use of ratchets to provide FS by encrypting each message with a different key, as shown in the figure below: + +![ratchet](ratchet.png) + +In the figure one can see the ratchet for encrypting a sequence of messages. +The sender requires an initial update secret `I_1`, which is introduced in a PRG. +The PRG will produce two outputs, namely a symmetric key for AEAD encryption, and a seed for the next ratchet state. +The associated data needed in the AEAD encryption includes the message index `i`. +The ciphertext `c_i` associated to message `m_i` is then broadcasted to all group members. +The next step requires deleting `I_1`, `k_i` and any old ratchet state. + +After a period of time the sender may replace the ratchet state with new update secrets `I_2`, `I_3`, and so on. + +To start a post-compromise security update, a user creates a new random value known as a seed secret and shares it with every other group member through a secure two-party channel. +Upon receiving the seed secret, each group member uses it to calculate an update secret for both the sender's ratchet and their own. +Additionally, the recipient sends an unencrypted acknowledgment to the group confirming the update. +Every member who receives the acknowledgment updates not only the ratchet for the original sender but also the ratchet for the sender of the acknowledgment. +Consequently, after sharing the seed secret through `n - 1` two-party messages and confirming it with `n - 1` broadcast acknowledgments, +every group member has derived an update secret and updated their ratchet accordingly. + +When removing a group member, the user who initiates the removal conducts a post-compromise security update +by sending the update secret to all group members except the one being removed. +To add a new group member, each existing group member shares the necessary state with the new user, +enabling them to derive their future update secrets. + +Since group members may receive messages in various orders, +it's important to ensure that each sender's ratchet is updated consistently +with the same sequence of update secrets at each group member. + +The network protocol used in this scheme ensures that messages from the same sender are processed in the order they were sent. + +## Components of the protocol + +This protocol relies in 3 components: authenticated causal broadcast (ACB), decentralized group membership (DGM) and 2-party secure messaging (2SM). + +### Authenticated causal broadcast +A causal order is a partial order relation `<` on messages. +Two messages `m_1` and `m_2` are causally ordered, or `m_1` causally precedes `m_2` +(denoted by `m_1 < m_2`), if one of the following contiditions hold: + +1. `m_1` and `m_2` were sent by the same group member, and `m_1` was sent before `m_2`. +2. `m_2` was sent by a group member U, and `m_1` was received and processed by `U` before sending `m_2`. +3. There exists `m_3` such that `m_1 < m_3` and `m_3 < m_2`. + +Causal broadcast requires that before processing `m`, a group member must process all preceding messages `{m' | m' < m}`. + +The causal broadcast module used in this protocol authenticates the sender of each message, +as well as its causal ordering metadata, using a digital signature under the sender’s identity key. +This prevents a passive adversary from impersonating users or affecting causally ordered delivery. + +### Decentralized group membership +This protocol assumes the existence of a DGM function (denoted as DGM) +that takes a set of membership change messages and their causal order relantionships, +and returns the current set of group members’ IDs. +It needs to be deterministic and depend only on causal order, and not exact order. + +### 2-party secure messaging (2SM) +This protocol makes use of bidirectional 2-party secure messaging schemes, which consist of 3 algorithms: `2SM-Init`, `2SM-Send` and `2SM-Receive`. + +#### 2SM-Init +This function takes two IDs as inputs: ID1 representing the local user and ID2 representing the other party. +It returns an initial protocol state sigma`. +The 2SM protocol relies on a Public Key Infrastructure (PKI) or a key server to map these IDs to their corresponding public keys. +In practice, the PKI should incorporate ephemeral prekeys. +This allows users to send messages to a new group member, even if that member is currently offline. + +#### 2SM-Send +This function takes a state `sigma` and a plaintext `m` as inputs, and returns a new state `sigma’` and a ciphertext `c`. + +#### 2SM-Receive +This function takes a state sigma` and a ciphertext `c`, and returns a new state sigma’` and a plaintext `m`. + +# 2SM Syntax + +The variable `sigma` denotes the state consisting in the variables below: +``` +sigma.mySks[0] = sk +sigma.nextIndex = 1 +sigma.receivedSk = empty_string +sigma.otherPk = pk`
+sigma.otherPksender = “other” +sigma.otherPkIndex = 0 +``` + +## 2SM-Init +On input a key pair `(sk, pk)`, this functions otuputs a state `sigma`. + +## 2SM-Send +This function encrypts the message `m` using `sigma.otherPk`, which represents the other party’s current public key. +This key is determined based on the last public key generated for the other party or the last public key received from the other party, +whichever is more recent. +sigma.otherPkSender` is set to `me` in the former case and `other` in the latter case. + +Metadata including `otherPkSender` and `otherPkIndex` are included in the message to indicate which of the recipient’s public keys is being utilized. + +Additionally, this function generates a new key pair for the local user, storing the secret key in sigma.mySks` and sending the public key. +Similarly, it generates a new key pair for the other party, sending the secret key (encrypted) and storing the public key in sigma.otherPk`. + +``` +sigma.mySks[sigma.nextIndex], myNewPk) = PKE-Gen() +(otherNewSk, otherNewPk) = PKE-Gen() +plaintext = (m, otherNewSk, sigma`.nextIndex, myNewPk) +msg = (PKE-Enc(sigma.otherPk, plaintext), sigma.otherPkSender, sigma.otherPkIndex) +sigma.nextIndex++ +(sigma.otherPk, sigma.otherPkSender, sigma.otherPkIndex) = (otherNewPk, "me", empty_string) +return (sigma`, msg) +``` + +## 2SM-Receive + +This function utilizes the metadata of the message `c` to determine which secret key to utilize for decryption, assigning it to `sk`. +If the secret key corresponds to one generated by ourselves, that secret key along with all keys with lower index are deleted. +This deletion is indicated by `sigma.mySks[≤ keyIndex] = empty_string`. +Subsequently, the new public and secret keys contained in the message are stored. + +``` +(ciphertext, keySender, keyIndex) = c +if keySender = "other" then +sk = sigma.mySks[keyIndex] +sigma.mySks[≤ keyIndex] = empty_string +else sk = sigma.receivedSk +(m, sigma.receivedSk, sigma.otherPkIndex, sigma.otherPk) = PKE-Dec(sk, ciphertext) +sigma.otherPkSender = "other" +return (sigma, m) +``` +# PKE Syntax + +The required PKE that MUST be used is ElGamal with a 2048-bit modulus `p`. + +## Parameters + +The following parameters must be used: + +``` +p = 308920927247127345254346920820166145569 +g = 2 +``` + +## PKE-KGen + +Each user `u` MUST do the following: + +``` +PKE-KGen(): +a = randint(1, p-2) +pk = (p, g, g^a) +sk = a +return (pk, sk) +``` + +## PKE-Enc + +A user `v` encrypting a message `m` for `u` MUST follow these steps: + +``` +PKE-Enc(pk): +k = randint(1, p-2) +eta = g^k % p +delta = m * (g^a)^k % p +return ((eta, delta)) +``` + +## PKE-Dec + +The user `u` recovers a message `m` from a ciphertext `c` by performing the following operations: + +``` +PKE-Dec(sk): +mu = eta^(p-1-sk) % p +return ((mu` * delta) % p) +``` + +# DCGKA Syntax +## Auxiliary functions + +There exist 6 functions that are auxiliary for the rest of components of the protocol, namely: + +### init + +This function takes an `ID` as input and returns its associated initial state, denoted by `gamma`: + +``` +gamma.myId = ID +gamma.mySeq = 0 +gamma.history = empty +gamma.nextSeed = empty_string +gamma.2sm[·] = empty_string +gamma.memberSecret[·, ·, ·] = empty_string +gamma.ratchet[·] = empty_string +return (gamma) +``` + +### encrypt-to + +Upon reception of the recipient’s `ID` and a plaintext, it encrypts a direct message for another group member. +Should it be the first message for a particular `ID`, then the `2SM` protocol state is initialized and stored in `gamma.2sm[recipient.ID]`. +One then uses `2SM_Send` to encrypt the message and store the updated protocol in `gamma`. + +``` +if gamma.2sm[recipient_ID] = empty_string then +gamma.2sm[recipient_ID] = 2SM_Init(gamma.myID, recipient_ID) +(gamma.2sm[recipient_ID], ciphertext) = 2SM_Send(gamma.2sm[recipient_ID], plaintext) +return (\gamma, ciphertext) +``` + +### decrypt-from + +After receiving the sender’s `ID` and a ciphertext, it behaves as the reverse function of `encrypt-to` and has a similar initialization: + +``` +if gamma.2sm[sender_ID] = empty_string then +gamma.2sm[sender_ID] = 2SM_Init(gamma.myID, sender_ID) +(gamma.2sm[sender_ID], plaintext) = 2SM_Receive(gamma.2sm[sender_ID], ciphertext) +return (gamma, plaintext) +``` + +### update-ratchet + +This function generates the next update secret `I` for the group member `ID`. +The ratchet state is stored in `gamma.ratchet[ID]`. +It is required to use a HMAC-based key derivation function HKDF to combine the ratchet state with an input, returning an update secret and a new ratchet state. + +``` +(updateSecret, gamma.ratchet[ID]) = HKDF(gamma.ratchet[ID], input) +return (gamma, updateSecret) +``` + +### member-view + +This function calculates the set of group members based on the most recent control message sent by the specified user `ID`. +It filters the group membership operations to include only those observed by the specified `ID`, and then invokes the DGM function to generate the group membership. + +``` +ops = {m in gamma.history st. m was sent or acknowledged by ID} +return DGM(ops) +``` + +### generate-seed + +This functions generates a random bit string and sends it encrypted to each member of the group using the `2SM` mechanism. +It returns the updated protocol state and the set of direct messages to send. + +``` +gamma.nextSeed = random.randbytes() +dmsgs = empty +for each ID in recipients: +(gamma, msg) = encrypt-to(gamma, ID, gamma.nextSeed) +dmsgs = dmsgs + (ID, msg) +return (gamma, dmsgs) +``` + +## Creation of a group + +A group is generated in a 3 steps procedure: + +1. A user calls the `create` function and broadcasts a control message of type *create*. +2. Each receiver of the message processes the message and broadcasts an *ack* control message. +3. Each member processes the *ack* message received. + +### create +This function generates a *create* control message and calls `generate-seed` to define the set of direct messages that need to be sent. +Then it calls `process-create` to process the control message for this user. +The function `process-create` returns a tuple including an updated state gamma and an update secret $I$. + +``` +control = (“create”, gamma.mySeq, IDs) +(gamma, dmsgs) = generate-seed(gamma, IDs) +(gamma, _, _, I, _) = process-create(gamma, gamma.myId, gamma.mySeq, IDs, empty_string) +return (gamma, control, dmsgs, I) +``` + +### process-seed +This function initially employs `member-view` to identify the users who were part of the group when the control message was dispatched. +Then, it attempts to acquire the seed secret through the following steps: + +1. If the control message was dispatched by the local user, it uses the most recent invocation of `generate-seed` stored the seed secret in gamma.nextSeed. +2. If the *control* message was dispatched by another user, and the local user is among its recipients, +the function utilizes `decrypt-from` to decrypt the direct message that includes the seed secret. +3. Otherwise, it returns an *ack* message without deriving an update secret. + +Afterwards, `process-seed` generates separate member secrets for each group member from the seed secret by combining the seed secret and each user ID using HKDF. +The secret for the sender of the message is stored in *senderSecret*, +while those for the other group members are stored in gamma.memberSecret. +The sender's member secret is immediately utilized to update their KDF ratchet and compute their update secret `I_sender` using `update-ratchet`. +If the local user is the sender of the control message, the process is completed, and the update secret is returned. +However, if the seed secret is received from another user, an *ack* control message is constructed for broadcast, +including the sender ID and sequence number of the message being acknowledged. + +The final step computes an update secret `I_me` for the local user invoking the `process-ack` function. + +``` +recipients = member-view(gamma, sender) - {sender} +if sender = gamma.myId then seed = gamma.nextSeed; gamma.nextSeed = empty_string +else if gamma.myId in recipients then (gamma, seed) = decrypt-from(gamma, sender, dmsg) +else +return (gamma, (ack, ++gamma.mySeq, (sender, seq)), empty_string , empty_string , empty_string) + +for ID in recipients do gamma.memberSecret[sender, seq, ID] = HKDF(seed, ID) + +senderSecret = HKDF(seed, sender) +(gamma, $I_{sender}$) = update-ratchet(gamma, sender, senderSecret) +if sender = gamma.myId then return (gamma, empty_string , empty_string , I_sender, empty_string) +control = (ack, ++gamma.mySeq, (sender, seq)) +members = member-view(gamma, gamma.myId) +forward = empty +for ID in {members - (recipients + {sender})}` + s = gamma.memberSecret[sender, seq, gamma.myId] + (gamma, msg) = encrypt-to(gamma, ID, s) + forward = forward + {(ID, msg)} + +(gamma, _, _, I_me, _) = process-ack(gamma, gamma.myId, gamma.mySeq, (sender, seq), empty_string) +return (gamma, control, forward, I_sender, I_me) +``` + +### process-create +This function is called by the sender and each of the receivers of the *create* control message. +First, it records the information from the create message in the `gamma.history+, +which is used to track group membership changes. Then, it proceeds to call `process-seed`. + +``` +op = (”create”, sender, seq, IDs) +gamma$.history = gamma.history + {op} +return (process-seed(gamma, sender, seq, dmsg)) +``` + +### process-ack +This function is called by those group members once they receive an ack message. +In `process-ack`, `ackID` and `ackSeq` are the sender and sequence number of the acknowledged message. +Firstly, if the acknowledged message is a group membership operation, it records the acknowledgement in `gamma.history`. + +Following this, the function retrieves the relevant member secret from `gamma.memberSecret` which was previously obtained from the seed secret contained in the acknowledged message. + +Finally, it updates the ratchet for the sender of the *ack* and returns the resulting update secret. + +``` +if (ackID, ackSeq) was a create / add / remove then +op = ("ack", sender, seq, ackID, ackSeq) +gamma$.history = gamma.history + {op}` +s = gamma.memberSecret[ackID, ackSeq, sender] +gamma$.memberSecret[ackID, ackSeq, sender] = empty_string +if (s = empty_string) & (dmsg = empty_string) then return (gamma, empty_string, empty_string, empty_string, empty_string) +if (s = empty_string) then (gamma, s) = decrypt-from(gamma, sender, dmsg) +(gamma, I) = update-ratchet(gamma, sender, s) +return (gamma, empty_string, empty_string, I, empty_string) +``` + +The HKDF function MUST follow RFC 5869 using the hash function SHA256. + + +## Post-compromise security updates and group member removal + +The functions `update` and `remove` share similarities with `create`: +they both call the function `generate-seed` to encrypt a new seed secret for each group member. +The distinction lies in the determination of the group members using `member-view`. +In the case of `remove`, the user being removed is excluded from the recipients of the seed secret. +Additionally, the control message they construct is designated with type *update* or *remove* respectively. + +Likewise, `process-update` and `process-remove` are akin to `process-create`. +The function `process-update` skips the update of gamma.history, whereas `process-remove` includes a removal operation in the history. + +### update +``` +control = ("update", ++gamma.mySeq, empty_string) +recipients = member-view(gamma, gamma.myId) - {gamma.myId} +(gamma, dmsgs) = generate-seed(gamma, recipients) +(gamma, _, _, I , _) = process-update(gamma, gamma.myId, gamma.mySeq, empty_string, empty_string) +return (gamma, control, dmsgs, I) +``` + +### remove +``` +control = ("remove", ++gamma.mySeq, empty) +recipients = member-view(gamma, gamma.myId) - {ID, gamma.myId} +(gamma, dmsgs) = generate-seed(gamma, recipients) +(gamma, _, _, I , _) = process-update(gamma, gamma.myId, gamma.mySeq, ID, empty_string) +return (gamma, control, dmsgs, I) +``` + +### process-update +`return process-seed(gamma, sender, seq, dmsg)` + +### process-remove +``` +op = ("remove", sender, seq, removed) +gamma.history = gamma.history + {op} +return process-seed(gamma, sender, seq, dmsg) +``` + +## Group member addition + +### add +When adding a new group member, an existing member initiates the process by invoking the `add` function and providing the ID of the user to be added. +This function prepares a control message marked as *add* for broadcast to the group. +Simultaneously, it creates a welcome message intended for the new member as a direct message. +This *welcome* message includes the current state of the sender's KDF ratchet, encrypted using `2SM`, along with the history of group membership operations conducted so far. + +``` +control = ("add", ++gamma.mySeq, ID) +(gamma, c) = encrypt-to(gamma, ID, gamma.ratchet[gamma.myId]) +op = ("add", gamma.myId, gamma.mySeq, ID) +welcome = (gamma.history + {op}, c) +(gamma, _, _, $I$, _) = process-add(gamma, gamma.myId, gamma.mySeq, ID, empty_string) +return (gamma, control, {(ID, welcome)}, $I$) +``` + +### process-add +This function is invoked by both the sender and each recipient of an *add* message, which includes the new group member. +If the local user is the newly added member, the function proceeds to call `process-welcome` and then exits. +Otherwise, it extends `gamma.history` with the `add` operation. + +Line 5 determines whether the local user was already a group member at the time the "add" message was sent; +this condition is typically true but may be false if multiple users were added concurrently. + +On lines 6 to 8, the ratchet for the sender of the *add* message is updated twice. +In both calls to `update-ratchet`, a constant string is used as the ratchet input instead of a random seed secret. + +The value returned by the first ratchet update is stored in `gamma.memberSecret` as the added user’s initial member secret. +The result of the second ratchet update becomes I_sender, the update secret for the sender of the *add* message. On line 10, if the local user is the sender, the update secret is returned. + +If the local user is not the sender, an acknowledgment for the *add* message is required. +Therefore, on line 11, a control message of type *add-ack* is constructed for broadcast. +Subsequently, in line 12 the current ratchet state is encrypted using `2SM` to generate a direct message intended for the added user, +allowing them to decrypt subsequent messages sent by the sender. +Finally, in lines 13 to 15, `process-add-ack` is called to calculate the local user’s update secret (I_me), which is then returned along with I_sender. + +``` +if added = gamma.myId then return process-welcome(gamma, sender, seq, dmsg) +op = ("add", sender, seq, added) +gamma.history = gamma.history + {op} +if gamma.myId in member-view(gamma, sender) then + (gamma, s) = update-ratchet(\gamma, sender, "welcome") + gamma.memberSecret[sender, seq, added] = s + (gamma, I_sender) = update-ratchet(gamma, sender, "add") +else I_sender = empty_string +if sender = gamma.myId then return (gamma, empty_string, empty_string, I_sender, empty_string) +control = ("add-ack", ++gamma.mySeq, (sender, seq)) +(gamma, c) = encrypt-to(gamma, added, ratchet[gamma.myId]) +(gamma, _, _, I_me, _) = process-add-ack(gamma, gamma.myId, gamma.mySeq, (sender, seq), empty_string) +return (gamma, control, {(added, c)}, I_sender, I_me) +``` + +### process-add-ack +This function is invoked by both the sender and each recipient of an *add-ack* message, including the new group member. +Upon lines 1–2, the acknowledgment is added to `gamma.history`, mirroring the process in `process-ack`. +If the current user is the new group member, the *add-ack* message includes the direct message constructed in `process-add`; +this direct message contains the encrypted ratchet state of the sender of the *add-ack*, then it is decrypted on lines 3–5. + +Upon line 6, a check is performed to check if the local user was already a group member at the time the *add-ack* was sent. +If affirmative, a new update secret `I` for the sender of the *add-ack* is computed on line 7 by invoking `update-ratchet` with the constant string *add*. + +In the scenario involving the new member, the ratchet state was recently initialized on line 5. T +This ratchet update facilitates all group members, including the new addition, to derive each member’s update by obtaining any update secret from before their inclusion. + +``` +op = ("ack", sender, seq, ackID, ackSeq) +gamma$.history = gamma.history + {op} +if dmsg != empty_string then + (gamma, s) = decrypt-from(gamma, sender, dmsg) + gamma.ratchet[sender] = s +if gamma.myId in member-view(gamma, sender) then + (gamma, $I$) = update-ratchet(gamma, sender, "add") + return (gamma, empty_string, empty_string, I, empty_string) +else return (gamma, empty_string, empty_string, empty_string, empty_string) +``` + +### process-welcome +This function serves as the second step called by a newly added group member. +In this context, *adderHistory* represents the adding user’s copy of `gamma.history` sent in their welcome message, which is utilized to initialize the added user’s history. +Here, `c` denotes the ciphertext of the adding user’s ratchet state, which is decrypted on line 2 using `decrypt-from`. + +Once `gamma.ratchet[sender]` is initialized, `update-ratchet` is invoked twice on lines 3 to 5 with the constant strings *welcome* and *add* respectively. +These operations mirror the ratchet operations performed by every other group member in `process-add`. +The outcome of the first `update-ratchet` call becomes the first member secret for the added user, while the second call returns I_sender, +the update secret for the sender of the add operation. + +Subsequently, the new group member constructs an *ack* control message to broadcast on line 6 and calls `process-ack` to compute their initial update secret I_me. +The function `process-ack` reads from `gamma.memberSecret` and passes it to `update-ratchet`. +The previous ratchet state for the new member is the empty string `empty`, as established by `init`, thereby initializing the new member’s ratchet. +Upon receiving the new member’s *ack*, every other group member initializes their copy of the new member’s ratchet in a similar manner. + +By the conclusion of `process-welcome`, the new group member has acquired update secrets for themselves and the user who added them. +The ratchets for other group members are initialized by `process-add-ack`. + +``` +gamma.history = adderHistory +(gamma, gamma.ratchet[sender]) = decrypt-from(gamma, sender, c) +(gamma, s) = update-ratchet(gamma, sender, "welcome") +gamma$.memberSecret[sender, seq, gamma.myId] = s +(gamma, I_sender) = update-ratchet(gamma, sender, "add") +control = ("ack", ++gamma.mySeq, (sender, seq)) +(gamma, _, _, I_me, _) = process-ack(gamma, gamma.myId, gamma.mySeq, (sender, seq), empty_string) +return (gamma, control, empty_string , I_sender, I_me) +``` + +# Privacy Considerations + +## Dependency on PKI +The [DCGKA](https://eprint.iacr.org/2020/1281) proposal presents some limitations highlighted by the authors. +Among these limitations one finds the requirement of a PKI (or a key server) mapping IDs to public keys. + +One method to overcome this limitation is adapting the protocol SIWE (Sign in with Ethereum) so a user `u_1` who wants to start a communication with a user `u_2` can interact with latter’s wallet to request a public key using an Ethereum address as `ID`. + +### SIWE +The [SIWE](https://docs.login.xyz/general-information/siwe-overview) (Sign In With Ethereum) proposal was a suggested standard for leveraging Ethereum to authenticate and authorize users on web3 applications. +Its goal is to establish a standardized method for users to sign in to web3 applications using their Ethereum address and private key, +mirroring the process by which users currently sign in to web2 applications using their email and password. +Below follows the required steps: + +1. A server generates a unique Nonce for each user intending to sign in. +2. A user initiates a request to connect to a website using their wallet. +3. The user is presented with a distinctive message that includes the Nonce and details about the website. +4. The user authenticates their identity by signing in with their wallet. +5. Upon successful authentication, the user's identity is confirmed or approved. +6. The website grants access to data specific to the authenticated user. + +### Our approach +The idea in the [DCGKA](https://eprint.iacr.org/2020/1281) setting closely resembles the procedure outlined in SIWE. Here: + +1. The server corresponds to user D1, who initiates a request (instead of generating a nonce) to obtain the public key of user D2. +2. Upon receiving the request, the wallet of D2 send the request to the user, +3. User D2 receives the request from the wallet, and decides whether accepts or rejects. +4. The wallet and responds with a message containing the requested public key in case of acceptance by D2. + +This message may be signed, allowing D1 to verify that the owner of the received public key is indeed D2. + +## Multi-device setting +One may see the set of devices as a group and create a group key for internal communications. +One may use treeKEM for instance, since it provides interesting properties like forward secrecy and post-compromise security. +All devices share the same `ID`, which is hold by one of them, and from other user’s point of view, they would look as a single user. + +Using servers, like in the paper [Multi-Device for Signal](https://eprint.iacr.org/2019/1363), should be avoided; +but this would imply using a particular device as receiver and broadcaster within the group. +There is an obvious drawback which is having a single device working as a “server”. +Should this device be attacked or without connection, there should be a mechanism for its revocation and replacement. + +Another approach for communications between devices could be using the keypair of each device. +This could open the door to use UPKE, since keypairs should be regenerated frequently. + +Each time a device sends a message, either an internal message or an external message, it needs to replicate and broadcast it to all devices in the group. + +![Captura de pantalla 2024-03-21 a les 12.07.23.png](https://prod-files-secure.s3.us-west-2.amazonaws.com/1518abd9-c08f-4989-93c1-96525e62bce5/9144c2dd-aa6c-4f7c-9acc-f9dc7f18661d/Captura_de_pantalla_2024-03-21_a_les_12.07.23.png) + +The mechanism for the substitution of misbehaving leader devices follows: + +1. Each device within a group knows the details of other leader devices. This information may come from metadata in received messages, and is replicated by the leader device. +2. To replace a leader, the user should select any other device within its group and use it to send a signed message to all other users. +3. To get the ability to sign messages, this new leader should request the keypair associated to the ID to the wallet. +4. Once the leader has been changed, it revocates access from DCGKA to the former leader using the DCGKA protocol. +5. The new leader starts a key update in DCGKA. + +Not all devices in a group should be able to send messages to other users. +Only the leader device should be in charge of sending and receiving messages. +To prevent other devices from sending messages outside their group, a requirement should be signing each message. +The keys associated to the `ID` should only be in control of the leader device. + +The leader device is in charge of setting the keys involved in the DCGKA. +This information must be replicated within the group to make sure it is updated. + +To detect missing messages or potential misbehavior, messages must include a counter. + +# Using UPKE + +Managing the group of devices of a user can be done either using a group key protocol such as treeKEM or using the keypair of each device. +Setting a common key for a group of devices under the control of the same actor might be excessive, +furthermore it may imply some of the problems one can find in the usual setting of a group of different users; +for example: one of the devices may not participate in the required updating processes, representing a threat for the group. + +The other approach to managing the group of devices is using each device’s keypair, +but it would require each device updating these materia frequently, something that may not happens. + +[Updatable public-key encryption](https://eprint.iacr.org/2022/068) is a form of asymetric cryptography +where any user can update any other user’s key pair by running an update algorithm with (high-entropy) private coins. +Any sender can initiate a *key update* by sending a special update ciphertext. +This ciphertext updates the receiver’s public key and also, once processed by the receiver, will update their secret key. + +To the best of my knowledge, there exists several efficient constructions both [classic](https://eprint.iacr.org/2019/1189) (based in the DH assumption) and [postquantum]((https://eprint.iacr.org/2023/1400)) (based in lattices). +None of them have been implemented in a secure messaging protocol, and this opens the door to some novel research. + +# Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +# References +- [Causal TreeKEM](https://mattweidner.com/assets/pdf/acs-dissertation.pdf) +- [CoCoa](https://eprint.iacr.org/2022/251) +- [DCGKA](https://eprint.iacr.org/2020/1281) +- [MLS](https://messaginglayersecurity.rocks) +- [Multi-device for Signal](https://eprint.iacr.org/2019/1363) +- [UPKE](https://eprint.iacr.org/2022/068) +- [UPKE from ElGamal](https://eprint.iacr.org/2019/1189) +- [UPKE from Lattices](https://eprint.iacr.org/2023/1400) \ No newline at end of file