Skip to content

Commit e9dabb8

Browse files
committed
πŸ”‘ Key Generation and ElectionGuard Package Bump (#60)
* πŸ™ˆ Ignore code-workspaces for vs-code * ✨ Creation of Election and Auxiliary Keys - Add generation of keys - Add tests * πŸ†™ Upgrade to electionguard 1.1.3 - Upgrade to newest electionguard - Remove previous serialization logic in favor of base logic - πŸ“¦ Add `pytest` to dev packages
1 parent 55e8648 commit e9dabb8

File tree

10 files changed

+271
-56
lines changed

10 files changed

+271
-56
lines changed

β€Ž.gitignoreβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ dmypy.json
138138
cython_debug/
139139

140140
# VS Code
141-
*.local.json
141+
*.code-workspace
142142

143143
# Mac
144144
.DS_Store

β€ŽPipfileβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ black = "*"
88
mkdocs = "*"
99
mypy = "*"
1010
pylint = "*"
11+
pytest = "*"
1112

1213
[packages]
1314
electionguard = "*"

β€ŽPipfile.lockβ€Ž

Lines changed: 67 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€Žapp/api/v1/api.pyβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from fastapi import APIRouter
22

3-
from app.api.v1.endpoints import ballot, ping, election
3+
from app.api.v1.endpoints import ballot, election, key, ping
44

55
api_router = APIRouter()
66
api_router.include_router(ping.router, prefix="/ping", tags=["ping"])
77
api_router.include_router(election.router, prefix="/election", tags=["election"])
88
api_router.include_router(ballot.router, prefix="/ballot", tags=["ballot"])
9+
api_router.include_router(key.router, prefix="/key", tags=["key"])

β€Žapp/api/v1/endpoints/ballot.pyβ€Ž

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from fastapi import APIRouter, Body, HTTPException
1010
from pydantic import BaseModel
1111
from typing import Any
12-
from app.utils.serialize import write_json, write_json_object
1312

1413
router = APIRouter()
1514

@@ -31,7 +30,7 @@ def cast_ballot(request: AcceptBallotRequest = Body(...)) -> Any:
3130
status_code=500,
3231
detail="Ballot failed to be cast",
3332
)
34-
return write_json_object(cast_ballot)
33+
return cast_ballot.to_json_object()
3534

3635

3736
@router.post("/spoil")
@@ -45,14 +44,14 @@ def spoil_ballot(request: AcceptBallotRequest = Body(...)) -> Any:
4544
status_code=500,
4645
detail="Ballot failed to be spoiled",
4746
)
48-
return write_json_object(spoiled_ballot)
47+
return spoiled_ballot.to_json_object()
4948

5049

5150
def handle_ballot(request: AcceptBallotRequest, state: BallotBoxState) -> Any:
52-
ballot = CiphertextBallot.from_json(write_json(request.ballot))
53-
description = ElectionDescription.from_json(write_json(request.description))
51+
ballot = CiphertextBallot.from_json_object(request.ballot)
52+
description = ElectionDescription.from_json_object(request.description)
5453
internal_description = InternalElectionDescription(description)
55-
context = CiphertextElectionContext.from_json(write_json(request.context))
54+
context = CiphertextElectionContext.from_json_object(request.context)
5655

5756
accepted_ballot = accept_ballot(
5857
ballot,

β€Žapp/api/v1/endpoints/election.pyβ€Ž

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from fastapi import APIRouter, HTTPException
33
from os.path import realpath, join
44
from typing import Any
5-
from app.utils.serialize import write_json_object
6-
75

86
router = APIRouter()
97

@@ -18,7 +16,7 @@ def get_election_constants() -> Any:
1816
Return the constants defined for an election
1917
"""
2018
constants = ElectionConstants()
21-
return write_json_object(constants)
19+
return constants.to_json_object()
2220

2321

2422
@router.get("/description")

β€Žapp/api/v1/endpoints/key.pyβ€Ž

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from electionguard.key_ceremony import (
2+
generate_election_key_pair,
3+
generate_rsa_auxiliary_key_pair,
4+
)
5+
from electionguard.serializable import write_json_object
6+
from electionguard.group import int_to_q_unchecked
7+
from fastapi import APIRouter, HTTPException
8+
from pydantic import BaseModel
9+
from typing import Optional, Any
10+
11+
router = APIRouter()
12+
13+
14+
class ElectionKeyPairRequest(BaseModel):
15+
quorum: int
16+
nonce: Optional[str] = None
17+
18+
19+
class ElectionKeyPairResponse(BaseModel):
20+
secret_key: str
21+
public_key: str
22+
proof: Any
23+
polynomial: Any
24+
25+
26+
class AuxiliaryKeyPairResponse(BaseModel):
27+
secret_key: str
28+
public_key: str
29+
30+
31+
GuardianKeysRequest = ElectionKeyPairRequest
32+
33+
34+
class GuardianKeysResponse(BaseModel):
35+
election: ElectionKeyPairResponse
36+
auxiliary: AuxiliaryKeyPairResponse
37+
38+
39+
@router.post("/generate", response_model=GuardianKeysResponse)
40+
def generate_keys(request: GuardianKeysRequest) -> GuardianKeysResponse:
41+
"""
42+
Generate election key pairs for use in election process
43+
"""
44+
election_keys = generate_election_key_pair(
45+
request.quorum,
46+
int_to_q_unchecked(request.nonce) if request.nonce is not None else None,
47+
)
48+
auxiliary_keys = generate_rsa_auxiliary_key_pair()
49+
if not election_keys:
50+
raise HTTPException(
51+
status_code=500,
52+
detail="Election keys failed to be generated",
53+
)
54+
if not auxiliary_keys:
55+
raise HTTPException(
56+
status_code=500, detail="Auxiliary keys failed to be generated"
57+
)
58+
return GuardianKeysResponse(
59+
election=ElectionKeyPairResponse(
60+
public_key=str(election_keys.key_pair.public_key),
61+
secret_key=str(election_keys.key_pair.secret_key),
62+
proof=write_json_object(election_keys.proof),
63+
polynomial=write_json_object(election_keys.polynomial),
64+
),
65+
auxiliary=AuxiliaryKeyPairResponse(
66+
public_key=auxiliary_keys.public_key, secret_key=auxiliary_keys.secret_key
67+
),
68+
)
69+
70+
71+
@router.post("/election/generate", response_model=ElectionKeyPairResponse)
72+
def generate_election_keys(request: ElectionKeyPairRequest) -> ElectionKeyPairResponse:
73+
"""
74+
Generate election key pairs for use in election process
75+
"""
76+
keys = generate_election_key_pair(
77+
request.quorum,
78+
int_to_q_unchecked(request.nonce) if request.nonce is not None else None,
79+
)
80+
if not keys:
81+
raise HTTPException(
82+
status_code=500,
83+
detail="Election keys failed to be generated",
84+
)
85+
return ElectionKeyPairResponse(
86+
public_key=str(keys.key_pair.public_key),
87+
secret_key=str(keys.key_pair.secret_key),
88+
proof=write_json_object(keys.proof),
89+
polynomial=write_json_object(keys.polynomial),
90+
)
91+
92+
93+
@router.post("/auxiliary/generate", response_model=AuxiliaryKeyPairResponse)
94+
def generate_auxiliary_keys() -> AuxiliaryKeyPairResponse:
95+
"""
96+
Generate auxiliary key pair for auxiliary uses during process
97+
"""
98+
keys = generate_rsa_auxiliary_key_pair()
99+
if not keys:
100+
raise HTTPException(
101+
status_code=500, detail="Auxiliary keys failed to be generated"
102+
)
103+
return AuxiliaryKeyPairResponse(
104+
public_key=keys.public_key, secret_key=keys.secret_key
105+
)

β€Žapp/utils/__init__.pyβ€Ž

Whitespace-only changes.

β€Žapp/utils/serialize.pyβ€Ž

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
Β (0)