Exemplo n.º 1
0
        public void Step03_RecordBallots()
        {
            var castIds    = new List <string>();
            var spoiledIds = new List <string>();

            // randomly assign to cast or spoil lists
            foreach (var id in _ballotIds)
            {
                if (BallotGenerator.RandomBit())
                {
                    castIds.Add(id);
                }
                else
                {
                    spoiledIds.Add(id);
                }
            }

            var result = ElectionGuardApi.RecordBallots(
                _electionGuardConfig,
                castIds,
                spoiledIds,
                _ballotIds,
                _encryptedBallots,
                _exportFolder,
                _ballotsPrefix
                );

            Assert.AreEqual(castIds.Count, result.CastedBallotTrackers.Count);
            Assert.AreEqual(spoiledIds.Count, result.SpoiledBallotTrackers.Count);
            _ballotsFilename = result.EncryptedBallotsFilename;
            Assert.IsNotNull(_ballotsFilename);
        }
Exemplo n.º 2
0
        public void Step02_VotingAndEncryption()
        {
            var deleteSuccess     = ElectionGuardApi.SoftDeleteEncryptedBallotsFile(_exportFolder, _encryptedBallotsPrefix);
            var currentNumBallots = 0;

            while (currentNumBallots < _numberOfBallots)
            {
                // generates new random ballot
                var randomBallot = BallotGenerator.FillRandomBallot(
                    _electionGuardConfig.NumberOfSelections, _expectedNumberOfSelected);

                var result = ElectionGuardApi.EncryptBallot(
                    randomBallot,
                    _expectedNumberOfSelected,
                    _electionGuardConfig,
                    $"{currentNumBallots}",
                    _exportFolder,
                    _encryptedBallotsPrefix
                    );

                Assert.IsNotEmpty(result.EncryptedBallotMessage);
                Assert.IsNotEmpty(result.Tracker);
                Assert.AreEqual($"{currentNumBallots}", result.ExternalIdentifier);
                Assert.IsNotEmpty(result.OutputFileName);

                _encryptedBallots.Add(result.EncryptedBallotMessage);
                _ballotIds.Add(result.ExternalIdentifier);

                currentNumBallots++;
            }
        }
        public ActionResult <EncryptBallotResponse[]> EncryptBallots(EncryptBallotsRequest request)
        {
            // TODO: cache encrypted ballot id's in memory and disallow encrypting an existing ballot id

            try
            {
                var exportPath          = request.ExportPath ?? _exportPath;
                var exportFileName      = request.ExportFileName ?? _encryptedBallotsExportFileName;
                var electionMap         = request.ElectionMap ?? GetElectionMap(request.Election);
                var electionGuardConfig = request.ElectionGuardConfig ?? _electionGuardConfig;
                if (electionMap == null || electionGuardConfig == null)
                {
                    return(BadRequest(EncryptionSetupRequiredMessage));
                }

                if (request.Ballots.Any(i => String.IsNullOrWhiteSpace(i.BallotId)))
                {
                    return(BadRequest(EncryptMissingIdentifierMessage));
                }

                var response = new List <EncryptBallotResponse>();

                foreach (var ballot in request.Ballots)
                {
                    var selections       = _electionMapper.ConvertToSelections(ballot, electionMap);
                    var numberOfExpected = electionMap.BallotStyleMaps[ballot.BallotStyle.Id].ExpectedNumberOfSelected;
                    var encryptedBallot  = ElectionGuardApi.EncryptBallot(
                        selections,
                        numberOfExpected,
                        electionGuardConfig,
                        ballot.BallotId,
                        exportPath,
                        exportFileName);

                    _currentBallotCount++;

                    var ballotResponse = new EncryptBallotResponse()
                    {
                        Id = encryptedBallot.ExternalIdentifier,
                        EncryptedBallotMessage = encryptedBallot.EncryptedBallotMessage,
                        Tracker                = encryptedBallot.Tracker,
                        OutputFileName         = encryptedBallot.OutputFileName,
                        CurrentNumberOfBallots = _currentBallotCount
                    };

                    response.Add(ballotResponse);
                }

                return(CreatedAtAction(nameof(EncryptBallots), response));
            }
            catch (Exception ex)
            {
                _logger.LogError("EncryptBallots: ", ex);
                return(StatusCode(500));
            }
        }
Exemplo n.º 4
0
        public void Step01_InitializeElection()
        {
            var result = ElectionGuardApi.CreateElection(_electionGuardConfig);

            _electionGuardConfig = result.ElectionGuardConfig;

            Assert.That(string.IsNullOrEmpty(_electionGuardConfig.JointPublicKey), Is.False);

            _trusteeKeys = result.TrusteeKeys;
            Assert.AreEqual(result.ElectionGuardConfig.NumberOfTrustees, _trusteeKeys.Count);

            Assert.Greater(_electionGuardConfig.NumberOfSelections, 0);
            var expectedNumberOfSelections = 3;

            Assert.AreEqual(expectedNumberOfSelections, result.ElectionGuardConfig.NumberOfSelections);
        }
Exemplo n.º 5
0
        public void Step04_TallyVotes()
        {
            // assume we have the equivalent number of trustees present to the threshold number required
            var numberOfTrusteesPresent = _electionGuardConfig.Threshold;
            var result = ElectionGuardApi.TallyVotes(
                _electionGuardConfig,
                _trusteeKeys.Values,
                numberOfTrusteesPresent,
                _ballotsFilename,
                _exportFolder,
                _tallyPrefix
                );

            Assert.IsNotNull(result.EncryptedTallyFilename);
            Assert.AreEqual(_electionGuardConfig.NumberOfSelections, result.TallyResults.Count);
        }
        public ActionResult <CreateElectionResult> CreateElection(ElectionRequest request)
        {
            try
            {
                var electionMap = _electionMapper.GetElectionMap(request.Election);
                request.Config.NumberOfSelections = electionMap.NumberOfSelections;

                var election = ElectionGuardApi.CreateElection(request.Config);
                return(CreatedAtAction(nameof(CreateElection), new ElectionResponse {
                    ElectionGuardConfig = election.ElectionGuardConfig,
                    TrusteeKeys = election.TrusteeKeys,
                    ElectionMap = electionMap,
                }));
            }
            catch (Exception ex)
            {
                _logger.LogError("CreateElection: ", ex);
                return(StatusCode(500));
            }
        }
Exemplo n.º 7
0
        static int NUM_RANDOM_BALLOTS  = 5;             // the number of ballots to use when executing the test

        static void Main(string[] args)
        {
            var initialConfig = new ElectionGuardConfig()
            {
                NumberOfTrustees   = NUM_TRUSTEES,
                NumberOfSelections = NUM_SELECTIONS,
                Threshold          = THRESHOLD,
                SubgroupOrder      = 0,
                ElectionMetadata   = "placeholder",
            };

            // Create Election

            Console.WriteLine("\n--- Create Election ---\n");

            var electionResult = ElectionGuardApi.CreateElection(initialConfig);

            foreach (KeyValuePair <int, string> entry in electionResult.TrusteeKeys)
            {
                if (String.IsNullOrWhiteSpace(entry.Value))
                {
                    throw new Exception("Error reading trustee keys");
                }
            }

            // Encrypt Ballots

            Console.WriteLine("\n--- Encrypt Ballots ---\n");

            var now = DateTime.Now;

            var expectedNumberOfSelected = 2;
            var encryptedBallotsFileName = "";
            var encryptedOutputPath      = "./ballots_encrypter/";
            var encryptedOutputPrefix    = $"encrypted-ballots_{now.Year}_{now.Month}_{now.Day}";

            if (!ElectionGuardApi.SoftDeleteEncryptedBallotsFile(encryptedOutputPath, encryptedOutputPrefix))
            {
                throw new Exception("Failed soft deleting the encrypted ballots file");
            }

            var testBallots = new List <TestBallot>();

            for (var i = 0; i < NUM_RANDOM_BALLOTS; i++)
            {
                var ballot = new TestBallot();
                ballot.ExternalIdentifier = $"{encryptedOutputPrefix}_{i}";
                ballot.Selections         = FillRandomBallot(NUM_SELECTIONS, expectedNumberOfSelected);

                var encryptBallotResult = ElectionGuardApi.EncryptBallot(
                    ballot.Selections,
                    expectedNumberOfSelected,
                    electionResult.ElectionGuardConfig,
                    ballot.ExternalIdentifier,
                    encryptedOutputPath,
                    encryptedOutputPrefix
                    );

                Console.WriteLine($"Encrypted Ballot {i}:");
                Console.WriteLine($"\tIdentifier = {encryptBallotResult.ExternalIdentifier}");
                Console.WriteLine($"\tTracker = {encryptBallotResult.Tracker}");
                Console.WriteLine($"\tEncryptedBallotMessage.Length = {encryptBallotResult.EncryptedBallotMessage.Length}");

                ballot.EncryptedBallotMessage = encryptBallotResult.EncryptedBallotMessage;
                ballot.Tracker           = encryptBallotResult.Tracker;
                encryptedBallotsFileName = encryptBallotResult.OutputFileName;

                testBallots.Add(ballot);
            }

            // TODO: test simulating multiple encrypters or an encrypter being reset

            // [START] OPTIONAL:

            // When running an encrypter on another device, it is possible to import a file
            // and pass it to the tally functions, but this is not strictly necessary
            // from an API Perspective.

            Console.WriteLine("\n--- Load Ballots ---\n");

            var loadBallotsResult = ElectionGuardApi.LoadBallotsFile(
                0,
                2000,
                NUM_SELECTIONS,
                encryptedBallotsFileName
                );

            var loadedExternalIdentifiers = (List <string>)loadBallotsResult.ExternalIdentifiers;
            var loadedEncryptedBallots    = (List <string>)loadBallotsResult.EncryptedBallotMessages;

            Debug.Assert(
                LoadedBallotIdentifiersMatchEncryptedBallots(
                    loadedExternalIdentifiers,
                    testBallots,
                    NUM_RANDOM_BALLOTS
                    )
                );

            Debug.Assert(
                LoadedBallotsMatchEncryptedBallots(
                    loadedEncryptedBallots,
                    testBallots,
                    NUM_RANDOM_BALLOTS
                    )
                );

            // TODO: test loading ballots in batches

            // [END] OPTIONAL:

            // Register & Record Cast/Spoil Multiple Ballots

            Console.WriteLine("\n--- Randomly Assigning Ballots to be Cast or Spoil Arrays ---\n");

            int currentCastIndex          = 0;
            int currentSpoiledIndex       = 0;
            var castIds                   = new List <string>();
            var spoiledIds                = new List <string>();
            var memoryExternalIdentifiers = new List <string>();
            var memoryEncryptedBallots    = new List <string>();

            for (int i = 0; i < NUM_RANDOM_BALLOTS; i++)
            {
                memoryExternalIdentifiers.Add(testBallots[i].ExternalIdentifier);
                memoryEncryptedBallots.Add(testBallots[i].EncryptedBallotMessage);

                if (RandomBit())
                {
                    testBallots[i].IsCast    = true;
                    testBallots[i].IsSpoiled = false;
                    castIds.Add(testBallots[i].ExternalIdentifier);

                    Console.WriteLine($"Ballot Id: {testBallots[i].ExternalIdentifier} - Cast!");
                    currentCastIndex++;
                }
                else
                {
                    testBallots[i].IsCast    = false;
                    testBallots[i].IsSpoiled = true;
                    spoiledIds.Add(testBallots[i].ExternalIdentifier);

                    Console.WriteLine($"Ballot Id: {testBallots[i].ExternalIdentifier} - Spiled!");
                    currentSpoiledIndex++;
                }
            }

            if ((currentCastIndex + currentSpoiledIndex) != NUM_RANDOM_BALLOTS)
            {
                throw new Exception("Cast and Spil did not match expected ballots");
            }

            Console.WriteLine("\n--- Record Ballots (Register, Cast, and Spoil) ---\n");

            var registeredBallotsOutputPath   = "./ballots/";
            var registeredBallotsOutputPrefix = $"registered-ballots_{now.Year}_{now.Month}_{now.Day}";

            var recordResult = ElectionGuardApi.RecordBallots(
                electionResult.ElectionGuardConfig,
                castIds,
                spoiledIds,
                memoryExternalIdentifiers,
                memoryEncryptedBallots,
                registeredBallotsOutputPath,
                registeredBallotsOutputPrefix
                );

            var castedTrackers  = (List <string>)recordResult.CastedBallotTrackers;
            var spoiledTrackers = (List <string>)recordResult.SpoiledBallotTrackers;

            Console.WriteLine($"RecordBallots cast trackers\n");
            for (int i = 0; i < currentCastIndex; i++)
            {
                Console.WriteLine($"\t{castIds[i]}: {castedTrackers[i]}");
            }

            Console.WriteLine($"\nRecordBallots spoiled trackers\n");
            for (int i = 0; i < currentSpoiledIndex; i++)
            {
                Console.WriteLine($"\t{spoiledIds[i]}: {spoiledTrackers[i]}");
            }

            Console.WriteLine("\nBallot registrations and recording of cast/spoil successful!\n");
            Console.WriteLine($"RecordBallots outputted to file = {recordResult.EncryptedBallotsFilename}");

            // Tally Votes & Decrypt Results

            Console.WriteLine("\n--- Tally & Decrypt Votes ---\n");

            var tallyOutputPath   = "./tallies/";
            var tallyOutputPrefix = $"tally_{now.Year}_{now.Month}_{now.Day}";


            var tallyResult = ElectionGuardApi.TallyVotes(
                electionResult.ElectionGuardConfig,
                electionResult.TrusteeKeys.Values,
                DECRYPTING_TRUSTEES,
                recordResult.EncryptedBallotsFilename,
                tallyOutputPath,
                tallyOutputPrefix
                );

            var tallyResults = (List <int>)tallyResult.TallyResults;

            Console.WriteLine("\nTally Results:");
            for (int i = 0; i < electionResult.ElectionGuardConfig.NumberOfSelections; i++)
            {
                Debug.Assert(
                    ResultEqualsExpectedSelections(
                        testBallots,
                        tallyResults[i],
                        i
                        )
                    );
            }

            Console.WriteLine($"\nTallyVotes output to file = {tallyResult.EncryptedTallyFilename}");

            Console.WriteLine("\n--- Done! ---\n\n");
        }