As described in the Netvote White Paper, accepting a vote involves Authentication, Authorization, and a Vote Gateway. For large elections (Government or otherwise), Authentication & Authorization steps will involve integrations that will vary per organization.
This project provides a demo-ready Authentication, Authorization, and Vote Gateway built on top of Firebase. In this simple case, any voter who provides a valid key is allowed to vote. The admin is responsible for distributing a key to the correct voters.
Note: This project has not undergone any security audit, and should not be used to manage real elections at this time.
- Create ballot metadata and post to IPFS (no API)
- Create election with IPFS reference, and save off electionId for QR (API)
- Create Voter Keys (via API)
- Distribute Voter Keys in QRs (directly, no API)
- Activate Election (if not auto-activated)
- Scan QR containing election electionId
- Make selections in application
- Scan QR containing Voter Key, exchange key for JWT Token
- Submit vote with JWT Token
- Close election (via API or DApp)
- Reveal Encryption Key (via API)
- Tally Results in application
Exchange a voter key for a vote token. The key is in place of what would normally involve showing one's ID at a polling station. In this case, it is the Admin's reponsibility to distribute the key safely to voters who may vote.
Note:
- The vote token is currently good for one hour from exchange.
- Another token can be requested at any time. (The blockchain prevents duplicate voting)
Header
Authorization: Bearer VOTER-KEY-HERE
Body:
{
"electionId": "electionId"
}
- electionId: (required) the electionId of the
BasicElection
contract
Returns:
{
"token": "JWT-TOKEN"
}
Casts a vote for the election. If a vote has already been cast for this voter (baked into JWT key), an update will occur (if election allows updates)
Note:
- This will validate the vote matches the ballot schema of options defined in the metadata. (same number of options, valid choices)
Header
Authorization: Bearer JWT-TOKEN
Body:
{
"vote": "base64-of-serialized-proto",
"proof": "IPFS-ID",
"pushToken": "abc123"
}
- vote: (required) this is a BASE64-encoded serialized Vote message from Vote.proto
- proof: (optional) references a document in IPFS containing the JSON:
{ "publicKey": "...", "signature": "..."}
- pushToken: (optional) API will kindly send a push message to voter when vote has been cast
Returns:
{"txId":"OBJECT-REFERENCE","collection":"transactionCastVote"}
Note:
- The firebase collection reference can be polled for completion. (obj.status = complete)
- The signature must sign a base64 payload containing only
ballotVotes
andsignatureSeed
Create an election on the ethereum blockchain owned by the current firebase user UID. Only that user may invoke other election-specific admin APIs.
Body:
{
"autoActivate": true,
"metadataLocation": "ipfs-address",
"allowUpdates": true,
"isPublic": true,
"network": "ropsten or netvote",
"requireProof": true
}
- autoActivate: (optional) allow voting immediately
- metadataLocation: (required) electionId of ballot metadata on IPFS
- allowUpdates: (optional) allow voters to update their vote after the fact (enforced on chain)
- isPublic: (optional) generate and post the encryption key to the ballot immediately so tallying can occur during the election
- network: (optional) deploy to either ropsten (eth test net) or netvote (private proof-of-authority network)
- requireProof: (optional) if true, votes require a public key and signature as an IPFS reference in a proof parameter
Returns:
{"txId":"OBJECT-REFERENCE","collection":"transactionCreateElection"}
Note:
- The firebase collection reference can be polled for completion. (obj.status = complete)
Generate voter keys for the election and return. This will store a one-way HMAC of the key in firebase to be looked up.
NOTE:
- The UID must be authorized by the election contract.
- The contract stores web3.sha3(uid) as the reference
Body:
{
"electionId": "electionId",
"count": 1
}
- electionId: (required) electionId of election
- count: (required) number of keys to create in this request
Returns:
["key1", "key2"...]
The response is the only time these keys are visible. The admin must ensure these are delivered to voters safely and correctly.
If not already activated (via autoActivate), this will allow voting for the election.
NOTE:
- The UID must be authorized by the election contract.
- The contract stores web3.sha3(uid) as the reference
Body:
{
"electionId": "electionId"
}
- electionId: (required) electionId of election
This will do the following:
- Close the election to prevent further voting
- Post the encryption key to the election contract to allow for vote reveal.
- Delete the hashing secret for the election to preserve anonymity even in full-collusion cases.
NOTE:
- This will permanently close the election (no more votes allowed). This is irreversable.
NOTE: the UID must be authorized by the election contract.
Body:
{
"electionId": "electionId"
}
- electionId: (required) electionId of election
This will do the following:
- Start a tally of the election
- Return the firestore collection to listen on for changes.
NOTE:
- If the election is not ready to be tallied, you'll get a 409 back
Path Parameters:
- electionId: (required) electionId of election
- Fork repo
- Make desired changes
- Submit PR (Reference Issue #)
- Reviewer will review
- Reviewer Squash + Merges PR
All code is released under the GNU General Public License v3.0.