PeaceFounder / PeaceFounder.jl

Centralised E2E verifiable evoting via pseudonym braiding and history trees
http://peacefounder.org
Apache License 2.0
17 stars 1 forks source link

Cast as intended verification during the vote #21

Closed JanisErdmanis closed 5 months ago

JanisErdmanis commented 8 months ago

At present, voters can only confirm that their vote has been cast as intended and accurately counted after the vote has ended and the votes are published. As the publication of votes can be delayed as a measure against coercion, it might discourage voters' participation from verifying that their vote is indeed cast as intended and counted as cast. The key issue lies in the possibility of unnoticed malware on voting devices. If voters don't verify their votes, the likelihood of malware affecting a significant number of votes without detection increases. Thus, having a procedure that enables immediate verification of the voting process is essential to engage more voters to check their votes.

The PeaceFounder system can address this by providing voters with a token displayed on the client's screen for vote verification. This token can be used in a web browser to confirm that the vote has been cast as intended. It also indicates if the vote has been superseded by a subsequent vote or one with a higher sequence number, which may occur if the member's key is compromised. To maintain receipt-freeness, the token remains valid for only a short period, such as 15 minutes. The expiration is crucial; it allows voters to verify their votes while preventing coercion or bribery attempts. It also hinders any unsolicited checks on voters' choices.

The most straightforward method to generate a token is using the byte string of the vote. This is done by setting the token as $token={\rm{Hash}}(0|vote)$, where the vote itself is the secret to be safeguarded. To utilise this token, an HTTP request is sent to the server containing $TokenID={\rm Hash}(token)$ along with an HMAC of the request. This request is directed to:

GET /ballotbox/{proposal_index}/votes/peek/{token_id}

When the server receives a vote verification request, it first checks that the token is valid and has not expired and then returns the vote's metadata. To maintain the integrity of this response during its transmission, the reply is secured with HMAC. Additionally, encrypting this reply would be advantageous to safeguard the voter's privacy when their network is under surveillance.

However, this approach has limitations. It doesn't prevent the possibility of a network monitor storing data for future comparison with the information on the ballotbox ledger, where votes and, therefore, tokens are eventually published. To enhance security in this aspect, the token could be derived from the Diffie-Hellman key, which could remain secret indefinitely. The server would generate a key pair and incorporate the public key into the receipt, whereas locally exponentiate pseudonym to derive the key.

There's also the risk of a corrupt election authority monitoring the voter. That could trace the voter's pseudonym back to their IP address and, ultimately, their identity. The most effective way to mitigate this risk is to run these requests through a TOR browser, ensuring anonymity. An ultimate solution from a usability point of view would be if the TOR client could be embedded within web assembly to make the request, but there does not seem to be support for that.

For this issue, the following tasks thus need to be addressed:

Regarding the website interface, several technical details must be specified: the server's address, the Hash/HMAC function for request authorisation, and the encryption method for replies. However, these technicalities will be seamlessly integrated into the user experience. A custom-designed bulletin board facade will hardcode these parameters, requiring the user only to input the token.

It's crucial to highlight that while voters can verify their vote to be cast as intended through this system, there remains uncertainty. Voters cannot be assured that malware won't ultimately influence the election results by altering their votes or adding a coercion tag invalidating it (which is not disclosed). Additionally, this implementation does not guard against the possibility of the server providing misleading information about the vote being cast. In such a scenario, the worst-case recourse for voters would be to recast their vote and eventually compare it with the ballotbox ledger after the votes are published.

JanisErdmanis commented 7 months ago

I've made a significant advancement in integrating the API authorisation on the Julia side, achieving compatibility with the existing JavaScript implementation right from the outset. This small milestone includes the development of fetchAuthorize in JavaScript, mirroring the functionality of the standard fetch method but with an additional feature: it accepts an authorisation key to sign the request and verify the signed response.

On the Julia side, I've introduced AuthorizationMiddleware, which is designed to simplify adaptation to various requirements. This middleware facilitates the seamless integration of authorisation mechanisms into our existing infrastructure. Also, CORS issues have been resolved so that the requests can be made from a random static page without issues.

I have put proof of concept in this gist. This implementation freezes Julia and JavaScript for endpoint authorisation APIs for #14, so work can continue on the refactor.

JanisErdmanis commented 7 months ago

One of the setbacks for anonymity looks like it is going to be the User-Agent header, which puts rather specific information in combination with an IP address, making tracking for a corrupt server easy. Thus, the use of TOR is recommended when making such requests.

From a UX standpoint, it would be great if the verification of the vote could be performed only if the user opens the webpage with TOR. This, however, seems impossible to do as TOR has put an effort to make it indistinguishable from an ordinary browser.

JanisErdmanis commented 6 months ago

The webiste interface will be cosidered seperatelly. For this issue it is only important that the voter's client shows a token after casting the vote and that it can be used to query the vote from terminal making a coresponding HTTP request.

JanisErdmanis commented 5 months ago

Screenshot 2024-04-23 at 02 36 33 Screenshot 2024-04-23 at 02 35 58

The access codes have been implemented. On the left, it is shown how it is displayed to the voter, put in brackets next to the cast record. This approach was chosen in contrast to placing the access code in a new line because:

The access code is kept short at 4 bytes. This is, however, a bit too small as an adversary can make a credential -> key mapping table, which only takes 16GB. The key size could be increased to 5 bytes to increase the strength, which would make the table take around 16TB. There are two user-friendly options to increase the key size:

The first option would be nicer from the users' point of view. ~However, there is no standard way to do so.~ A base32 encoding like outlined here would be suitable. The second option is dead simple for developing.

Another factor that can strengthen the key is making the adversary invalidate the table frequently:

The next aspect is the encryption of the response. This aspect is dropped because it takes significant effort to make compatible encryption between CryptoJS in Javascript and Nettle in Julia. A padding issue is involved, so the adversary could not know how the voter voted, depending on the response length.

For access codes, it does look like a much better option to strengthen them is either on the voter side:

For the first option, a node-TOR project looks relevant, which could allow to make requests through a static web page without voter needing to run the TOR browser on their own. The second option is a more pragmatic approach and can be easily implemented, but it would not help to maintain untraceability from the server itself.

JanisErdmanis commented 5 months ago

Crockford base32 encoding has now been implemented, thus increasing the tracking code size to 5 bytes and, as a result, increasing the decoding table to 5TB (5 * 256^5 / 1024^4).