The client

So far, we have focused mostly on the server part of the bulletin board. But some of the logic, as the message signing, is done in the clients side. So, the system also includes some client libraries to be used within the software that manages users and permissions. In our case, this software is Decidim, but the solution is prepared to support other options in the future if needed.

Ruby client

To be able to integrate the client inside the Decidim app, we needed to implement a Ruby client, released as a gem ( This gem includes a Client class that, once configured, allows to perform all the operations that are expected to be done by the authority:

  • create_election: Send a create_election message that will be used as a manifest for a new election in the bulletin board.

  • start_key_ceremony and start_tally: Send messages to start the phases that will require the participation of the trustees and the bulletin board. In fact, in both cases, the bulletin board will be responsible for sending the message to end those phases.

  • start_vote and end_vote: Send messages to start and end the voting period.

  • cast_vote: Send a ciphered ballot created by a voter to the bulletin board, in a vote.cast_vote message.

  • in_person_vote: Register that a ballot was cast physically by a voter, in a vote.in_person_vote message.

  • publish_results: Make the calculated results available publicly in the bulletin board.

There are also some auxiliary methods to retrieve information from the bulletin board:

  • get_election_results: Retrieve the election results from the bulletin board.

  • get_election_status: Retrieve the current status of an election.

  • get_pending_message_status Retrieve the status of a message pending to be processed. All the operations will return the identifier of the message sent and will not wait the message to be processed to return the control to the app. This method will allow the app to check if the message was already processed or if it is still enqueued.

The JavaScript client

Besides the server-side client, we also needed to build a JavaScript client to perform some tasks directly in the user machine. There are some scenarios where being able to send some queries from the browser improves the administrator user experience, but the main reason to have a JS client is to implement the trustees and voters logic.

Regarding trustees, the private identification keys need to be located only on the user machine, as we don’t want the authority to be able to sign trustees messages. This feature is implemented within the class IdentificationKeys in the JS client, and it is implemented using the browser’s Crypto API.

The trustee part also implements all the logic for the key ceremony and tally phases from the trustee perspective, reading messages from the bulletin board and sending responses when needed. In fact, this logic uses an abstract class called TrusteeWrapperAdapter, that should be implemented by the voting scheme to apply the cryptographic methods to create the election key during the key ceremony and to calculate results during the tally.

Concerning the voters, the important idea here is that the authority should not be able to see the voter’s plain ballot contents, so this part should be also implemented on the browser side. Therefore, the JS client implements the logic that retrieves the election definition and the public key used to cipher votes from the bulletin board election log. But for the actual process of ciphering of the votes, as with the trustees, the JS client only defines an abstract class called VoterWrapperAdapter, that should be implemented by the voting scheme code. This class receives the plaintext ballot and all the information needed to cipher it, and returns the ciphered ballot and the information needed to audit the ballot.

If the voter decides to cast the ballot, it can be sent to the authority to be signed and sent to the bulletin board. The voter can trust that the authority will not change the ballot contents because the ballot should appear in the bulletin board with an equal contentHash to the SHA256 calculated by the voter browser before casting it.

The voter calculates a hash of the ciphered ballot

The voter calculates a hash of the ciphered ballot, sends it to the Decidim server and checks the election log to be sure that the message content was not changed.

If the voter decides to audit the ballot, they will be able to download all the information generated by the voting scheme to verify that the vote is being cast as intended. We will explain the tool used to do this in the next section.