Skip to content
No description, website, or topics provided.
C Perl Makefile C++ Shell DIGITAL Command Language Other
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


The Koinonia system is an implementation of the Koinonia voting protocol. The protocol contains three independent servers (ESP, EA, and Tellers) which are recommended to be running on different machines. We use PostgreSQL (v9.6) on ESP, EA, and Tellers as the database back-end for storing election data. Clients will get the Voter application from the Authority and execute it on a Web browser. Both server-side and client-side applications are written in Node.js (v12) and use an abstract Koinonia library to get access to protocol functions such as vote share generation and proof verification. To accomodate the different deployment and optimization needs, we have thus made two implementations of the Koinonia library, one for client-side and the other for server-side. The client-side library is implemented with 500+ lines of JavaScript code based on SJCL. The server-side library is implemented through Node.js C++ Addons (1200 lines of native code) in order to optimize the performance of group exponentiations. The released software has been tested on Ubuntu 18.04.

The Readme contains instructions to deploy and test the Koinonia system involving multiple servers (e.g., one ESP, one EA, and three Tellers). Also, the Readme provides a performance benchmark script to stress test the system with one million ballots under the multi-server setting. Beyond the Koinonia system, we also release an implementation of secure communication channel establishment using experimental quantum-safe cryptographic algorithms, based on Open Quantum Safe (OQS) and Stunnel.

The source code can be found at

Installing Software

  • The instruction of installation is tested on Ubuntu 18.04+
  • Node.js v12.x+
  • PostgreSQL v9.6
1. Install Nodejs
curl -sL | sudo -E bash -
sudo apt-get install -y nodejs
2. Install PostgreSQL
  • create the file /etc/apt/sources.list.d/pgdg.list, and add a line for the repository

    deb YOUR_UBUNTU_VERSION_HERE-pgdg main

  • Import the repository signing key, and update the package lists

    wget --quiet -O - | \
        sudo apt-key add -
    sudo apt-get update
    sudo apt-get install postgresql-9.6
  • Use password as authentication method for PostgreSQL

    • Change the password
    sudo -u postgres psql -p [port number]
    ALTER USER postgres WITH PASSWORD [new password];

    port number can be find in /etc/postgresql/[pg version]/postgresql.conf By default, the port number is 5432, unless multi version pg server is installed.

    • Configure postgresql to do password-based login.
      By default postgres uses peer authentication. We need to login the postgres server and change the postgres password

      • edit /etc/postgresql/9.6/main/pg_hba.conf
      • change authentication method from peer to md5

Setup software environment

  • Install node module

    npm install
  • Get the "sjcl" as a git sub module

    git submodule init
    git submodule update
  • Compile "sjcl" with ecc

    cd external/sjcl
    ./configure --with-ecc --with-cbc

    the compiled sjcl.js has already has a symbolic link under src/common/sjcl.js

  • Compile native module

    node-gyp configure
    node-gyp build

    You should run the command under project root directory.

  • System parameter generation Generate the system parameter (curve_name and h).

    cd src/common
    nodejs paramSetup.js > parameter.js

    The parameter setup script paramSetup.js computes digest(common string) which is the $x$ coordinate in the EC (elliptic curve equation) ($y^2 = x^3 + ax + b$). The bit $b$ is to determine which $y$ coordinate we want to use (1 refers to odd $y$, and 0 refers to even $y$). $x$ plus bit $b$ is the compressed format of an EC point $h = (x, y)$. Notice that not every $x$ has a solution $y$. Therefore, the script repeat adds 1 to $x$ until finding a valid $x$.

    • command option for paramSetup.js
      • -n [curve name]
        --name=[curve name] elliptic curve name, currently only secp256k1, prime256v1, secp256r1 (alias of prime256v1), secp384r1, and secp521r1 are supported [default: prime256v1]
      • -d [digest algorithm]
        --digest=[digest algorithm] digest algorithm [default: sha256]
      • -s [common string]
        --str=[common string] a common string used for generate h [default: hello world]
      • -b [bit]
        --bit=[bit], a bit (either 0 or 1) used for generate h. [default: 1]
  • Compile common.js


    You need to re-compile the common.js if system parameter is re-generated.

  • Setup database

    psql -U postgres -p [port number]
    \i ecliptic.sql

    ecliptic.sql is located in project root directory. Please run command psql under project root directory.

Start the Koinonia servers

  • Server Key generation (applicable to Auth, ESP and Tellers)

    • key file generation, here gives elliptic curve example (other key types like rsa also support)
      openssl ecparam -genkey -name [curve name] -out priv.pem

    • for [curve name] secp256k1 is k256, prime256v1 is p256,

    • To get full curve list, use command:
      openssl ecparam -list_curves

    • Encrypt private key file (you can other encryption algorithm in openssl) w/ password. The password is needed to decrypt the key when starting the server. openssl pkey -in [private key file] -aes256 -out [output filename]

    • Example for generating Auth server key:

    openssl ecparam -genkey -name prime256v1 -out src/auth/priv.pem
    openssl pkey -in src/auth/priv.pem -aes256 -out src/auth/priv.pem.enc
  • Start Auth server

    nodejs auth-server.js [key file password] [key file] [host port]
    cd src/auth

    Example for generating Auth server key and starting Auth using port 60000

    cd src/auth
    openssl ecparam -genkey -name prime256v1 -out priv.pem
    openssl pkey -in priv.pem -aes256 -out priv.pem.enc
    nodejs auth-server.js 123456 priv.pem.enc 60000
  • Start Esp server

    cd src/esp
    nodejs esp-server.js [port] [key file password] [key file]

    Example for generating Auth server key and starting Esp using port 60001

    cd src/esp
    openssl ecparam -genkey -name prime256v1 -out priv.pem
    openssl pkey -in priv.pem -aes256 -out priv.pem.enc
    nodejs esp-server.js 60001 123456 priv.pem.enc
  • start teller server

    • Generate teller server password config file
      The password config file is used to instruct the server how to generate the aes encryption key in startup
       cd src/teller
       nodejs passwordSetup > [output filename]
    • Command options for passwordSetup:
      • -i [iterations]
        --iterations=[iterations] iterations is an integer >= 1000 [default: 100000]
      • -k [key length]
        --keyLen=[key length] key length is 128, 192, or 256 [default: 256]
      • -d [digest algorithm]
        --digest=[digest algorithm] digest algorithm [default: sha256]
      • -s [salt string]
        --salt=[salt string] an random string [default: random keylen number of bits encoded in base64]
    • Start a single teller server
    cd src/teller
    nodejs teller-server.js [port] [db schema] [key file password] [password config file] [key file]

    [db schema] refers to the table to use; currently we have teller, teller2, teller3

    • Example for generating Teller server key and starting 3 Teller using port 50001, 50002, and 50003 on a single server
    cd src/teller
    openssl ecparam -genkey -name prime256v1 -out priv.pem
    openssl pkey -in priv.pem -aes256 -out priv.pem.enc
    nodejs passwordSetup > priv.conf
    nodejs teller-server.js 50001 teller 123456 priv.conf priv.pem.enc
    nodejs teller-server.js 50002 teller2 123456 priv.conf priv.pem.enc
    nodejs teller-server.js 50003 teller3 123456 priv.conf priv.pem.enc

Simulate an election

  • Run election Visit the website http://localhost:60001 and click the button Create Election to run a new election.

    Each step can be found in directory doc_simulate_election.

    1. create election
    2. freeze election
    3. teller registration (teller url [protocol]//[domain]:[port]) protocol: http: | https: domain: ip address or domain port: optional for http/https
    4. freeze tellers
    5. register voters [each line is an email address]
    6. freeze voters
    7. open election
    8. vote a. Type email address to give vote link. b. If you cannot get the link, add 'console.log(link);' after line 83 in file src/auth/sendVoteLink.js. This is because email server may block certain IP address. The edu IP address which started with 128...* should work. c. Use the vote link to vote
    9. close election on election admin page
    10. Download ballot file from the election website. The summation file can be downloaded after Tallying on ESP.
  • Tallying on each teller

    • Tellering script
      The script will add up will look up the ballot file add up all shares submitted to the server. The result will submitted to the ESP afterwards.
    cd src/teller
    nodejs electionTallying.js [election id] [ballot file] [db schema] [key file password] [password config file] [key file] [teller index]

    Note: The password should be the same password used for key file. Ballot file can be download after election closed via button 'Dump Votes'.

    • Example of tallying on 3 teller servers running on one machine. election id 3, ballot file /tmp/election_3_ballots.csv download from election website.
    cd src/teller
    nodejs electionTallying.js 3 /tmp/election_3_ballots.csv teller 123456 priv.conf priv.pem.enc 0
    nodejs electionTallying.js 3 /tmp/election_3_ballots.csv teller2 123456 priv.conf priv.pem.enc 1
    nodejs electionTallying.js 3 /tmp/election_3_ballots.csv teller3 123456 priv.conf priv.pem.enc 2
  • Tallying on ESP

    • Tallying script
      The script will verify the result received from each teller server and publish the final summation.
    cd src/esp
    nodejs finallyTallying.js [election id] [ballot file]
    • Example of publish the result of election 3.
    cd src/esp
    nodejs finallyTallying.js 3 /tmp/election_3_ballots.csv
  • Third party voting verification

    cd src/common
    nodejs offlineVerify.js [ballot file] [summation file] [report interval (ms) optional]
    • Command options
      • [ballot file] is a file containing all accepted bullets for one election
      • [summation file] is a file containing the election information and summation result, which can be download after final tallying via button 'Dump Summation'
      • [report interval (ms) optional] is a time interval to report how many bullets are proofed, default is 3000ms
    • Example of verifying election 3 offline
    cd src/common
    nodejs offlineVerify.js /tmp/election_3_ballots.csv /tmp/election_3_summation.json

Simulate large population voting by using autoscript

The source code is located at src/autoscript.

To use autoscript, you should rewrite the src/autoscript/dbConfig.js according to the dbConfig.tmpl.js

  • generateVoters.js

    Automatically generate a list of voters for the election

    nodejs generateVoters.js [start voter id] [length]

    Example of generating 1000 voters.

    nodejs generateVoters.js 0 1000 > /tmp/voters.csv
  • loadVoters.js

    automatically loading a list of emails into the database, which are the identities of voters. This step should run right after step 5 (register voters).

    nodejs loadVoters.js [election id] [email list file] [Auth startup password] [Auth  priv key file]

    Example of loading 1000 voters (voter id from 0 to 999) for election 3

    cd src/auth
    nodejs loadVoters.js 3 /tmp/voters.csv 123456 ../auth/priv.pem.enc

    You should

  • dumpVoters.js

    dump a list of voterf from the auth servers which will be used for autovote.js

    nodejs dumpVoters.js [election id] [output filename]

    Example of dumping voters for election 3

    nodejs dumpVoters.js 3 /tmp/voters_dump.csv
  • autovote.js

    run the automatic voting process. This step should run right after step 7 (open election). nodejs autovote.js [election id] [voter ID file] [hostname of authority] [port]

    nodejs autovote.js [election id] [ESP server url] [dumped voter file]

    Example of auto voting for election 3

    nodejs autovote.js 3 http://localhost:60001 /tmp/voters_dump.csv


  • first, build stunnel

    cd stunnel-oqs
  • then run stunnel with the server side configuration file (stunnel-localhost-servers-demo.conf)

    • if one runs the server apps on different machines, each should get a separate configuration file
    cd stunnel-oqs
    ./stunnel-5.40-oqs-build/bin/stunnel ./stunnel-localhost-servers-demo.conf
  • expected default ports of server apps:

    • Auth (app port-60000)
    • Teller-1 (app port-50001)
    • Teller-2 (app port-50002)
    • Teller-3 (app port-50003)
    • ESP (app port-60001)
  • default stunnel port:

    • Auth (stunnel port-40000)
    • Teller-1 (stunnel port-40001)
    • Teller-2 (stunnel port-40002)
    • Teller-3 (stunnel port-40003)
    • ESP (stunnel port-40004)
  • other pre-requisite for client :

  • submit vote through stunnel (client) The script will read an configuration file and launch a firefox which will show a voting page.

    ./stunnel-oqs/ http(s)://[host]:[port]/electionapi/[election id] [voting link]

    Example of run stunnel client. Remember to add quote to the url in order to let the shell to treat it as an single argument.

    ./stunnel-oqs/ "http://localhost:60001/electionapi/5" "http://localhost:60001/election/5/vote?"

For more details regarding stunnel, please read the readme file under directory stunnel-oqs.

You can’t perform that action at this time.