Skip to content

Commit 7165e78

Browse files
Revert "Merge branch 'overvote_and_writeins' into main"
This reverts commit 355b689, reversing changes made to a6fad69.
1 parent 355b689 commit 7165e78

22 files changed

Lines changed: 303 additions & 671 deletions

File tree

bindings/netstandard/ElectionGuard/ElectionGuard.Encryption.Tests/TestEncrypt.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void Test_Encrypt_Ballot_Undervote_Succeeds()
7373
}
7474

7575
[Test]
76-
public void Test_Encrypt_Ballot_Overvote_Succeeds()
76+
public void Test_Encrypt_Ballot_Overvote_Fails()
7777
{
7878
// Configure the election context
7979
var keypair = ElGamalKeyPair.FromSecret(Constants.TWO_MOD_Q);
@@ -86,9 +86,8 @@ public void Test_Encrypt_Ballot_Overvote_Succeeds()
8686

8787
// Act
8888
var ballot = BallotGenerator.GetFakeBallot(internalManifest, 2);
89-
var ciphertext = mediator.Encrypt(ballot);
89+
Assert.Throws<ArgumentException>(() => mediator.Encrypt(ballot));
9090

91-
Assert.That(ciphertext.IsValidEncryption(context.ManifestHash, keypair.PublicKey, context.CryptoExtendedBaseHash));
9291
}
9392

9493
[Test]

include/electionguard/ballot.hpp

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,11 @@ namespace electionguard
4343
/// <returns>BallotBoxState.unknown if the value cannot be resolved</returns>
4444
/// </Summary>
4545
EG_API BallotBoxState getBallotBoxState(const std::string &value);
46-
46+
4747
/// <summary>
4848
/// ExtendedData represents any arbitrary data expressible as a string with a length.
4949
///
50-
/// This class is used primarily as a field to hold encrypted data on a
51-
/// contest, overvote data and writeins.
50+
/// This class is used primarily as a field on a selection to indicate a write-in candidate text value
5251
/// </summary>
5352
struct ExtendedData {
5453
public:
@@ -72,7 +71,7 @@ namespace electionguard
7271
return std::make_unique<ExtendedData>(this->value, this->length);
7372
}
7473
};
75-
74+
7675
/// <summary>
7776
/// A BallotSelection represents an individual selection on a ballot.
7877
///
@@ -95,7 +94,8 @@ namespace electionguard
9594
PlaintextBallotSelection(const PlaintextBallotSelection &other);
9695
PlaintextBallotSelection(PlaintextBallotSelection &&other);
9796
PlaintextBallotSelection(std::string objectId, uint64_t vote,
98-
bool isPlaceholderSelection = false, std::string writeIn = "");
97+
bool isPlaceholderSelection = false,
98+
std::unique_ptr<ExtendedData> extendedData = nullptr);
9999
~PlaintextBallotSelection();
100100

101101
PlaintextBallotSelection &operator=(PlaintextBallotSelection other);
@@ -118,9 +118,9 @@ namespace electionguard
118118
bool getIsPlaceholder() const;
119119

120120
/// <summary>
121-
/// an optional field holding the value of a write-in candidate
121+
/// an optional field of arbitrary data, such as the value of a write-in candidate
122122
/// </summary>
123-
std::string getWriteIn() const;
123+
ExtendedData *getExtendedData() const;
124124

125125
/// <summary>
126126
/// Given a PlaintextBallotSelection validates that the object matches an expected object
@@ -330,14 +330,6 @@ namespace electionguard
330330
//TODO: void setNonce(ElementModQ *nonce);
331331
};
332332

333-
typedef enum valid_contest_return_e {
334-
SUCCESS = 0,
335-
OVERVOTE = 1,
336-
OVERVOTE_ERROR = 2,
337-
INVALID_OBJECT_ID_ERROR = 2,
338-
TOO_MANY_SELECTIONS_ERROR = 3,
339-
} valid_contest_return;
340-
341333
/// <summary>
342334
/// A PlaintextBallotContest represents the selections made by a voter for a specific ContestDescription
343335
///
@@ -378,10 +370,8 @@ namespace electionguard
378370
///
379371
/// Note: because this class supports partial representations, undervotes are considered a valid state.
380372
/// </Summary>
381-
valid_contest_return isValid(const std::string &expectedObjectId,
382-
uint64_t expectedNumberSelections,
383-
uint64_t expectedNumberElected, uint64_t votesAllowd = 0,
384-
bool supportOvervotes = true) const;
373+
bool isValid(const std::string &expectedObjectId, uint64_t expectedNumberSelections,
374+
uint64_t expectedNumberElected, uint64_t votesAllowd = 0) const;
385375

386376
private:
387377
class Impl;
@@ -414,8 +404,7 @@ namespace electionguard
414404
std::unique_ptr<ElementModQ> nonce,
415405
std::unique_ptr<ElGamalCiphertext> ciphertextAccumulation,
416406
std::unique_ptr<ElementModQ> cryptoHash,
417-
std::unique_ptr<ConstantChaumPedersenProof> proof,
418-
std::unique_ptr<HashedElGamalCiphertext> hashedElGamal);
407+
std::unique_ptr<ConstantChaumPedersenProof> proof);
419408
~CiphertextBallotContest();
420409

421410
CiphertextBallotContest &operator=(CiphertextBallotContest other);
@@ -463,12 +452,6 @@ namespace electionguard
463452
/// </summary>
464453
ConstantChaumPedersenProof *getProof() const;
465454

466-
/// <summary>
467-
/// The hashed elgamal ciphertext is the encrypted extended data (overvote information
468-
/// and writeins).
469-
/// </summary>
470-
std::unique_ptr<HashedElGamalCiphertext> getHashedElGamalCiphertext() const;
471-
472455
/// <summary>
473456
/// Given an encrypted BallotContest, generates a hash, suitable for rolling up
474457
/// into a hash / tracking code for an entire ballot. Of note, this particular hash examines
@@ -496,8 +479,7 @@ namespace electionguard
496479
const ElementModQ &proofSeed, const uint64_t numberElected,
497480
std::unique_ptr<ElementModQ> nonce = nullptr,
498481
std::unique_ptr<ElementModQ> cryptoHash = nullptr,
499-
std::unique_ptr<ConstantChaumPedersenProof> proof = nullptr,
500-
std::unique_ptr<HashedElGamalCiphertext> hashedElGamal = nullptr);
482+
std::unique_ptr<ConstantChaumPedersenProof> proof = nullptr);
501483

502484
/// <summary>
503485
/// An aggregate nonce for the contest composed of the nonces of the selections.

include/electionguard/ballot_compact.hpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ namespace electionguard
3939
CompactPlaintextBallot(const CompactPlaintextBallot &other);
4040
CompactPlaintextBallot(const CompactPlaintextBallot &&other);
4141
CompactPlaintextBallot(const std::string &objectId, const std::string &styleId,
42-
std::vector<uint64_t> selections, std::vector<std::string> writeins);
42+
std::vector<uint64_t> selections,
43+
std::map<uint64_t, std::unique_ptr<ExtendedData>> extendedData);
4344
~CompactPlaintextBallot();
4445

4546
CompactPlaintextBallot &operator=(CompactPlaintextBallot other);
@@ -65,16 +66,22 @@ namespace electionguard
6566
std::vector<uint64_t> getSelections() const;
6667

6768
/// <Summary>
68-
/// The collection of writeins on the ballot ordered by the contest sequence order
69-
/// and the selection sequence order. It is up to the consumer to guarantee the order of elements
69+
/// The mapping of extended data selections as they apply to the selections on the ballot
70+
/// by index order when calling `getSelections`.
7071
/// </Summary>
71-
std::vector<std::string> getWriteIns() const;
72+
std::map<uint64_t, std::reference_wrapper<ExtendedData>> getExtendedData() const;
7273

7374
/// <Summary>
7475
/// Make a compact representation of a plaintext ballot
7576
/// </Summary>
7677
static std::unique_ptr<CompactPlaintextBallot> make(const PlaintextBallot &plaintext);
7778

79+
/// <Summary>
80+
/// Convenience accessor for retrieving the extended data for a selection index
81+
/// <returns>a value or a null pointer if none exists</returns>
82+
/// </Summary>
83+
std::unique_ptr<ExtendedData> getExtendedDataFor(const uint64_t index) const;
84+
7885
/// <Summary>
7986
/// Export the ballot representation as BSON
8087
/// </Summary>

include/electionguard/elgamal.hpp

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ namespace electionguard
3737
/// <Summary>
3838
/// Make an elgamal keypair from a secret.
3939
/// </Summary>
40-
static std::unique_ptr<ElGamalKeyPair> fromSecret(const ElementModQ &secretKey,
41-
bool isFixedBase = true);
40+
static std::unique_ptr<ElGamalKeyPair> fromSecret(const ElementModQ &secretKey, bool isFixedBase = true);
4241

4342
private:
4443
class Impl;
@@ -132,18 +131,23 @@ namespace electionguard
132131
/// <returns>A ciphertext tuple.</returns>
133132
/// </summary>
134133
EG_API std::unique_ptr<ElGamalCiphertext>
135-
elgamalEncrypt_with_precomputed(uint64_t m, ElementModP &gToRho, ElementModP &pubkeyToRho);
134+
elgamalEncrypt_with_precomputed(uint64_t m, ElementModP &gToRho,
135+
ElementModP &pubkeyToRho);
136136
/// <summary>
137137
/// Accumulate the ciphertexts by adding them together.
138138
/// </summary>
139139
EG_API std::unique_ptr<ElGamalCiphertext>
140140
elgamalAdd(const std::vector<std::reference_wrapper<ElGamalCiphertext>> &ciphertexts);
141141

142-
#define HASHED_CIPHERTEXT_BLOCK_LENGTH 32U
143-
#define _PAD_INDICATOR_SIZE sizeof(uint16_t)
142+
#define HASHED_CIPHERTEXT_BLOCK_LENGTH 32U
143+
#define _PAD_INDICATOR_SIZE sizeof(uint16_t)
144144

145145
typedef enum padded_data_size_e {
146146
NO_PADDING = 0,
147+
BYTES_32 = 32 - _PAD_INDICATOR_SIZE,
148+
BYTES_64 = 64 - _PAD_INDICATOR_SIZE,
149+
BYTES_128 = 128 - _PAD_INDICATOR_SIZE,
150+
BYTES_256 = 256 - _PAD_INDICATOR_SIZE,
147151
BYTES_512 = 512 - _PAD_INDICATOR_SIZE
148152
} padded_data_size_t;
149153

@@ -155,7 +159,7 @@ namespace electionguard
155159
/// result. Create one with `hashedElgamalEncrypt`. Decrypt using one the
156160
/// 'decrypt' method.
157161
/// </summary>
158-
class EG_API HashedElGamalCiphertext : public CryptoHashable
162+
class EG_API HashedElGamalCiphertext
159163
{
160164
public:
161165
HashedElGamalCiphertext(const HashedElGamalCiphertext &other);
@@ -203,17 +207,14 @@ namespace electionguard
203207
/// </Summary>
204208
std::vector<uint8_t> getMac() const;
205209

206-
virtual std::unique_ptr<ElementModQ> crypto_hash() override;
207-
virtual std::unique_ptr<ElementModQ> crypto_hash() const override;
208-
209210
/// <summary>
210211
/// Decrypts ciphertext with the Auxiliary Encryption method (as specified in the
211212
/// ElectionGuard specification) given a random nonce, an ElGamal public key,
212213
/// and a description hash. The encrypt may be called to look for padding to
213214
/// verify and remove, in this case the plaintext will be smaller than
214215
/// the ciphertext, or not to look for padding in which case the
215-
/// plaintext will be the same size as the ciphertext.
216-
///
216+
/// plaintext will be the same size as the ciphertext.
217+
///
217218
/// <param name="nonce"> Randomly chosen nonce in [1,Q). </param>
218219
/// <param name="publicKey"> ElGamal public key. </param>
219220
/// <param name="descriptionHash"> Hash of the ballot description. </param>
@@ -231,7 +232,7 @@ namespace electionguard
231232
private:
232233
class Impl;
233234
#pragma warning(suppress : 4251)
234-
std::unique_ptr<Impl> pimpl;
235+
std::unique_ptr<Impl> pimpl;
235236
};
236237

237238
/// <summary>
@@ -243,32 +244,24 @@ namespace electionguard
243244
/// This value indicates the maximum length of the plaintext that may be
244245
/// encrypted. The padding scheme applies two bytes for length of padding
245246
/// plus padding bytes. If padding is not to be applied then the
246-
/// max_len parameter must be NO_PADDING. and the plaintext must
247+
/// max_len parameter must be NO_PADDING and the plaintext must
247248
/// be a multiple of the block length (32) and the ciphertext will be
248-
/// the same size. If the max_len is set to something other than
249-
/// NO_PADDING and the allow_truncation parameter is set to
250-
/// true then if the message parameter data is longer than
251-
/// max_len then it will be truncated to max_len. If the max_len is set to
252-
/// something other than NO_PADDING and the allow_truncation parameter
253-
/// is set to false then if the message parameter data is longer than
254-
/// max_len then an exception will be thrown.
249+
/// the same size.
255250
///
256-
/// <param name="message"> Message to hashed elgamal encrypt. </param>
251+
/// <param name="plaintext"> Message to hashed elgamal encrypt. </param>
257252
/// <param name="nonce"> Randomly chosen nonce in [1,Q). </param>
258253
/// <param name="publicKey"> ElGamal public key. </param>
259254
/// <param name="descriptionHash"> Hash of the ballot description. </param>
260255
/// <param name="max_len"> If padding is to be applied then this indicates the
261256
/// maximum length of plaintext, must be one padded_data_size_t enumeration
262257
/// values. If padding is not to be applied then this parameter must use
263258
/// the NO_PADDING padded_data_size_t enumeration value.</param>
264-
/// <param name="allow_truncation"> Truncates data to the max_len if set to
265-
/// true. If max_len is set to NO_PADDING then this parameter is ignored. </param>
266259
/// <returns>A ciphertext triple.</returns>
267260
/// </summary>
268261
EG_API std::unique_ptr<HashedElGamalCiphertext>
269262
hashedElgamalEncrypt(std::vector<uint8_t> plaintext, const ElementModQ &nonce,
270263
const ElementModP &publicKey, const ElementModQ &descriptionHash,
271-
padded_data_size_t max_len, bool allow_truncation);
264+
padded_data_size_t max_len);
272265

273266
} // namespace electionguard
274267

include/electionguard/encrypt.hpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -111,30 +111,14 @@ namespace electionguard
111111
const ElementModQ &cryptoExtendedBaseHash, const ElementModQ &nonceSeed,
112112
bool isPlaceholder = false, bool shouldVerifyProofs = true);
113113

114-
/// <summary>
115-
/// Gets overvote and write in information from the selections in a contest
116-
/// puts the information in a json string. The internalManifest is needed because
117-
/// it has the candidates and the candidate holds the indicator if a
118-
/// selection is a write in.
119-
///
120-
/// <param name="contest">the contest in valid input form</param>
121-
/// <param name="internalManifest">the `InternalManifest` which defines this ballot's structure</param>
122-
/// <param name="is_overvote">indicates if an overvote was detected</param>
123-
/// <returns>string holding the json with the write ins</returns>
124-
/// </summary>
125-
std::string getOvervoteAndWriteIns(const PlaintextBallotContest &contest,
126-
const InternalManifest &internalManifest,
127-
valid_contest_return is_overvote);
128-
129114
/// <summary>
130115
/// Encrypt a specific `BallotContest` in the context of a specific `Ballot`
131116
///
132117
/// This method accepts a contest representation that only includes `True` selections.
133118
/// It will fill missing selections for a contest with `False` values, and generate `placeholder`
134119
/// selections to represent the number of seats available for a given contest. By adding `placeholder`
135120
/// votes
136-
/// <param name="contest">the contest in valid input form</param>
137-
/// <param name="internalManifest">the `InternalManifest` which defines this ballot's structure</param>
121+
/// <param name="plaintext">the selection in the valid input form</param>
138122
/// <param name="description">the `ContestDescriptionWithPlaceholders` from the `ContestDescription`
139123
/// which defines this contest's structure</param>
140124
/// <param name="elgamalPublicKey">the public key (K) used to encrypt the ballot</param>
@@ -147,7 +131,6 @@ namespace electionguard
147131
/// </summary>
148132
EG_API std::unique_ptr<CiphertextBallotContest>
149133
encryptContest(const PlaintextBallotContest &contest,
150-
const InternalManifest &internalManifest,
151134
const ContestDescriptionWithPlaceholders &description,
152135
const ElementModP &elgamalPublicKey, const ElementModQ &cryptoExtendedBaseHash,
153136
const ElementModQ &nonceSeed, bool shouldVerifyProofs = true);

include/electionguard/group.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,6 @@ namespace electionguard
283283
/// </summary>
284284
EG_API std::unique_ptr<ElementModQ> rand_q();
285285

286-
std::string vector_uint8_t_to_hex(const std::vector<uint8_t> &bytes);
287-
288286
} // namespace electionguard
289287

290288
#endif /* __ELECTIONGUARD_CPP_GROUP_HPP_INCLUDED__ */

include/electionguard/hash.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ namespace electionguard
2222
std::vector<std::reference_wrapper<const CryptoHashable>>,
2323
std::vector<std::reference_wrapper<const ElementModP>>,
2424
std::vector<std::reference_wrapper<const ElementModQ>>, std::vector<uint64_t>,
25-
std::vector<std::string>,
26-
std::vector<uint8_t>>;
25+
std::vector<std::string>>;
2726

2827
/// <Summary>
2928
/// Given zero or more elements, calculate their cryptographic hash

include/electionguard/manifest.hpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,6 @@ namespace electionguard
971971
InternalManifest(InternalManifest &&other);
972972
explicit InternalManifest(
973973
std::vector<std::unique_ptr<GeopoliticalUnit>> geopoliticalUnits,
974-
std::vector<std::unique_ptr<Candidate>> candidates,
975974
std::vector<std::unique_ptr<ContestDescriptionWithPlaceholders>> contests,
976975
std::vector<std::unique_ptr<BallotStyle>> ballotStyles, const ElementModQ &manifestHash);
977976
InternalManifest(const Manifest &description);
@@ -990,11 +989,6 @@ namespace electionguard
990989
/// </Summary>
991990
std::vector<std::reference_wrapper<GeopoliticalUnit>> getGeopoliticalUnits() const;
992991

993-
/// <Summary>
994-
/// Collection of candidates for this election.
995-
/// </Summary>
996-
std::vector<std::reference_wrapper<Candidate>> getCandidates() const;
997-
998992
/// <Summary>
999993
/// Collection of contests for this election.
1000994
/// </Summary>
@@ -1058,9 +1052,6 @@ namespace electionguard
10581052
static std::vector<std::unique_ptr<GeopoliticalUnit>>
10591053
copyGeopoliticalUnits(const Manifest &description);
10601054

1061-
static std::vector<std::unique_ptr<Candidate>>
1062-
copyCandidates(const Manifest &description);
1063-
10641055
static std::vector<std::unique_ptr<BallotStyle>>
10651056
copyBallotStyles(const Manifest &description);
10661057

0 commit comments

Comments
 (0)