Skip to content
Commits on Source (4)
*~
_build
_run
venv
__pycache__
geckodriver.log
env.sh
stages:
- build_and_run_automated_test_scenarios_with_preinstalled_image
- build_and_test_with_preinstalled_image
- build_and_test_with_debian_image
build_and_test_with_preinstalled_image:
stage: build_and_test_with_preinstalled_image
# Image swergas/beleniosbase:efa5df3049f736dd34eb8289da730dd709eb99939f6511fa93ae0080a61ce4fb is based on ocaml/opam2:debian-9 with all pre-installed apt packages and opam packages that are required by Belenios
image: swergas/beleniosbase:efa5df3049f736dd34eb8289da730dd709eb99939f6511fa93ae0080a61ce4fb
# Image glondu/beleniosbase:YYYYMMDD-N is built by Dockerfile_base_environment
image: glondu/beleniosbase:20181206-2
script:
# Install required packages
# - sudo apt-get update -qq && sudo apt-get install -y -qq build-essential libgmp-dev libpcre3-dev pkg-config m4 libssl-dev libsqlite3-dev wget ca-certificates unzip aspcud libncurses-dev uuid-runtime zlib1g-dev
# Install the same Opam packages that opam-bootstrap.sh installs
# - eval `grep "opam install" ./opam-bootstrap.sh`
# Initialize environment
- source ~/env.sh
# Compile belenios
- BELENIOS_DEBUG=1 make all
# Create a bundled version of belenios (this produces a belenios.tar.gz file, which is needed by the web server)
......@@ -45,3 +44,27 @@ build_and_test_with_debian_image:
- if [ "$(echo \"$first_access_index_page_output\" | grep '>Belenios</a>' | wc -l)" != "1" ]; then echo "[First page access] First page access does not show a single '>Belenios</a>' text, but it should" && exit 1; else echo "[First page access] First page access shows a single '>Belenios</a>' text, as expected"; fi
# Run a test of an election
# - BELENIOS_DEBUG=1 make check
build_and_run_automated_test_scenarios_with_preinstalled_image:
stage: build_and_run_automated_test_scenarios_with_preinstalled_image
# Image glondu/beleniosbase-tests:YYYYMMDD-N is built by Dockerfile_test_scenario_environment
image: glondu/beleniosbase-tests:20181206-2
script:
# Initialize environment
- source ~/env.sh
# Compile belenios
- BELENIOS_DEBUG=1 make all
# Create a bundled version of belenios (this produces a belenios.tar.gz file, which is needed by the web server)
- make archive
# We don't need to start belenios web server, as it will be started by the automated test
# - ./demo/run-server.sh &
# Create a Python 3 virtual environment, where pip packages will be installed
- python3 -m venv venv
# Step into this new virtual environment
- source venv/bin/activate
# Install pip packages
- pip install -r requirements.txt
# Run the automated test scenario 2
- python3 ./tests/test_scenario_2.py
# Run the automated test scenario 1
- python3 ./tests/test_scenario_1.py
wrap-build-commands: []
wrap-install-commands: []
wrap-remove-commands: []
required-tools: []
1.8 (2018-02-04)
================
* Add the possibility to override sendmail via an environment variable
* Use SOURCE_DATE_EPOCH if available
* Use opam 2.0.0 in bootstrap script
* Web server:
+ Add some automated tests
+ Add the possibility to create administrator accounts
+ Add booth preview
+ Add automatic open / close dates
+ Unhide support for threshold decryption
+ Fixed a bug that caused some elections to not appear in the
administrator's listing when the election pool is big
+ Force the server to be a trustee in basic mode
+ Record in trustee public keys whether the server has the private key
1.7.1 (2018-12-05)
==================
......
FROM debian:9
RUN apt-get update -qq && apt-get upgrade -qq && apt-get install -qq bubblewrap build-essential libgmp-dev libpcre3-dev pkg-config m4 libssl-dev libsqlite3-dev wget ca-certificates zip unzip aspcud libncurses-dev uuid-runtime zlib1g-dev libgd-securityimage-perl cracklib-runtime git
RUN useradd --create-home belenios
COPY .opamrc-nosandbox /home/belenios/.opamrc
COPY opam-bootstrap.sh /home/belenios
USER belenios
WORKDIR /home/belenios
RUN ./opam-bootstrap.sh
# Docker image used as FROM has been generated from ./Dockerfile_base_environment
FROM glondu/beleniosbase:20181206-2
USER root
# Install firefox-esr (The firefox package is not present in apt repositories of this linux image, so we use firefox-esr)
RUN apt-get install -y -qq firefox-esr
# Install geckodriver (It is needed by selenium to run firefox)
ENV GECKODRIVER_VERSION 0.18.0
RUN wget --no-verbose -O /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v$GECKODRIVER_VERSION/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz && rm -rf /opt/geckodriver && tar -C /opt -zxf /tmp/geckodriver.tar.gz && rm /tmp/geckodriver.tar.gz && mv /opt/geckodriver /opt/geckodriver-$GECKODRIVER_VERSION && chmod 755 /opt/geckodriver-$GECKODRIVER_VERSION && ln -fs /opt/geckodriver-$GECKODRIVER_VERSION /usr/bin/geckodriver
# Install packages required to run the test scenario
RUN apt-get install -y -qq python3 python3-venv
USER belenios
......@@ -13,6 +13,7 @@ OCaml projects.
The non-OCaml prerequisites are:
* a POSIX system with a C compiler
* on Linux, [Bubblewrap](https://github.com/projectatomic/bubblewrap)
* [GMP](http://gmplib.org/)
* [PCRE](http://www.pcre.org/)
* [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/)
......@@ -25,12 +26,14 @@ The non-OCaml prerequisites are:
* [aspcud](http://www.cs.uni-potsdam.de/wv/aspcud/) (optional)
* [ncurses](http://invisible-island.net/ncurses/)
* [uuidgen](https://www.kernel.org/pub/linux/utils/util-linux/)
* [GD-SecurityImage](https://metacpan.org/release/GD-SecurityImage)
* [cracklib](http://sourceforge.net/projects/cracklib)
These libraries and tools are pretty common, and might be directly part
of your operating system. On [Debian](http://www.debian.org/) and its
derivatives, they can be installed with the following command:
sudo apt install build-essential libgmp-dev libpcre3-dev pkg-config m4 libssl-dev libsqlite3-dev wget ca-certificates zip unzip aspcud libncurses-dev uuid-runtime zlib1g-dev
sudo apt install bubblewrap build-essential libgmp-dev libpcre3-dev pkg-config m4 libssl-dev libsqlite3-dev wget ca-certificates zip unzip aspcud libncurses-dev uuid-runtime zlib1g-dev libgd-securityimage-perl cracklib-runtime
If you are unfamiliar with OCaml or OPAM, we provide an
`opam-bootstrap.sh` shell script that creates a whole, hopefully
......@@ -41,7 +44,7 @@ variable, or it will take `~/.belenios` by default. Just run:
./opam-bootstrap.sh
On a modern desktop system, this needs approximately 11 minutes and 2
On a modern desktop system, this needs approximately 20 minutes and 2.6
gigabytes of disk space.
If everything goes successfully, follow the given instructions to
......
......@@ -3,7 +3,8 @@
<src/platform/native/*>: package(zarith), package(cryptokit)
<src/web/*.{ml,mli,byte,native,odoc}>: thread, package(eliom.server), package(lwt.ppx), package(calendar), package(csv)
<src/tool/tool_cmdline.*>: package(zarith), package(cryptokit), package(cmdliner), use_platform-native
<src/tool/tool_js*> or <src/platform/js/*> or <src/booth/*>: package(js_of_ocaml-lwt), package(js_of_ocaml-ppx), package(lwt.ppx), use_platform-js
<src/tool/tool_js*> or <src/platform/js/*>: package(js_of_ocaml-lwt), package(js_of_ocaml-ppx), package(lwt.ppx), use_platform-js
<**/*serializable_j.ml>: warn(-32)
true: warn(A-4-6-29-44-45-48), safe_string
<venv>: not_hygienic
belenios (1.8+dfsg-1) unstable; urgency=medium
* New upstream release
-- Stéphane Glondu <glondu@debian.org> Mon, 04 Feb 2019 11:43:56 +0100
belenios (1.7.1+dfsg-1) unstable; urgency=medium
* New upstream release
......
......@@ -37,6 +37,9 @@
<site path="static" charset="utf-8">
<static dir="_SRCDIR_/_build/src/static" />
</site>
<site path="monitor">
<eliom findlib-package="eliom.server.monitor.start"/>
</site>
<eliom module="_build/src/web/server.cma">
<maxmailsatonce value="1000"/>
<uuid length="14"/>
......@@ -45,6 +48,7 @@
<server mail="noreply@example.org"/>
<auth name="demo"><dummy/></auth>
<auth name="local"><password db="demo/password_db.csv"/></auth>
<auth name="public"><password db="_RUNDIR_/password_db.csv" allowsignups="true"/></auth>
<!-- <auth name="google"><oidc server="https://accounts.google.com" client_id="client-id" client_secret="client-secret"/></auth> -->
<source file="../belenios.tar.gz"/>
<default-group file="demo/groups/default.json"/>
......
......@@ -17,6 +17,8 @@ mkdir -p \
$BELENIOS_RUNDIR/spool \
$BELENIOS_TMPDIR/run
touch $BELENIOS_RUNDIR/password_db.csv
sed \
-e "s@_OCAML_STDLIBDIR_@$OCAML_STDLIBDIR@g" \
-e "s@_TMPDIR_@$BELENIOS_TMPDIR@g" \
......
# Documentation related to automated tests of Belenios
Automated tests are stored in the `tests` directory.
Technologies used to run these tests are:
- `python3`: Python 3. We us it in a virtual environment
- `pip`: Python's package manager. We use it to install Python packages such as `selenium` (`pip` installs packages mentioned in `requirements.txt`)
- `selenium`: Selenium's Python API documentation: https://selenium-python.readthedocs.io/)
- `firefox`: The browser we use to run tests with Selenium. We can use standard Firefox, or `firefox-esr`, depending what is available on the system and which Firefox version is compatible with Selenium at the moment
- `geckodriver`: A Firefox driver for Selenium
- `unittest`: Python's standard test framework
These automated tests start the Belenios demo server (`demo/run-server.sh`), with the `BELENIOS_SENDMAIL` environment variable defined as the path to a fake `sendmail` executable (similar to a mock, provided in `tests/tools/sendmail_fake.sh`). This way, Belenios server does not return an error when trying to send emails in the test environment (that has no `sendmail` installed nor configured), and the fake `sendmail` executable makes it possible to verify what emails have been sent and read their content, simply by reading the log file where it redirects all its input (we use `/tmp/sendmail_fake` as location for this log file).
Note: For example, during election creation procedure, a step sends emails to voters. If at this moment, a `sendmail` binary is not properly installed and configured (or replaced by a mock), the web page displays the following error message: `Netchannels.Command_failure(WEXITED 126)`
When these automated tests start running, and when they end, they clean up Belenios database: Belenios database consists in directories and files under the `_run/spool` directory, for each election. So these are deleted during test setup. Belenios demo server stores initial admin users logins and passwords in `demo/password_db.csv`. This file is not deleted during test setup, and its contents are used to log in the adminstrator during the test and have this administrator create an election.
Automated tests can be executed manually, or via Continuous Integration. Next sub-sections explain how to execute them in each of these 2 contexts.
## Executing automated test suites manually on your local machine
You can execute a test suite by running its python script from your Python virtual environment, given you have already installed its `pip` requirements, `firefox` and `geckodriver`. Automated tests need that Belenios server has already been compiled. So if you have not done any of these, this is the sequence of commands that you can execute:
```
export GECKODRIVER_VERSION=0.18.0
wget --no-verbose -O /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v$GECKODRIVER_VERSION/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz && rm -rf /opt/geckodriver && sudo tar -C /opt -zxf /tmp/geckodriver.tar.gz && rm /tmp/geckodriver.tar.gz && sudo mv /opt/geckodriver /opt/geckodriver-$GECKODRIVER_VERSION && sudo chmod 755 /opt/geckodriver-$GECKODRIVER_VERSION && sudo ln -fs /opt/geckodriver-$GECKODRIVER_VERSION /usr/bin/geckodriver
sudo apt-get install -y -qq python3 python3-venv firefox
BELENIOS_DEBUG=1 make all
make archive
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python ./tests/test_scenario_1.py
```
Note: Depending on the version of `firefox` that you use, you may need to adjust the version of `geckodriver` to download and install. Please refer to this compatibility table: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/Support.html
Note: The `make all` command exits in error if `ocamlbuild` finds compiled files (including `.so` shared libraries) other than the ones it expects. So, make sure that you run this command before creation of the Python virtual environment and installation of `pip` requirements. If you want to re-compile Belenios after this, you can simply delete the `venv` folder.
Note: We cannot run the Belenios server from a folder that is not the git repository root, otherwise it exits immediately in an error: `This script should be run from the root of the (built) source tree!`.
## Executing automated tests using Continuous Integration
For this, we run a Docker image (built from `Dockerfile_test_scenario_environment`) that preinstalls compatible versions of `firefox-esr`, `geckodriver`, `python`, and python virtual environment.
File `.gitlab-ci.yml` defines a task `build_and_run_automated_test_scenario_1_with_preinstalled_image` that uses this docker image, compiles belenios, creates a python virtual environment, step into it, install pip required packages, and then executes the automated test suite.
Note: You can execute this Continuous Integration task as if you were running GitlabCI, by executing the following command:
```
gitlab-runner exec docker build_and_run_automated_test_scenario_1_with_preinstalled_image
```
Note: The Docker image has been built and pushed to Docker Hub using the following commands:
```
docker build -t glondu/beleniosbase:20181206-1 -f Dockerfile_base_environment .
docker build -t glondu/beleniosbase-tests:20181206-1 -f Dockerfile_test_scenario_environment .
sudo docker push glondu/beleniosbase-tests:20181206-1
```
We use `YYYYMMDD-N` for docker-tagging, where `YYYYMMDD` is the build date, and `N` is a sequence number.
## Customizing configuration variables of Test Scenario 1
Test `test_scenario_1.py` executes using some default configuration that can be customized, by setting some environment variables when executing the script.
The list of configuration variables is:
- `RANDOM_SEED`: An integer used as seed for the random number generator of Python. By default, a random seed is used. Seed used is displayed at every run of the test, so you can re-run the test using the same random seed by setting this configuration variable to the value displayed.
- `USE_HEADLESS_BROWSER`: Set this to non-zero (True) if you run this test in Continuous Integration (it has no graphical display). Set this to 0 (False) if you want to see the browser open its graphical user interface and visually track progress ot the test. By default, the falue is True.
- `WAIT_TIME_BETWEEN_EACH_STEP`: In seconds (float). Time we wait between each action that we tell Selenium driver to do in the browser. Set to 0 if you don't need to have the time to visually follow progress of actions in the browser
- `EXPLICIT_WAIT_TIMEOUT`: In seconds. Maximum duration Selenium driver will wait for appearance of a specific DOM element expected in the page (for example when transitioning from a page to another). This referes to Selenium's "Explicit Wait" concept
- `SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH`
- `NUMBER_OF_INVITED_VOTERS`: This is N in description of Scenario 1. N is between 6 (quick test) and 1000 (load testing)
- `NUMBER_OF_VOTING_VOTERS`: This is K in description of Scenario 1. K is between 6 (quick test) and 1000 (load testing). K <= N. (Some invited voters don't vote, this is abstention, and its value is N - K)
- `NUMBER_OF_REVOTING_VOTERS`: This is L in description of Scenario 1. L <= K
- `NUMBER_OF_REGENERATED_PASSWORD_VOTERS`: This is M in description of Scenario 1. M <= K
- `SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH`: By default, this is "/tmp/sendmail_fake"
- `ADMINISTRATOR_USERNAME`: By default, this value comes from file `demo/password_db.csv`, first row, first column
- `ADMINISTRATOR_PASSWORD`: By default, this value comes from file `demo/password_db.csv`, first row, 4th column
Here is an example of how you can set configuration variables and execute the test in your terminal:
```
RANDOM_SEED=222 WAIT_TIME_BETWEEN_EACH_STEP=1.2 USE_HEADLESS_BROWSER=0 NUMBER_OF_INVITED_VOTERS=4 python3 ./tests/test_scenario_1.py
```
Scenario 1: Simple vote, in "fully automated" mode
=================================
## Introduction and parameters
Protagonists to emulate: election administrator, `K` electors, an auditor.
Administrator uses only her browser.
Electors use their browser and read emails sent by the server.
`L` electors re-vote (with `L <= K`)
`M` electors ask administrator to re-generate their password, and vote with their re-generated password (with `M <= K`).
The auditor makes web requests, has a persistent state, and runs the commandline version of the Belenios tool.
Auditor makes web requests, has a persistent state, and runs the commandline version of the Belenios tool.
Authentication of administrator and electors are done using a login / password combination.
Examples of parameters sizes: `N` and `K` would be between 6 (quick test) and 1000 (load test)
## Note about verification
Verifications all along the process is done using command line tools `belenios-tool verify` and `belenios-tool verify-diff`:
- `belenios-tool verify` does a static verification (it verifies that vote data at current time is coherent)
- `belenios-tool verify-diff` does a dynamic verification (it verifies that current state of vote data is a possible/legitimate evolution of a vote data snapshot that has been saved during a previous step of the process)
## Detailed steps of the Test Scenario 1 process
- Starting setup of the election (action of the administrator)
- Creation of the draft election
- Alice has been given administrator rights on an online voting app called Belenios. She goes to check out its homepage and logs in.
- She clicks on the "Prepare a new election" link
- (She keeps default values on the form: Credential management is automatic (not manual), and Authentication method is Password, not CAS)
- She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
- She changes values of fields name and description of the election
- She clicks on the "Save changes button" (the one that is next to the election description field)
- Edition of election's questions
- She clicks on the "Edit questions" link, to write her own questions
- She arrives on the Questions page. She checks that the page title is correct
- She removes answer 3
- She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
- Setting election's voters
- She clicks on the "Edit voters" link, to then type the list of voters
- She types `N` e-mail addresses (the list of invited voters)
- She clicks on the "Add" button to submit changes
- She clicks on "Return to draft page" link
- She clicks on button "Generate on server"
- (Server sends emails to voters.) She checks that server does not show any error that would happen when trying to send these emails (this can happen if sendmail is not configured)
- We do a sanity check that server has really tried to send emails. (For this, we look for email addresses in the temporary file where our fake sendmail executable redirects its inputs to.)
- She clicks on the "Proceed" link
- In "Authentication" section, she clicks on the "Generate and mail missing passwords" button
- She checks that the page contains expected confirmation text, instead of an error
- She clicks on the "Proceed" link
- Finalize creation of election
- In "Validate creation" section, she clicks on the "Create election" link
- (She arrives on the "Checklist" page, that lists all main parameters of the election for review, and that flags incoherent or misconfigured parameters. For example, in this test scenario, it displays 2 warnings: "Warning: No trustees were set. This means that the server will manage the election key by itself.", and "Warning: No contact was set!")
- In the "Validate creation" section, she clicks on the "Create election" button
- (She arrives back on the "My test election for Scenario 1 — Administration" page. Its contents have changed. There is now a text saying "The election is open. Voters can vote.", and there are now buttons "Close election", "Archive election", "Delete election")
- She remembers the URL of the voting page, that is where the "Election home" link points to
- She checks that a "Close election" button is present (but she does not click on it)
- Log out and close the browser window
- Regenerating electors' lost passwords (for M electors) (action of the administrator)
- Alice has been contacted by some voters who say they lost their password. She wants to re-generate their passwords and have the platform send them by email. For this, she logs in as administrator.
- She remembers the list of voters who contacted her and said they lost their password.
- She selects the election that she wants to edit
- She arrives to the election administration page. For each voter of the M selected voters:
- She clicks on the "Regenerate and mail a password" link
- She types the e-mail address of the voter in the "Username" field
- She clicks on the "Submit" button
- She checks that the page shows a confirmation message similar to "A new password has been mailed to name@email.com"
- She clicks on the "Proceed" link (She arrives back to the election administration page)
- We do a sanity check that server has really tried to send these emails, and to these users only.
- She logs out and closes the browser window
- Verify election consistency (using command line tool `belenios_tool verify`)
- All voting electors cast their vote (`K` electors vote). We check vote data consistency for every batch of `X` votes (using `belenios_tool verify-diff` and a snapshot of election data copied in previous batch). For each batch of `X` voters:
- Create election data snapshot
- Current batch of electors vote. For each voter of this batch:
- Bob checks that he has received 2 emails containing an invitation to vote and all necessary credentials (election page URL, username, password). He goes to the election page URL.
- He clicks on the "Start" button
- A loading screen appears, then another screen appears. He clicks on the "Here" button
- A modal opens (it is an HTML modal created using Window.prompt()), with an input field. He types his credential.
- He fills his votes to each answer of the question (for each displayed checkbox, he decides to mark it or leave it empty)
- He clicks on the "Next" button
- He remembers the smart ballot tracker that is displayed
- He clicks on the "Continue" button
- He types his voter username and password, and submits the form
- He checks that the smart ballot tracker value that appears on screen is the same as the one he noted
- He clicks on the "I cast my vote" button
- He clicks on the "ballot box" link
- He checks that his smart ballot tracker appears in the list
- He closes the window (there is no log-out link, because user is not logged in: credentials are not remembered)
- He checks his mailbox to find a new email with confirmation of his vote, and verifies the value of the smart ballot tracker written in this email is the same as the one he noted.
- Verify election consistency (using `belenios_tool verify-diff`)
- Delete election data snapshot
- Verify election consistency (using command line tool `belenios_tool verify`)
- Create election data snapshot
- All electors who want to change their vote re-vote (`L` electors re-vote)
- We re-apply the same procedure as listed in previous step, except we use the set of `L` re-voters instead of the set of `K` voters
- Verify election consistency (using `belenios_tool verify-diff` and the snapshot created right before re-votes)
- Delete election data snapshot
- Verify election consistency (using command line tool `belenios_tool verify`)
- Administrator does tallying of the election
- Alice goes to the election page
- She clicks on the "Administer this election" link
- She logs in as administrator
- She clicks on the "Close election" button
- She clicks on the "Proceed to vote counting" button
- She checks consistency of the election result
- She checks that the number of accepted ballots is the same as the number of voters who voted
- For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance
- She checks that each ballot content corresponds to content that of this vote that has been randomly generated in advance
- Verify election consistency (using command line tool `belenios_tool verify`)
Scenario 2: Vote with vote codes in manual mode and manual trustees
=================================
## Introduction and parameters
Protagonists to emulate: election administrator, credential authority, 2 trustees, `K` electors, an auditor.
Administrator and trustees uses only thier browser. Credential authority uses her browser and sends emails.
Electors use their browser and read emails sent by the server and by the credential authority.
`L` electors re-vote (with `L <= K`)
`M` electors ask administrator to re-generate their password, and vote with their re-generated password (with `M <= K`).
The auditor makes web requests, has a persistent state, and runs the commandline version of the Belenios tool.
Auditor makes web requests, has a persistent state, and runs the commandline version of the Belenios tool.
Authentication of administrator and electors are done using a login / password combination.
Examples of parameters sizes: `N` and `K` would be between 6 (quick test) and 1000 (load test)
## Note about verification
Verifications all along the process is done using command line tools `belenios-tool verify` and `belenios-tool verify-diff`:
- `belenios-tool verify` does a static verification (it verifies that vote data at current time is coherent)
- `belenios-tool verify-diff` does a dynamic verification (it verifies that current state of vote data is a possible/legitimate evolution of a vote data snapshot that has been saved during a previous step of the process)
## Detailed steps of the Test Scenario 1 process
- Starting setup of the election (action of the administrator)
- Creation of the draft election
- Alice has been given administrator rights on an online voting app called Belenios. She goes to check out its homepage and logs in.
- She clicks on the "Prepare a new election" link
- She picks the Credential management method: manual
- (She keeps default value for Authentication method: it is Password, not CAS)
- She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
- She changes values of fields name and description of the election
- She clicks on the "Save changes button" (the one that is next to the election description field)
- She remembers the URL of the draft election administration page
- Edition of election's questions
- She clicks on the "Edit questions" link, to write her own questions
- She arrives on the Questions page. She checks that the page title is correct
- She removes answer 3
- She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
- Setting election's voters
- She clicks on the "Edit voters" link, to then type the list of voters
- She types `N` e-mail addresses (the list of invited voters)
- She clicks on the "Add" button to submit changes
- She clicks on "Return to draft page" link
- In "Authentication" section, she clicks on the "Generate and mail missing passwords" button
- She checks that the page contains expected confirmation text, instead of an error
- She clicks on the "Proceed" link
- In "Credentials" section, she clicks on "Credential management" link
- She remembers the link displayed
- She sends the remembered link to the credential authority by email
- She logs out and closes the browser
- Credential authority sends credentials to electors
- Cecily, the Credential Authority, receives the email sent by Alice, and opens the link in it
- She remembers what the link to the election will be, so that she will be able to send it to voters by email with their private credential
- She clicks on the "Generate" button
- She clicks on the "private credentials" and "public credentials" links and downloads these files. (Files are by default downloaded using filenames `creds.txt` and `public_creds.txt` respectively)
- She clicks on the "Submit public credentials" button
- She checks that redirected page shows correct confirmation sentence
- She closes the window
- She reads the private credentials file (`creds.txt`) and sends credential emails to voters
- Continuing setup of the election: Administrator invites trustees
- Administrator logs in and goes to the election draft page
- In the trustees section, she clicks on the "here" link
- She adds two trustees (their email address), and remembers the link she will send to each trustee
- She sends to each trustee an email containing their own link
- She logs out and closes the window
- Trustees generate election private keys. Each trustee (Tom and Taylor) will do the following process:
- Trustee opens link that has been sent to him by election administrator
- He checks that the page content shows the same election URL as the one the administrator saw
- He clicks on the "Generate a new keypair" button
- He clicks on the "private key" and "public key" links, to download the private key and the public key (files are respectively saved by default as `private_key.json` and `public_key.json`)
- He clicks on the "Submit public key" button
- He checks that the next page shows the expected confirmation sentence
- He closes the window
- Administrator completes setup of the election
- Alice, as an administrator of an election, wants to finalize her draft election creation, to start the vote. She opens a browser and logs in as administrator
- She goes to the draft election administration page
- In "Validate creation" section, she clicks on the "Create election" link
- (She arrives on the "Checklist" page, that lists all main parameters of the election for review, and that flags incoherent or misconfigured parameters. For example, in this test scenario, it displays 2 warnings: "Warning: No trustees were set. This means that the server will manage the election key by itself.", and "Warning: No contact was set!")
- In the "Validate creation" section, she clicks on the "Create election" button
- (She arrives back on the "My test election for Scenario 1 — Administration" page. Its contents have changed. There is now a text saying "The election is open. Voters can vote.", and there are now buttons "Close election", "Archive election", "Delete election")
- She remembers the URL of the voting page, that is where the "Election home" link points to
- She checks that a "Close election" button is present (but she does not click on it)
- She logs out and closes the window
- Verify election consistency (using command line tool `belenios_tool verify`)
- All voting electors cast their vote (`K` electors vote). We check vote data consistency for every batch of `X` votes (using `belenios_tool verify-diff` and a snapshot of election data copied in previous batch). For each batch of `X` voters:
- Create election data snapshot
- Current batch of electors vote. For each voter of this batch:
- Bob checks that he has received 2 emails containing an invitation to vote and all necessary credentials (election page URL, username, password). He goes to the election page URL.
- He clicks on the "Start" button
- A loading screen appears, then another screen appears. He clicks on the "Here" button
- A modal opens (it is an HTML modal created using Window.prompt()), with an input field. He types his credential.
- He fills his votes to each answer of the question (for each displayed checkbox, he decides to mark it or leave it empty)
- He clicks on the "Next" button
- He remembers the smart ballot tracker that is displayed
- He clicks on the "Continue" button
- He types his voter username and password, and submits the form
- He checks that the smart ballot tracker value that appears on screen is the same as the one he noted
- He clicks on the "I cast my vote" button
- He clicks on the "ballot box" link
- He checks that his smart ballot tracker appears in the list
- He closes the window (there is no log-out link, because user is not logged in: credentials are not remembered)
- He checks his mailbox to find a new email with confirmation of his vote, and verifies the value of the smart ballot tracker written in this email is the same as the one he noted.
- Verify election consistency (using `belenios_tool verify-diff`)
- Delete election data snapshot
- Verify election consistency (using command line tool `belenios_tool verify`)
- Create election data snapshot
- All electors who want to change their vote re-vote (`L` electors re-vote)
- We re-apply the same procedure as listed in previous step, except we use the set of `L` re-voters instead of the set of `K` voters
- Verify election consistency (using `belenios_tool verify-diff` and the snapshot created right before re-votes)
- Delete election data snapshot
- Verify election consistency (using command line tool `belenios_tool verify`)
- Administrator starts tallying of the election
- Alice goes to the election page
- She clicks on the "Administer this election" link
- She logs in as administrator
- She clicks on the "Close election" button
- She clicks on the "Proceed to vote counting" button
- She remembers the encrypted tally hash
- She remembers the link to send to each trustee, so they can tally the election
- She sends to each trustee an email containing their own link
- She logs out and closes the window
- Trustees do tallying (partial decryption). Each trustee (Tom and Taylor) will do the following process:
- He opens the link that Alice (the election administrator) has sent to him
- We verify that the encrypted election hash is the same as the one that has been displayed to election administrator
- He verifies that the "private key" input field is empty (at the beginning)
- He clicks on the "Browse..." button and selects his private key file (initially downloaded as `private_key.json` by default)
- He waits until the "private key" input field (that has id "#private_key") becomes not empty anymore. This is because once the user has selected the file to upload, the Javascript code in the page detects that a file has been selected, reads it, and fills "private key" input field with file's contents. The computation triggered by click on the "Compute decryption factors" button will use the value of this field, not directly the uploaded file contents.
- He clicks on the "Compute decryption factors" button
- He checks that the text field below (used as visual feedback) now contains text
- He clicks on the "Submit" button
- He checks that next screen contains a confirmation sentence
- He closes the window
- Administrator finished tallying of the election
- Alice goes to the election page
- She clicks on the "Administer this election" link
- She logs in as administrator
- She checks that encrypted tally hash is still the same as the first time it has been displayed to her
- She checks that the "DONE?" column of each trustee is to "Yes"
- She clicks on the "Compute the result" button
- She checks consistency of the election result
- She checks that the number of accepted ballots is the same as the number of voters who voted
- For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance
- She checks that each ballot content corresponds to content that of this vote that has been randomly generated in advance
- Verify election consistency (using command line tool `belenios_tool verify`)
......@@ -61,6 +61,20 @@ section~\ref{default-group}.
\section{Parties}
\newcommand{\pk}{\texttt{public\_key}}
\newcommand{\sk}{\texttt{private\_key}}
\newcommand{\proof}{\texttt{proof}}
\newcommand{\iproof}{\texttt{iproof}}
\newcommand{\ciphertext}{\texttt{ciphertext}}
\newcommand{\pklabel}{\textsf{public\_key}}
\newcommand{\pok}{\textsf{pok}}
\newcommand{\challenge}{\textsf{challenge}}
\newcommand{\response}{\textsf{response}}
\newcommand{\alphalabel}{\textsf{alpha}}
\newcommand{\betalabel}{\textsf{beta}}
\newcommand{\Hash}{\mathcal{H}}
\begin{itemize}
\item $\mathcal{S}$: voting server
\item $\mathcal{A}$: server administrator
......@@ -106,7 +120,10 @@ partial decryption.
\item $\mathcal{A}$ checks $k_z$
\end{enumerate}
\item $\mathcal{A}$ combines all the trustee public keys into the election
public key $y$
public key $y$:
\[
y=\prod_{z\in[1\dots m]}\pklabel(k_z)
\]
\end{enumerate}
\subsubsection{Threshold decryption support}
......@@ -142,6 +159,8 @@ a partial decryption.
\end{enumerate}
\item $\mathcal{A}$ extracts encrypted decryption keys $K_1,\dots,K_m$ and
\hyperref[threshold-params]{threshold parameters}
\item $\mathcal{A}$ computes the election public key $y$ as specified
in section~\ref{polynomials}.
\end{enumerate}
\subsection{Vote}
......@@ -208,20 +227,6 @@ $\textsf{field}(o)$ to access the field \textsf{field} of $o$.
\subsection{Common structures}
\label{common}
\newcommand{\pk}{\texttt{public\_key}}
\newcommand{\sk}{\texttt{private\_key}}
\newcommand{\proof}{\texttt{proof}}
\newcommand{\iproof}{\texttt{iproof}}
\newcommand{\ciphertext}{\texttt{ciphertext}}
\newcommand{\pklabel}{\textsf{public\_key}}
\newcommand{\pok}{\textsf{pok}}
\newcommand{\challenge}{\textsf{challenge}}
\newcommand{\response}{\textsf{response}}
\newcommand{\alphalabel}{\textsf{alpha}}
\newcommand{\betalabel}{\textsf{beta}}
\newcommand{\Hash}{\mathcal{H}}
\begin{gather*}
\proof=\left\{
\begin{array}{rcl}
......@@ -466,6 +471,11 @@ $s_{ij}=f_i(j)\mod q$ for $j=1,\dotsc,m$. $\mathcal{T}_i$ then fills the
filled with $A_{i0},\dotsc,A_{it}$
\end{itemize}
The public key of the election will be:
\[
y=\prod_{z\in[1\dots m]}g^{f_z(0)}=\prod_{z\in[1\dots m]}A_{z0}
\]
\subsubsection{Vinputs}
\label{vinputs}
......
......@@ -4,7 +4,9 @@
if [ -d ../.git ] && which git >/dev/null 2>&1; then
BUILD=${BUILD:-$(git describe)}
else
BUILD=${BUILD:-$(date -u +%Y%m%d)}
DATE=${SOURCE_DATE_EPOCH:-$(date +%s)}
DATE=$(date -d @$DATE +%Y%m%d)
BUILD=${BUILD:-$DATE}
fi
head -n1 VERSION
......
......@@ -132,8 +132,8 @@ let () = dispatch & function
copy_rule "belenios-tool.html" "src/tool/belenios-tool.html" "src/static/belenios-tool.html";
copy_rule "encrypting.gif" "ext/booth/encrypting.gif" "src/static/encrypting.gif";
copy_rule "booth.js" "src/booth/booth.js" "src/static/booth.js";
copy_rule "tool_js_booth.js" "src/tool/tool_js_booth.js" "src/static/tool_js_booth.js";
copy_rule "tool_js_tkeygen.js" "src/tool/tool_js_tkeygen.js" "src/static/tool_js_tkeygen.js";
copy_rule "tool_js_ttkeygen.js" "src/tool/tool_js_ttkeygen.js" "src/static/tool_js_ttkeygen.js";
copy_rule "tool_js_credgen.js" "src/tool/tool_js_credgen.js" "src/static/tool_js_credgen.js";
......
......@@ -34,43 +34,26 @@ fi
mkdir -p "$BELENIOS_SYSROOT/bootstrap/src"
cd "$BELENIOS_SYSROOT/bootstrap/src"
wget http://caml.inria.fr/pub/distrib/ocaml-4.02/ocaml-4.02.3.tar.gz
wget https://github.com/ocaml/opam/releases/download/1.2.2/opam-full-1.2.2.tar.gz
wget https://github.com/ocaml/opam/releases/download/2.0.0/opam-full-2.0.0.tar.gz
if which sha256sum >/dev/null; then
sha256sum --check <<EOF
928fb5f64f4e141980ba567ff57b62d8dc7b951b58be9590ffb1be2172887a72 ocaml-4.02.3.tar.gz
15e617179251041f4bf3910257bbb8398db987d863dd3cfc288bdd958de58f00 opam-full-1.2.2.tar.gz
9dad4fcb4f53878c9daa6285d8456ccc671e21bfa71544d1f926fb8a63bfed25 opam-full-2.0.0.tar.gz
EOF
else
echo "WARNING: sha256sum was not found, checking tarballs is impossible!"
fi
echo
echo "=-=-= Compilation and installation of OCaml =-=-="
echo
cd "$BELENIOS_SYSROOT/bootstrap/src"
tar -xzf ocaml-4.02.3.tar.gz
cd ocaml-4.02.3
./configure -prefix "$BELENIOS_SYSROOT/bootstrap"
make world
if ! grep -q ARCH=none config/Makefile; then
make opt
make opt.opt
fi
make install
export PATH="$BELENIOS_SYSROOT/bootstrap/bin:$PATH"
echo
echo "=-=-= Compilation and installation of OPAM =-=-="
echo
cd "$BELENIOS_SYSROOT/bootstrap/src"
tar -xzf opam-full-1.2.2.tar.gz
cd opam-full-1.2.2
./configure -prefix "$BELENIOS_SYSROOT/bootstrap"
make lib-ext
make
make install
tar -xzf opam-full-2.0.0.tar.gz
cd opam-full-2.0.0
make cold CONFIGURE_ARGS="--prefix $BELENIOS_SYSROOT/bootstrap"
make cold-install LIBINSTALL_DIR="$BELENIOS_SYSROOT/bootstrap/lib/ocaml"
echo
echo "=-=-= Generation of env.sh =-=-="
......@@ -78,21 +61,20 @@ echo
cat > $BELENIOS_SRC/env.sh <<EOF
PATH="$BELENIOS_SYSROOT/bootstrap/bin:\$PATH"; export PATH;
OPAMROOT=$OPAMROOT; export OPAMROOT;
eval \`opam config env\`
eval \$(opam env)
EOF
echo
echo "=-=-= Initialization of OPAM root =-=-="
echo
opam init --no-setup
eval `opam config env`
opam switch 4.06.1
eval `opam config env`
opam init --bare --no-setup
opam switch create 4.06.1
eval $(opam env)
echo
echo "=-=-= Installation of Belenios build-dependencies =-=-="
echo
opam install --yes atdgen zarith cryptokit uuidm calendar cmdliner sqlite3 ssl=0.5.5 eliom=6.3.0 csv
opam install --yes atdgen zarith cryptokit uuidm calendar cmdliner sqlite3 ssl eliom=6.3.0 csv
echo
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
......
# Tools for automated tests
selenium==3.14.0
\ No newline at end of file