Exemplo n.º 1
0
    def trustees_do_partial_decryption(self, max_trustees=None):
        # Each of the `T` trustees (limited to `max_trustees`) will do the following process:
        for idx, trustee_email_address in enumerate(
                settings.TRUSTEES_EMAIL_ADDRESSES):
            if max_trustees is not None and idx >= max_trustees:  # TODO: Maybe we should pick trustees randomly in the list of trustees instead of always the first few ones?
                break
            # He opens the link that Alice (the election administrator) has sent to him
            self.browser = initialize_browser_for_scenario_2()
            browser = self.browser
            link_for_trustee = self.closed_election_tally_links_for_trustees[
                idx]
            browser.get(link_for_trustee)

            wait_a_bit()

            # He verifies that the "private key" input field is empty (at the beginning)
            private_key_field_css_selector = "#private_key"
            private_key_field_element = wait_for_element_exists(
                browser, private_key_field_css_selector)
            assert private_key_field_element.get_attribute('value') == ""

            # One trustee uploads his private key file, the other copy-pastes its contents into the form field
            private_key_file = self.downloaded_files_paths_per_trustee[
                trustee_email_address]["private key"]
            if idx % 2 == 0:
                # He clicks on the "Browse..." button and selects his private key file (initially downloaded as `private_key.json` by default)
                browse_button_css_selector = "input[id=private_key_file][type=file]"
                browse_button_element = wait_for_element_exists(
                    browser, browse_button_css_selector)
                path_of_file_to_upload = private_key_file
                browse_button_element.clear()
                browse_button_element.send_keys(path_of_file_to_upload)

                # 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.
                private_key_field_expected_non_empty_attribute = "value"
                wait_for_element_exists_and_has_non_empty_attribute(
                    browser, private_key_field_css_selector,
                    private_key_field_expected_non_empty_attribute)
            else:
                with open(private_key_file) as myfile:
                    private_key_field_element.send_keys(myfile.read())
                wait_a_bit()

            # He clicks on the "Compute decryption factors" button
            compute_button_css_selector = "button[id=compute]"
            compute_button_element = wait_for_element_exists(
                browser, compute_button_css_selector)
            compute_button_element.click()

            # He checks that the text field below (used as visual feedback) now contains text
            visual_feedback_css_selector = "#pd"
            visual_feedback_expected_non_empty_attribute = "value"
            try:
                wait_for_element_exists_and_has_non_empty_attribute(
                    browser, visual_feedback_css_selector,
                    visual_feedback_expected_non_empty_attribute, 60 * 2)
            except UnexpectedAlertPresentException as e:
                raise Exception(
                    "An alert was displayed at a moment when no alert should be displayed. Alert displayed probably contains error information about uploaded file contents."
                ) from e

            # He clicks on the "Submit" button
            submit_button_css_selector = "#pd_done input[type=submit]"
            submit_button_element = wait_for_element_exists(
                browser, submit_button_css_selector)
            submit_button_element.click()

            wait_a_bit()

            # He checks that next screen contains a confirmation sentence
            confirmation_sentence_expected_text = "Your partial decryption has been received and checked!"
            confirmation_sentence_css_selector = "#main p"
            wait_for_element_exists_and_contains_expected_text(
                browser, confirmation_sentence_css_selector,
                confirmation_sentence_expected_text,
                settings.EXPLICIT_WAIT_TIMEOUT)

            # He closes the window
            browser.quit()
Exemplo n.º 2
0
    def trustees_do_initialization_step_3_of_3(self):
        # Trustees initialization step 3/3: Trustees do the final checks so that the election can be validated. Each of the `T` (aka `NUMBER_OF_TRUSTEES`) trustees will do the following process:
        for idx, trustee_email_address in enumerate(
                settings.TRUSTEES_EMAIL_ADDRESSES):
            # Trustee opens link that has been sent to him by election administrator
            link_for_this_trustee = self.links_for_trustees[
                idx]  # TODO: Decide either not send trustee email at all or read trustee link from email content
            self.browser = initialize_browser_for_scenario_2()
            browser = self.browser
            browser.get(link_for_this_trustee)

            wait_a_bit()

            # He checks that the page content shows the same election URL as the one the administrator saw
            election_url_css_selector = "#main ul li"
            election_url_element = wait_for_element_exists_and_has_non_empty_content(
                browser, election_url_css_selector)
            election_url_content = election_url_element.get_attribute(
                'innerText').strip()
            assert election_url_content == self.election_page_url

            # He checks the presence of text "Step 3/3"
            expected_confirmation_label = "Step 3/3"
            expected_confirmation_css_selector = "#main"
            wait_for_element_exists_and_contains_expected_text(
                browser, expected_confirmation_css_selector,
                expected_confirmation_label)

            # In field next to "Enter your private key:", he types the content of the `private_key.txt` file he downloaded
            private_key_storage_label = "private key"
            private_key_file = self.downloaded_files_paths_per_trustee[
                trustee_email_address][private_key_storage_label]
            private_key_css_selector = "#compute_private_key"
            private_key_element = wait_for_element_exists(
                browser, private_key_css_selector)
            private_key_element.clear()
            with open(private_key_file) as myfile:
                private_key_element.send_keys(myfile.read())

            wait_a_bit()

            # He clicks on the "Proceed" button
            proceed_button_css_selector = "#compute_button"
            proceed_button_element = wait_for_element_exists(
                browser, proceed_button_css_selector)
            proceed_button_element.click()

            # He waits until the text field next to "Data:" contains text, and clicks on the "Submit" button
            data_field_css_selector = "#compute_data"
            data_field_expected_non_empty_attribute = "value"
            wait_for_element_exists_and_has_non_empty_attribute(
                browser, data_field_css_selector,
                data_field_expected_non_empty_attribute)

            submit_button_expected_label = "Submit"
            submit_button_css_selector = "#compute_form input[type=submit][value=" + submit_button_expected_label + "]"
            submit_button_element = wait_for_element_exists(
                browser, submit_button_css_selector)
            submit_button_element.click()

            wait_a_bit()

            # He checks that the next page contains text "Your job in the key establishment protocol is done!"
            expected_confirmation_label = "Your job in the key establishment protocol is done!"
            expected_confirmation_css_selector = "#main"
            wait_for_element_exists_and_contains_expected_text(
                browser, expected_confirmation_css_selector,
                expected_confirmation_label)

            wait_a_bit()

            # He clicks on the "public key" link and downloads the file (file is saved by default as `public_key.json`)
            link_css_ids = ["public_key"]
            link_expected_labels = ["public key"]
            if trustee_email_address not in self.downloaded_files_paths_per_trustee:
                self.downloaded_files_paths_per_trustee[
                    trustee_email_address] = dict()
            for idx2, link_css_id in enumerate(link_css_ids):
                link_target_filename = str(uuid4())
                set_element_attribute(browser, link_css_id, 'download',
                                      link_target_filename)
                link_expected_label = link_expected_labels[idx2]
                link_element = wait_for_an_element_with_partial_link_text_exists(
                    browser, link_expected_label)
                assert link_element.get_attribute('id') == link_css_id
                link_element.click()
                file_absolute_path = os.path.join(
                    settings.BROWSER_DOWNLOAD_FOLDER, link_target_filename)
                # We save the filename in a class instance property, so that we can import the file afterwards (during partial decryption step)
                self.downloaded_files_paths_per_trustee[trustee_email_address][
                    link_expected_labels[idx2]] = file_absolute_path
                self.remember_temporary_file_to_remove_after_test(
                    file_absolute_path)

            wait_a_bit()

            # He closes the window
            browser.quit()

            # Administrator logs in, and selects the election by clicking on its link
            self.browser = initialize_browser_for_scenario_2()
            browser = self.browser

            log_in_as_administrator(browser)

            browser.get(self.draft_election_administration_page_url)

            wait_a_bit()

            # In the trustees section, she clicks on the "here" link
            setup_election_key_link_label = "here"
            setup_election_key_link_element = wait_for_an_element_with_partial_link_text_exists(
                browser, setup_election_key_link_label)
            setup_election_key_link_element.click()

            wait_a_bit()

            # If current trustee is the last one, she checks that in the table, the "STATE" column is now "done" on every row. Else, she checks that in the table on the current trustee row, the "STATE" column is now "3b" (instead of "3a")
            if idx == settings.NUMBER_OF_TRUSTEES - 1:
                expected_value = "done"
                verify_all_trustee_states_in_table(browser, expected_value)
            else:
                expected_value = "3b"
                verify_trustee_state_in_table(browser, idx, expected_value)

            wait_a_bit()

            # She closes the window
            browser.quit()
Exemplo n.º 3
0
    def trustees_do_partial_decryption(self):
        # Each trustee (Tom and Taylor) will do the following process:
        for idx, trustee_email_address in enumerate(settings.TRUSTEES_EMAIL_ADDRESSES):
            # He opens the link that Alice (the election administrator) has sent to him
            self.browser = initialize_browser_for_scenario_2()
            browser = self.browser
            link_for_trustee = self.closed_election_tally_links_for_trustees[idx]
            browser.get(link_for_trustee)

            wait_a_bit()

            # We verify that the encrypted election hash is the same as the one that has been displayed to election administrator
            encrypted_tally_hash_css_selector = "#hash"
            encrypted_tally_hash_element = wait_for_element_exists_and_has_non_empty_content(browser, encrypted_tally_hash_css_selector)
            encrypted_tally_hash = encrypted_tally_hash_element.get_attribute('innerText')
            assert encrypted_tally_hash == self.encrypted_tally_hash, "Error: Encrypted tally hash displayed to trustee (" + encrypted_tally_hash + ") is not the same as the one displayed to election administrator (" + self.encrypted_tally_hash + ")."

            # He verifies that the "private key" input field is empty (at the beginning)
            private_key_field_css_selector = "#private_key"
            private_key_field_element = wait_for_element_exists(browser, private_key_field_css_selector)
            assert private_key_field_element.get_attribute('value') == ""

            # One trustee uploads his private key file, the other copy-pastes its contents into the form field
            private_key_file = self.downloaded_files_paths_per_trustee[trustee_email_address]["private key"]
            if idx % 2 == 0:
                # He clicks on the "Browse..." button and selects his private key file (initially downloaded as `private_key.json` by default)
                browse_button_css_selector = "input[id=private_key_file][type=file]"
                browse_button_element = wait_for_element_exists(browser, browse_button_css_selector)
                path_of_file_to_upload = private_key_file
                browse_button_element.clear()
                browse_button_element.send_keys(path_of_file_to_upload)

                # 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.
                private_key_field_expected_non_empty_attribute = "value"
                wait_for_element_exists_and_has_non_empty_attribute(browser, private_key_field_css_selector, private_key_field_expected_non_empty_attribute)
            else:
                with open(private_key_file) as myfile:
                    private_key_field_element.send_keys(myfile.read())
                wait_a_bit()

            # He clicks on the "Compute decryption factors" button
            compute_button_css_selector = "button[id=compute]"
            compute_button_element = wait_for_element_exists(browser, compute_button_css_selector)
            compute_button_element.click()

            # He checks that the text field below (used as visual feedback) now contains text
            visual_feedback_css_selector = "#pd"
            visual_feedback_expected_non_empty_attribute = "value"
            try:
                wait_for_element_exists_and_has_non_empty_attribute(browser, visual_feedback_css_selector, visual_feedback_expected_non_empty_attribute, 60 * 2)
            except UnexpectedAlertPresentException as e:
                raise Exception("An alert was displayed at a moment when no alert should be displayed. Alert displayed probably contains error information about uploaded file contents.") from e

            # He clicks on the "Submit" button
            submit_button_css_selector = "#pd_done input[type=submit]"
            submit_button_element = wait_for_element_exists(browser, submit_button_css_selector)
            submit_button_element.click()

            wait_a_bit()

            # He checks that next screen contains a confirmation sentence
            confirmation_sentence_expected_text = "Your partial decryption has been received and checked!"
            confirmation_sentence_css_selector = "#main p"
            wait_for_element_exists_and_contains_expected_text(browser, confirmation_sentence_css_selector, confirmation_sentence_expected_text, settings.EXPLICIT_WAIT_TIMEOUT)

            # He closes the window
            browser.quit()
Exemplo n.º 4
0
    def trustees_do_initialization_step_2_of_3(self):
        # Trustees initialization step 2/3: Trustees generate their share of the decryption key. Each of the `T` (aka `NUMBER_OF_TRUSTEES`) trustees will do the following process:
        for idx, trustee_email_address in enumerate(
                settings.TRUSTEES_EMAIL_ADDRESSES):
            # Trustee opens link that has been sent to him by election administrator
            link_for_this_trustee = self.links_for_trustees[
                idx]  # TODO: Decide either not send trustee email at all or read trustee link from email content
            self.browser = initialize_browser_for_scenario_2()
            browser = self.browser
            browser.get(link_for_this_trustee)

            wait_a_bit()

            # He checks that the page content shows the same election URL as the one the administrator saw
            election_url_css_selector = "#main ul li"
            election_url_element = wait_for_element_exists_and_has_non_empty_content(
                browser, election_url_css_selector)
            election_url_content = election_url_element.get_attribute(
                'innerText').strip()
            assert election_url_content == self.election_page_url

            # He checks the presence of text "Now, all the certificates of the trustees have been generated. Proceed to generate your share of the decryption key."
            expected_confirmation_label = "Now, all the certificates of the trustees have been generated. Proceed to generate your share of the decryption key."
            expected_confirmation_css_selector = "#main"
            wait_for_element_exists_and_contains_expected_text(
                browser, expected_confirmation_css_selector,
                expected_confirmation_label)

            # In field next to "Enter your private key:", he types the content of the `private_key.txt` file he downloaded
            private_key_storage_label = "private key"
            private_key_file = self.downloaded_files_paths_per_trustee[
                trustee_email_address][private_key_storage_label]
            private_key_css_selector = "#compute_private_key"
            private_key_element = wait_for_element_exists(
                browser, private_key_css_selector)
            private_key_element.clear()
            with open(private_key_file) as myfile:
                private_key_element.send_keys(myfile.read())

            wait_a_bit()

            # He clicks on the "Proceed" button
            proceed_button_css_selector = "#compute_button"
            proceed_button_element = wait_for_element_exists(
                browser, proceed_button_css_selector)
            proceed_button_element.click()

            # He waits until the text field next to "Data:" contains text, and clicks on the "Submit" button
            data_field_css_selector = "#compute_data"
            data_field_expected_non_empty_attribute = "value"
            wait_for_element_exists_and_has_non_empty_attribute(
                browser, data_field_css_selector,
                data_field_expected_non_empty_attribute)

            submit_button_expected_label = "Submit"
            submit_button_css_selector = "#compute_form input[type=submit][value=" + submit_button_expected_label + "]"
            submit_button_element = wait_for_element_exists(
                browser, submit_button_css_selector)
            submit_button_element.click()

            wait_a_bit()

            # If he is not the last trustee in the list, he checks that the next page contains text "Waiting for the other trustees... Reload the page to check progress.". Else, he checks that the next page contains text "Now, all the trustees have generated their secret shares. Proceed to the final checks so that the election can be validated."
            if idx == settings.NUMBER_OF_TRUSTEES - 1:
                expected_confirmation_label = "Now, all the trustees have generated their secret shares. Proceed to the final checks so that the election can be validated."
            else:
                expected_confirmation_label = "Waiting for the other trustees... Reload the page to check progress."
            expected_confirmation_css_selector = "#main"
            wait_for_element_exists_and_contains_expected_text(
                browser, expected_confirmation_css_selector,
                expected_confirmation_label)

            wait_a_bit()

            # He closes the window
            browser.quit()

            # Administrator logs in, and selects the election by clicking on its link
            self.browser = initialize_browser_for_scenario_2()
            browser = self.browser

            log_in_as_administrator(browser)

            browser.get(self.draft_election_administration_page_url)

            wait_a_bit()

            # In the trustees section, she clicks on the "here" link
            setup_election_key_link_label = "here"
            setup_election_key_link_element = wait_for_an_element_with_partial_link_text_exists(
                browser, setup_election_key_link_label)
            setup_election_key_link_element.click()

            wait_a_bit()

            # If current trustee is the last one, she checks that in the table, the "STATE" column is now "3a" on every row. Else, she checks that in the table on the current trustee row, the "STATE" column is now "2b" (instead of "2a")
            if idx == settings.NUMBER_OF_TRUSTEES - 1:
                expected_value = "3a"
                verify_all_trustee_states_in_table(browser, expected_value)
            else:
                expected_value = "2b"
                verify_trustee_state_in_table(browser, idx, expected_value)

            wait_a_bit()

            # She closes the window
            browser.quit()