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); }
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)); } }
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); }
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)); } }
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"); }