Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolved revoke ballot issue & added security fixes #53

Merged
merged 9 commits into from
Apr 12, 2022

Conversation

007vedant
Copy link
Collaborator

  • implemented passcode based encryption and decryption of ballots using PyNaCl
  • modified the casting vote workflow to resolve issue of revoke ballot being CPU intensive
  • modified the db schema to support the new workflow and encryption

- added voter.salt (largeBinary), voter.key(largeBinary) attributes to voter table.
- updated ballot.id and ballot.voter as GUID type
- added a custom GUID type
- modified custom GUID class to UUID class
- changed Voter.keys to Voter.ballot_ids(Longtext type)
- updated Ballot.id to default UUID field
- updated Ballot.voter to String field (holds str(uuid))
- modified elections_voting_page() to perform encryption on ballots with passcode
- modified elections_edit() to perform decryption on ballots or alert if wrong passcode
@007vedant 007vedant requested review from kalkayan and jberkus March 29, 2022 19:14
@jberkus
Copy link
Member

jberkus commented Mar 30, 2022

New code looks OK, am going to test it out.

Comment on lines 117 to 121
passcode = passcode.encode("utf-8")
kdf = pwhash.argon2i.kdf
salt = utils.random(pwhash.argon2i.SALTBYTES)
key = kdf(secret.SecretBox.KEY_SIZE, passcode, salt)
box = secret.SecretBox(key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this out to a utility or security module and call that over here, the general idea is to have slim controllers and fat services and to create abstractions. And move all the encoding/decodings to a separate module.

Comment on lines 166 to 170
# decrypting encrypted ballot ids
kdf = pwhash.argon2i.kdf
passcode = F.request.form["password"].encode("utf-8")
key = kdf(secret.SecretBox.KEY_SIZE, passcode, voter.salt)
box = secret.SecretBox(key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repeated code, creates inconsistency and possible bugs.

Comment on lines 140 to 142
voter.ballot_ids = json.dumps(
enc_ballot_ids
) # json serialized encrypted ballot ids
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jberkus can you take a look into this, @007vedant I think this is not what we want to do as per the discussion we had on slack

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we storing a UUID for the voter in the ballot.voter of all the votes and storing the encryption of that UUID in voter.encrypted_ballot instead of voter.ballot_ids?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kalkayan I'll do the required modifications as per our discussion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kalkayan modifications done as per the review via latest updates

- changed Voter.ballot_id to LargeBinary type (encrypted byte string)
- added encryption for ballot.voter in ballot_id attribute of Voter schema
- removed redundant code
- handles the encryption workflow in controllers/elections.py
- provides APIs for getting encrypted and decrypted strings
@007vedant
Copy link
Collaborator Author

  • performed encryption of ballot.voter (UUID) as per the latest review
  • updated voter.ballot_id to LargeBinary type. (stores encrypted byte string of ballot.voter.
  • added encryption.py module in elekto/middlewares to provide encryption/decryption APIs.
  • removed redundant code.

- moved encryption module to elekto/core
- updated exception handlign in decrypt()
@007vedant
Copy link
Collaborator Author

  • moved encryption module to elekto/core
  • added core exceptions in decrypt()

@jberkus
Copy link
Member

jberkus commented Apr 8, 2022

You need to add pynacl to requirements.txt

- stores UUID as stringified hex values
@007vedant
Copy link
Collaborator Author

  • modified UUID type which now force convert UUID to stringified hex values for postgres storage
  • added latest stable version of PyNaCl to requirements.txt

@jberkus
Copy link
Member

jberkus commented Apr 8, 2022

@kalkayan, wanna give your +1 here before we merge?

@kalkayan
Copy link
Member

kalkayan commented Apr 9, 2022

We can merge this @jberkus.

@jberkus jberkus merged commit cf9df83 into elekto-io:main Apr 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants