static void Main(string[] args) { //HomoExample(); /* * Create a list of shareholders. * We need to set the number of shares so that if enough shareholders want to decrypt the secret they can. * But if the treshold is not met, they should not be able to decrypt the information */ List <PasswordProtectedShareHolder> shareHolders = new List <PasswordProtectedShareHolder> { CreateShareholder("xxx", id: 1, numberOfShares: 2), CreateShareholder("yyy", 2, numberOfShares: 2), CreateShareholder("zzz", 3, numberOfShares: 4) }; /* * HSM: Hardware security module - A machine that should zeroize (delete all keys/data) in case of phisical temper. * HSM never exposes the keys that it stores. The user of the HSM can do cryptographic operations with the keys, and create new keys. */ FakeHsmFactory fakeHsmFactory = new FakeHsmFactory(Path.GetTempFileName()); /* * Creates the homomorphic encryption context (encryption details), and helper methods for homomorphic cryptography operations. */ HomomorphicKeyManager keyManager = new HomomorphicKeyManager(); /* * A fake implementation of a database repository */ FakeCentralDbRepository fakeCentralDbRepository = new FakeCentralDbRepository(numberOfCandidates: 3); /* * Treshold, is the minimum number of shares needed to decrypt the splited secret. * ShareManager not tied to homomorphic encryption, it can be used with any type of encryption. */ ShareManager sm = new ShareManager(treshold: 4, hsmFactory: fakeHsmFactory, keyManager: keyManager, centralDbRepository: fakeCentralDbRepository, publicShareHolders: shareHolders.Select(sh => (IPublicShareHolder)sh).ToList()); /* * This will save the splited secret using the shareholder method to save the secret * Also this will store in the database the public key that will be used to encrypt the votes. * Along with the public key, the master key handle from the HSM will be saved as well in the database. */ sm.GenerateSplitedSecret(hsmSecret: null, electionId: 1).Wait(); /* * A key chain needs to be created so that every voting booth has a certificate signed by a certificate authority(Voting place-2019) * Voting place CA would be signed by a voting city CA, and up to voting country+electionID. * It is important for the vooting booth to sign all the votes that it prints so that the voter can later verify that he's vote has been taken into consideration. * If the voter wouldn't see his vote in the public database, he could proove to the authorities that his vote was registered by a booth. * Online he could see the hour of the vote, the vote hash, vote encrypted data, voting booth public certificate that can be used to validate the vote. */ var booth = new VotingBooth(new SignCertificate(StoreName.My, StoreLocation.CurrentUser, "ceapa"), keyManager); List <VotingBooth> votingBooths = new List <VotingBooth> { booth }; /* * A voting place is a room with voting booth's. It has the responsibility of periodically geting the data from the booth and to publish it on the public database. * The voters are saved in a separate database unlinked from the actual votes. You want them unlinked so that in future if the cipher is cracked, * no one will know what was my vote unless I showed it to somebody else. * FakeLocalBoothFinder is just gives for now instances of the voting booths. * But in a real scenario, this would just be a wrapper over the booth that would invoke the Voting Booth Server. * Only VotingPlace can access the Voting Booth Server (Using certificate authentication maybe) * */ VotingPlace votingPlace = new VotingPlace(fakeCentralDbRepository, new FakeLocalBoothFinder(votingBooths), 1, 1); booth.AddVote(new List <uint> { 0, 1, 0 }, new Voter { ID = "x", DisplayName = "X-ulescu" }); booth.AddVote(new List <uint> { 0, 1, 0 }, new Voter { ID = "y", DisplayName = "Y-ulescu" }); /* * Save the votes in the public database. * Save the voters in the public database(it may be that this is private, only to have a hash of the person?) */ votingPlace.SaveVotesPublicly().Wait(); /* * Vote aggregator. Code that adds the votes together. * Note that the aggregator only takes the context as the parameter (Not even the public key) * So anyone can actually do math operations on homomorphic encryption if they know the parameters. */ VoteAggregator aggregator = new VoteAggregator(keyManager); var aggregatedResult = aggregator.AddVotes(fakeCentralDbRepository.GetPublicVotesAsync().Result); /* * Combine the secret together again using the shareholder with ID 3(he has 4 shares, and that is the treshold for decryption) */ byte[] res = sm.GetCombinedSecret(shareHolders.Where(s => s.ID == 3).Select(s => (IAuthenticatedShareHolder)s).ToList(), null, 1).Result; /* * You can only read the votes using the combined secret and the context. * The VoteReader should only decrypt aggregates. They should agree only on a few decryptions. * Maybe a few tests on smaller aggregates, assuming that they already knwo the actual answer for those small agregates. */ VoteReader voteReader = new VoteReader(homomorphicKeyManager: keyManager, secretKeyData: res); var decryptedVotes = voteReader.DecryptVotes(aggregatedResult); }