At this stage, we need to create a vote, input answer choices and define voting access criteria. The most important thing at this stage is the selection of so-called trusted representatives. These are candidates in the election (or rather their representatives) or independent observers. What are their functions from our algorithm’s viewpoint? They perform the following roles:
- Form blockchain blocks and sign them using their personal keys.
- Encrypt the blockchain contents to hide intermediate election results.
These two functions are in fact in no way dependent on each other, but we decided to present them together to make it easier for end users to understand how the product works.
Starting the vote and forming the blocks
All trusted representatives receive a mining/observer application from us, create their own personal keys with which they will subsequently sign their blocks, deploy the application on servers or desktops and connect to our blockchain. Naturally, all operations are performed automatically. Now, they can receive voter transactions, assemble them into blocks and record them in the blockchain.
Encrypting the blockchain
We want to encrypt the voting results recorded in the blockchain. We need a key to do this. However, we cannot use a single key, because:
- it defeats the purpose of having a distributed system
- the key holder is potentially vulnerable: the single key may be stolen, enabling the voting results to be accessed ahead of time, or it may be lost altogether, in which case the voting results will be lost, as well
- the key holder can access the intermediate results
Secret sharing schemes do not have the shortcomings described above. Here are the properties of such schemes that are important to us:
- Each trusted representative has only part of the key, so no one can decrypt the data alone
- To decrypt the data, we do not need all parts of the key but a subset of them, to guard against situations where one of the representatives has disappeared. We use threshold encryption (n,k), where n>k>1, and we need k parts of the key to decrypt the data. The parameters n and k are defined in the process of setting up the system.
Eventually, we chose Shamir’s Secret Sharing scheme.
The scheme is based on the following idea:
You need k points to interpolate a polynomial of degree k−1. For example, it takes two points to define a straight line, three points to define a parabola, etc. It is impossible to interpolate a polynomial if you have fewer points.
If we want to share a secret among n people in such a way that it can only be recovered by k people (k ≤ n), we “hide” the secret in the formula of a polynomial of degree k−1. That is, we generate a random polynomial of degree k−1 with our secret being the constant term of the polynomial. Values of the polynomial in points from 1 to n are sent to all trusted representatives so that each value is sent to one representative. These values can be used to verify that the secret was created correctly. The polynomial and the original secret can only be recovered using k points. The number of different points of the polynomial is not limited.
At the threshold scheme’s initialization stage, each trusted representative Pi generates his or her private key si. Let us label the system’s common key as
Trusted representative Pi generates a random polynomial of degree k-1,
after which trusted representative Pi sends to each trusted representative Pj (including himself) the polynomial’s value
Additionally, the following is published:
where fij are the constants of polynomial Pi, and the following check is performed:
to prove that Pi actually calculated sij using the polynomial fi(z). Additionally, the private key that has been calculated is checked for matching the published parts of the key, i.e.,
A check is also performed to make sure that these parts match the public key that has been calculated:
If these checks are passed, then each trusted representative confirms that the public key is correct by signing it.