Skip to content

Commit cb0abb6

Browse files
authored
Merge pull request #144 from dedis/front-fix-encode
Fix the ballot encoding
2 parents b1048e0 + a11f9f1 commit cb0abb6

File tree

3 files changed

+25
-14
lines changed

3 files changed

+25
-14
lines changed

docs/ballot_encoding.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,14 @@ A possible encoding of an answer would be (by string concatenation):
4646
"text:cd13:base64("Noémien"),base64("Pierluca")\n"
4747
```
4848

49-
## Size of the ballot
49+
## Size of the ballot
5050

5151
In order to maintain complete voter anonymity and untraceability of ballots throughout the
5252
election process, it is important that all encrypted ballots have the same size. To this aim,
53-
the election has an attribute called "BallotSize" (multiple of 29) which is the size
53+
the election has an attribute called "BallotSize" which is the size
5454
that all ballots should have before they're encrypted. Smaller ballots should therefore be
5555
padded in order to reach this size. To denote the end of the ballot and the start of the padding,
56-
we use an empty line (\n\n). For a ballot size of 116, our ballot from the previous example
56+
we use an empty line (\n\n). For a ballot size of 117, our ballot from the previous example
5757
would then become:
5858

5959
```
@@ -63,5 +63,11 @@ would then become:
6363
6464
"text:cd13:base64("Noémien"),base64("Pierluca")\n\n" +
6565
66-
"ndtTx5uxmvnllH1T7NgLOREguUWbN"
66+
"ndtTx5uxmvnllH1T7NgLORuUWbN"
6767
```
68+
69+
## Chunks of ballot
70+
71+
The encoded ballot must then be divided into chunks of 29 or less bytes since the maximum size supported by the kyber library for the encryption is of 29 bytes.
72+
73+
For the previous example we would then have 5 chunks, the first 4 would contain 29 bytes, while the last chunk would contain a single byte.

web/frontend/src/pages/ballot/Show.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const Ballot: FC = () => {
2727

2828
const { electionId } = useParams();
2929
const UserID = sessionStorage.getItem('id');
30-
const { loading, configObj, electionID, status, pubKey, chunksPerBallot } =
30+
const { loading, configObj, electionID, status, pubKey, ballotSize, chunksPerBallot } =
3131
useElection(electionId);
3232
const { configuration, answers, setAnswers } = useConfiguration(configObj);
3333

@@ -75,7 +75,7 @@ const Ballot: FC = () => {
7575

7676
const sendBallot = async () => {
7777
try {
78-
const ballotChunks = voteEncode(answers, chunksPerBallot);
78+
const ballotChunks = voteEncode(answers, ballotSize, chunksPerBallot);
7979
const EGPairs = Array<Buffer[]>();
8080
ballotChunks.forEach((chunk) =>
8181
EGPairs.push(encryptVote(chunk, Buffer.from(hexToBytes(pubKey).buffer), edCurve))

web/frontend/src/pages/ballot/components/VoteEncode.tsx

+13-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { Buffer } from 'buffer';
22
import ShortUniqueId from 'short-unique-id';
33
import { Answers, RANK, SELECT, TEXT } from 'types/configuration';
44

5-
export function voteEncode(answers: Answers, chunksPerBallot: number): string[] {
5+
export function voteEncode(
6+
answers: Answers,
7+
ballotSize: number,
8+
chunksPerBallot: number
9+
): string[] {
610
// contains the special string representation of the result
711
let encodedBallot = '';
812

@@ -34,22 +38,23 @@ export function voteEncode(answers: Answers, chunksPerBallot: number): string[]
3438

3539
encodedBallot += '\n';
3640

37-
const chunkSize = 29;
38-
// ballot size
39-
const ballotSize = chunksPerBallot * chunkSize;
4041
const encodedBallotSize = Buffer.byteLength(encodedBallot);
4142

42-
// add padding if necessary
43+
// add padding if necessary until encodedBallot.length == ballotSize
4344
if (encodedBallotSize < ballotSize) {
4445
const padding = new ShortUniqueId({ length: ballotSize - encodedBallotSize });
4546
encodedBallot += padding();
4647
}
4748

49+
const chunkSize = 29;
4850
const ballotChunks: string[] = [];
4951

50-
// divide into chunks of 29 bytes, where 1 character === 1 byte
51-
for (let i = 0; i < ballotSize; i += chunkSize) {
52-
ballotChunks.push(encodedBallot.substring(i, i + chunkSize));
52+
// divide into chunksPerBallot chunks, where 1 character === 1 byte
53+
for (let i = 0; i < chunksPerBallot; i += 1) {
54+
const start = i * chunkSize;
55+
// substring(start, start + chunkSize), if (start + chunkSize) > string.length
56+
// then (start + chunkSize) is treated as if it was equal to string.length
57+
ballotChunks.push(encodedBallot.substring(start, start + chunkSize));
5358
}
5459

5560
return ballotChunks;

0 commit comments

Comments
 (0)