From aacf5b2ae01c54733293c6ea9efd8acd37245497 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Wed, 3 Apr 2024 23:25:28 +0000 Subject: [PATCH] build based on 7fbe8ac --- dev/.documenter-siteinfo.json | 2 +- dev/assets/registration_sequence/index.html | 2 +- dev/audit/index.html | 2 +- dev/audittools/index.html | 2 +- dev/client/index.html | 2 +- dev/controllers/index.html | 10 ++-- dev/index.html | 2 +- dev/model/index.html | 56 ++++++++++----------- dev/overview/index.html | 2 +- dev/schedulers/index.html | 4 +- dev/schema/index.html | 2 +- dev/setup/index.html | 2 +- 12 files changed, 44 insertions(+), 44 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index f3bd4be..4fc396c 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-04-01T22:27:33","documenter_version":"1.3.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.2","generation_timestamp":"2024-04-03T23:25:23","documenter_version":"1.3.0"}} \ No newline at end of file diff --git a/dev/assets/registration_sequence/index.html b/dev/assets/registration_sequence/index.html index d65f9cb..58dae16 100644 --- a/dev/assets/registration_sequence/index.html +++ b/dev/assets/registration_sequence/index.html @@ -10,4 +10,4 @@ Client ->> PeaceFounder: {ticket_id, member_id}_token PeaceFounder ->> Client: {member_id}_registrar Client ->> PeaceFounder: {pseudonym}_member - PeaceFounder ->> Client: inclusion_proof, {chain_state}_recorder + PeaceFounder ->> Client: inclusion_proof, {chain_state}_recorder diff --git a/dev/audit/index.html b/dev/audit/index.html index 0b9df5e..900d8c7 100644 --- a/dev/audit/index.html +++ b/dev/audit/index.html @@ -16,4 +16,4 @@ @test checksum(ballotbox_archive, hasher) == ledger_root @test audit(braidchain_archive, ballotbox_archive, hasher) -@show tally(ballotbox_archive)

Note that this audit does not check the honesty of the registrar and that it has not admitted fake users to gain more influence in the election result. Properties being verified by the audit:

All these properties together ensure software independence so that the resulting tally does not depend on trust in the honest execution of either peacefounder service or braiders. In other words, the previously listed properties would not be altered if the adversary had full control over the peacefounder service and the braiders.

The immutability is ensured by voter's clients updating their consistency proof chain, which includes their vote. If the vote gets removed from a chain, every voter who cast their vote will get proof for an inconsistent ledger state called blame. The voter can make the blame public without revealing their vote, thus ensuring immutability and persistence after votes are published. The auditable part here is the votes signed with a pseudonym, which contract voters' clients to follow up at later periods with consistency proofs. On top of that, other monitors can synchronise the ballotbox ledger and add assurances that way.

+@show tally(ballotbox_archive)

Note that this audit does not check the honesty of the registrar and that it has not admitted fake users to gain more influence in the election result. Properties being verified by the audit:

All these properties together ensure software independence so that the resulting tally does not depend on trust in the honest execution of either peacefounder service or braiders. In other words, the previously listed properties would not be altered if the adversary had full control over the peacefounder service and the braiders.

The immutability is ensured by voter's clients updating their consistency proof chain, which includes their vote. If the vote gets removed from a chain, every voter who cast their vote will get proof for an inconsistent ledger state called blame. The voter can make the blame public without revealing their vote, thus ensuring immutability and persistence after votes are published. The auditable part here is the votes signed with a pseudonym, which contract voters' clients to follow up at later periods with consistency proofs. On top of that, other monitors can synchronise the ballotbox ledger and add assurances that way.

diff --git a/dev/audittools/index.html b/dev/audittools/index.html index e3ed309..8c2494f 100644 --- a/dev/audittools/index.html +++ b/dev/audittools/index.html @@ -19,4 +19,4 @@ isbinding(chain::BraidChainLedger, bbox::BraidChainLedger) audit(chain::BraidChainLedger, bbox::BallotBoxLedger, commit::Commit{BallotBoxState}) -audit(chain::BraidChainLedger, bbox::BallotBoxLedger, root::Digest, N::Int = length(bbox))

Note that this audit does not check honesty of the registrar that it have admitted fake users to gain more influence in the ellection result. Properties being verified by the audit:

depend on a trust in honest execution of peacefounder service nor honesty of the braiders who provides new pseudonyms for the deme members. In other words the previously listed properties would not be altered if adversary would have a full control over the peacefounder service and the braiders.

The immutability is ensured from voter's clients updating their consistency proof chain which includes their vote. If the vote gets removed from a chain every single voter who had cast their vote would get a proof for inconsistent ledger state called blame. The blame can be made public by the voter without revealing it's vote and thus ensures immutability and also persitance after votes are published. The auditable part here are the votes themselves signed with pseudonym which contract voter's clients to follow up at latter periods with consistency proofs. On top of that, other monitors can synchronize the ballotbox ledger and add assurances that way.

source +audit(chain::BraidChainLedger, bbox::BallotBoxLedger, root::Digest, N::Int = length(bbox))

Note that this audit does not check honesty of the registrar that it have admitted fake users to gain more influence in the ellection result. Properties being verified by the audit:

depend on a trust in honest execution of peacefounder service nor honesty of the braiders who provides new pseudonyms for the deme members. In other words the previously listed properties would not be altered if adversary would have a full control over the peacefounder service and the braiders.

The immutability is ensured from voter's clients updating their consistency proof chain which includes their vote. If the vote gets removed from a chain every single voter who had cast their vote would get a proof for inconsistent ledger state called blame. The blame can be made public by the voter without revealing it's vote and thus ensures immutability and also persitance after votes are published. The auditable part here are the votes themselves signed with pseudonym which contract voter's clients to follow up at latter periods with consistency proofs. On top of that, other monitors can synchronize the ballotbox ledger and add assurances that way.

source diff --git a/dev/client/index.html b/dev/client/index.html index 151fc11..68d7ead 100644 --- a/dev/client/index.html +++ b/dev/client/index.html @@ -8,4 +8,4 @@

When a voter enters the proposal within the specified time window, it can go to ballot view by pressing Vote Now. The ballot view depends on the kind of Ballot used in the proposal. Since the votes are plaintext messages signed with pseudonyms, there are unlimited types of ballots that PeaceFounder can support, like - cardinal, preferential or budget-constrained ballots, some of which are planned to be implemented in the future.

A guard report is shown to the voter when the vote is cast. The guard contains three categories:

Left: a view for multiple question ballot. Right: a guard view where the voter sees ballot box identifier, a receipt for casting a vote and a commit of the current state of the ballot box.
-

The Merkle tree inclusion and consistency proof as a receipt to make a tamper-resistant bulletin board monitored by voters. So that undesirable votes can not be discarded when they have been recorded.

After the elections, each voter's client device checks whether the last cast vote is included in the final tally, together with a sequence number on the vote that prevents an adversary that has obtained the voter's private key from casting votes on voters' behalf without being noticed. This is done automatically as long as the client's device acts honestly, i.e., is not infected with malware.

In the case of malware, the fairness property maintained by the election authority and a timestamp on the casting receipt prevent malware on the voter's client from pointing to a substitute vote. Whereas the vote is cast as intended and counted as cast (important for revoting), a voter can check on the bulletin board with another computer using the receipt. If the malware is detected, the voter takes appropriate action for his device.

+

The Merkle tree inclusion and consistency proof as a receipt to make a tamper-resistant bulletin board monitored by voters. So that undesirable votes can not be discarded when they have been recorded.

After the elections, each voter's client device checks whether the last cast vote is included in the final tally, together with a sequence number on the vote that prevents an adversary that has obtained the voter's private key from casting votes on voters' behalf without being noticed. This is done automatically as long as the client's device acts honestly, i.e., is not infected with malware.

In the case of malware, the fairness property maintained by the election authority and a timestamp on the casting receipt prevent malware on the voter's client from pointing to a substitute vote. Whereas the vote is cast as intended and counted as cast (important for revoting), a voter can check on the bulletin board with another computer using the receipt. If the malware is detected, the voter takes appropriate action for his device.

diff --git a/dev/controllers/index.html b/dev/controllers/index.html index 6b7b906..c3768cc 100644 --- a/dev/controllers/index.html +++ b/dev/controllers/index.html @@ -4,21 +4,21 @@ tickets::Vector{Ticket} signer::Signer hmac::HMAC -end

Represents a state for token registrar service. To initialize the service it's necessary to create a signer who can issue a valid admisssion certificates and a secret key with which a recruit client can exchange authorized messages. See also method generate(Registrar, spec).

Metadata is used as means to securelly deliver to the client most recent server specification.

Interface: select, hmac, hasher, key, id, tickets, in, enlist!, admit!, isadmitted, ticket_status

source
PeaceFounder.Server.Controllers.TicketType
mutable struct Ticket
+end

Represents a state for token registrar service. To initialize the service it's necessary to create a signer who can issue a valid admisssion certificates and a secret key with which a recruit client can exchange authorized messages. See also method generate(Registrar, spec).

Metadata is used as means to securelly deliver to the client most recent server specification.

Interface: select, hmac, hasher, key, id, tickets, in, enlist!, admit!, isadmitted, ticket_status

source
PeaceFounder.Server.Controllers.TicketType
mutable struct Ticket
     const ticketid::TicketID
     timestamp::DateTime
     attempt::UInt8
     token::Digest
     tokenid::String # 
     admission::Union{Admission, Nothing}
-end

Represents a ticket state for ticket with ticketid. timestamp represents time when the ticket have been issued by a registrar client in authorization system of choice, for instance, Registrars.jl; attempt is a counter with which token can be reset which is calculated with token(ticketid, attempt, hmac). Lastly admission contains a certified member pseudonym which was authetificated by the user with token.

source
Base.inMethod
in(ticketid::TicketID, registrar::Registrar)::Bool

Return true if there already is a ticket with ticketid.

source
PeaceFounder.Core.Model.generateMethod
generate(Registrar, spec::CryptoSpec)

Generate a new token registrar with unique signer and athorization key.

source
PeaceFounder.Core.Model.selectMethod
select(Admission, ticketid::TicketID, registrar::Registrar)::Union{Admission, Nothing}

Return admission for a ticket with given a given identity pseudonym from registrar. If no ticket with given id is found OR ticket is not yet admitted returns nothing.

source
PeaceFounder.Core.Model.selectMethod
select(Admission, ticketid::TicketID, registrar::Registrar)::Union{Admission, Nothing}

Return admission for a ticket with given ticketid from registrar. If no ticket with given ticketid is found OR ticket is not yet admitted returns nothing.

source
PeaceFounder.Core.Model.selectMethod
select(T, predicate::Function, registrar::Registrar)::Union{T, Nothing}

From a list of all registrar tickets return T <: Union{Ticket, Admission} for which predicate is true. If none succeds returns nothing.

source
PeaceFounder.Core.ProtocolSchema.isadmittedMethod
isadmitted(ticketid::TicketID, registrar::Registrar)

Check whether a ticket is already admitted. Returns false when either ticket is nonexistent or it's admission is nothing.

source
PeaceFounder.Server.Controllers.admit!Method
admit!(registrar::Registrar, id::Pseudonym, ticketid::TicketID)::Admission

Attempt to admit an identity pseudonym id for ticket ticketid. Authorization is expected to happen at the service layer using provided token in the invite. If a ticket is already registered return admission if it matches the provided id. Otherwise throe an error.

source
PeaceFounder.Server.Controllers.enlist!Method
enlist!(registrar::Registrar, ticketid::TicketID, timestamp::DateTime; route::URI=registrar.route)::Invite

Registers a new ticket with given TicketID and returns an invite. If ticket is already registered the same invite is returned. Throws an error when ticket is already registered.

source
PeaceFounder.Server.Controllers.hmacMethod
hmac(x)::HMAC

Return HMAC authorizer from a given object.

source
PeaceFounder.Server.Controllers.set_demehash!Method
set_demespec!(registrar::Registrar, spec::Union{Digest, DemeSpec})

Replace metadata for a registrar. Note when data is replaced all unfinalized tokens need to be flushed.

source
PeaceFounder.Server.Controllers.ticket_statusMethod
ticket_status(ticketid::TicketID, registrar::Registrar)::Union{TicketStatus, Nothing}

Return a ticket status for a ticketid. In case ticket is not found return nothing.

source
PeaceFounder.Server.Controllers.ticketsMethod
tickets(registrar::Registrar)::Vector{TicketID}

Return a list of registered ticket ids.

source
PeaceFounder.Server.Controllers.tokenMethod
token(ticketid::TicketID, hmac::HMAC)

Compute a recruit token for a given ticketid. Calculates it as token=Hash(Hash(0|key)|attempt|ticketid) where attempt is a counter for which token is issued.

Note: the token generation from key is made in order to support it's local computation on a remote server where QR code for registration is shown within organization website.

source

BraidChain

PeaceFounder.Server.Controllers.BraidChainControllerType
struct BraidChain
+end

Represents a ticket state for ticket with ticketid. timestamp represents time when the ticket have been issued by a registrar client in authorization system of choice, for instance, Registrars.jl; attempt is a counter with which token can be reset which is calculated with token(ticketid, attempt, hmac). Lastly admission contains a certified member pseudonym which was authetificated by the user with token.

source
Base.inMethod
in(ticketid::TicketID, registrar::Registrar)::Bool

Return true if there already is a ticket with ticketid.

source
PeaceFounder.Core.Model.generateMethod
generate(Registrar, spec::CryptoSpec)

Generate a new token registrar with unique signer and athorization key.

source
PeaceFounder.Core.Model.selectMethod
select(Admission, ticketid::TicketID, registrar::Registrar)::Union{Admission, Nothing}

Return admission for a ticket with given a given identity pseudonym from registrar. If no ticket with given id is found OR ticket is not yet admitted returns nothing.

source
PeaceFounder.Core.Model.selectMethod
select(Admission, ticketid::TicketID, registrar::Registrar)::Union{Admission, Nothing}

Return admission for a ticket with given ticketid from registrar. If no ticket with given ticketid is found OR ticket is not yet admitted returns nothing.

source
PeaceFounder.Core.Model.selectMethod
select(T, predicate::Function, registrar::Registrar)::Union{T, Nothing}

From a list of all registrar tickets return T <: Union{Ticket, Admission} for which predicate is true. If none succeds returns nothing.

source
PeaceFounder.Core.ProtocolSchema.isadmittedMethod
isadmitted(ticketid::TicketID, registrar::Registrar)

Check whether a ticket is already admitted. Returns false when either ticket is nonexistent or it's admission is nothing.

source
PeaceFounder.Server.Controllers.admit!Method
admit!(registrar::Registrar, id::Pseudonym, ticketid::TicketID)::Admission

Attempt to admit an identity pseudonym id for ticket ticketid. Authorization is expected to happen at the service layer using provided token in the invite. If a ticket is already registered return admission if it matches the provided id. Otherwise throe an error.

source
PeaceFounder.Server.Controllers.enlist!Method
enlist!(registrar::Registrar, ticketid::TicketID, timestamp::DateTime; route::URI=registrar.route)::Invite

Registers a new ticket with given TicketID and returns an invite. If ticket is already registered the same invite is returned. Throws an error when ticket is already registered.

source
PeaceFounder.Server.Controllers.hmacMethod
hmac(x)::HMAC

Return HMAC authorizer from a given object.

source
PeaceFounder.Server.Controllers.set_demehash!Method
set_demespec!(registrar::Registrar, spec::Union{Digest, DemeSpec})

Replace metadata for a registrar. Note when data is replaced all unfinalized tokens need to be flushed.

source
PeaceFounder.Server.Controllers.ticket_statusMethod
ticket_status(ticketid::TicketID, registrar::Registrar)::Union{TicketStatus, Nothing}

Return a ticket status for a ticketid. In case ticket is not found return nothing.

source
PeaceFounder.Server.Controllers.ticketsMethod
tickets(registrar::Registrar)::Vector{TicketID}

Return a list of registered ticket ids.

source
PeaceFounder.Server.Controllers.tokenMethod
token(ticketid::TicketID, hmac::HMAC)

Compute a recruit token for a given ticketid. Calculates it as token=Hash(Hash(0|key)|attempt|ticketid) where attempt is a counter for which token is issued.

Note: the token generation from key is made in order to support it's local computation on a remote server where QR code for registration is shown within organization website.

source

BraidChain

PeaceFounder.Server.Controllers.BraidChainControllerType
struct BraidChain
     members::Set{Pseudonym}
     ledger::BraidChainLedger
     spec::DemeSpec
     generator::Generator
     tree::HistoryTree
     commit::Union{Commit{ChainState}, Nothing}
-end

Represents a braidchain ledger with it's associated state. Can be instantitated with a demespec file using BraidChain(::DemeSpec) method.

Interface: push!, record!, state, length, list, select, roll, constituents, generator, commit, commit_index, ledger, leaf, root, ack_leaf, ack_root, members, commit!

source
Base.push!Method
push!(ledger::BraidChainController, t::Transaction)

Add an element to the BraidChainController bypassing transaction verification with the chain. This should only be used when the ledger is loaded from a trusted source like a local disk or when final root hash is validated with a trusted source.

source
HistoryTrees.leafMethod
leaf(ledger::BraidChainController, N::Int)::Digest

Return a ledger's element digest at given index.

source
HistoryTrees.rootMethod
root(ledger::BraidChainController[, N::Int])::Digest

Return a ledger root digest. In case when index is not given a current index is used.

source
PeaceFounder.Core.Model.commitMethod
commit(ledger::BraidChainController)

Return a current commit for a braichain.

source
PeaceFounder.Core.Model.generatorMethod
generator(ledger[, index])

Return a generator at braidchain ledger row index. If index is omitted return the current state value.

source
PeaceFounder.Core.Model.generatorMethod
generator(ledger::BraidChainController)

Return a current relative generator for a braidchain ledger.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(chain::BraidChainController, state::ChainState)::Bool

Check that chain state is consistent with braidchain ledger.

source
PeaceFounder.Core.Model.membersMethod
members(chain::BraidChainController, [n::Int])::Set

Return a set of member pseudonyms which at given anchor index can participate in voting or braiding.

source
PeaceFounder.Core.Model.selectMethod
select(T, predicate::Function, ledger::BraidChainController)::Union{T, Nothing}

Return a first element from a ledger with a type T which satisfies a predicate.

source
PeaceFounder.Core.Model.stateMethod
state(ledger::BraidChainController)

Return a current braidchain ledger state metadata.

source
PeaceFounder.Server.Controllers.ack_leafMethod
ack_leaf(ledger::BraidChainController, index::Int)::AckInclusion

Return a proof for record inclusion with respect to a current braidchain ledger history tree root.

source
PeaceFounder.Server.Controllers.ack_rootMethod
ack_root(ledger::BraidChainController, index::Int)

Return a proof for the ledger root at given index with respect to the current braidchain ledger history tree root.

source
PeaceFounder.Server.Controllers.commit!Method
commit!(ledger::BraidChainController, signer::Signer)

Commit a current braidchain ledger state with a signer's issued cryptographic signature.

source
PeaceFounder.Server.Controllers.constituentsMethod
constituents(ledger::BraidChainController)::Set{Pseudonym}

Return all member identity pseudonyms.

source
PeaceFounder.Server.Controllers.listMethod
list(T, ledger::BraidChainController)::Vector{Tuple{Int, T}}

List braidchain elements with a given type together with their index.

source
PeaceFounder.Server.Controllers.reset_tree!Method
reset_tree!(ledger::BraidChainController)

Recompute a chain tree hash.

source
PeaceFounder.Server.Controllers.rollMethod
roll(ledger::BraidChainController)::Vector{Membership}

Return all member certificates from a braidchain ledger.

source

BallotBox and PollingStation

PeaceFounder.Server.Controllers.BallotBoxControllerType
mutable struct BallotBoxController
+end

Represents a braidchain ledger with it's associated state. Can be instantitated with a demespec file using BraidChain(::DemeSpec) method.

Interface: push!, record!, state, length, list, select, roll, constituents, generator, commit, commit_index, ledger, leaf, root, ack_leaf, ack_root, members, commit!

source
Base.push!Method
push!(ledger::BraidChainController, t::Transaction)

Add an element to the BraidChainController bypassing transaction verification with the chain. This should only be used when the ledger is loaded from a trusted source like a local disk or when final root hash is validated with a trusted source.

source
HistoryTrees.leafMethod
leaf(ledger::BraidChainController, N::Int)::Digest

Return a ledger's element digest at given index.

source
HistoryTrees.rootMethod
root(ledger::BraidChainController[, N::Int])::Digest

Return a ledger root digest. In case when index is not given a current index is used.

source
PeaceFounder.Core.Model.commitMethod
commit(ledger::BraidChainController)

Return a current commit for a braichain.

source
PeaceFounder.Core.Model.generatorMethod
generator(ledger[, index])

Return a generator at braidchain ledger row index. If index is omitted return the current state value.

source
PeaceFounder.Core.Model.generatorMethod
generator(ledger::BraidChainController)

Return a current relative generator for a braidchain ledger.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(chain::BraidChainController, state::ChainState)::Bool

Check that chain state is consistent with braidchain ledger.

source
PeaceFounder.Core.Model.membersMethod
members(chain::BraidChainController, [n::Int])::Set

Return a set of member pseudonyms which at given anchor index can participate in voting or braiding.

source
PeaceFounder.Core.Model.selectMethod
select(T, predicate::Function, ledger::BraidChainController)::Union{T, Nothing}

Return a first element from a ledger with a type T which satisfies a predicate.

source
PeaceFounder.Core.Model.stateMethod
state(ledger::BraidChainController)

Return a current braidchain ledger state metadata.

source
PeaceFounder.Server.Controllers.ack_leafMethod
ack_leaf(ledger::BraidChainController, index::Int)::AckInclusion

Return a proof for record inclusion with respect to a current braidchain ledger history tree root.

source
PeaceFounder.Server.Controllers.ack_rootMethod
ack_root(ledger::BraidChainController, index::Int)

Return a proof for the ledger root at given index with respect to the current braidchain ledger history tree root.

source
PeaceFounder.Server.Controllers.commit!Method
commit!(ledger::BraidChainController, signer::Signer)

Commit a current braidchain ledger state with a signer's issued cryptographic signature.

source
PeaceFounder.Server.Controllers.constituentsMethod
constituents(ledger::BraidChainController)::Set{Pseudonym}

Return all member identity pseudonyms.

source
PeaceFounder.Server.Controllers.listMethod
list(T, ledger::BraidChainController)::Vector{Tuple{Int, T}}

List braidchain elements with a given type together with their index.

source
PeaceFounder.Server.Controllers.reset_tree!Method
reset_tree!(ledger::BraidChainController)

Recompute a chain tree hash.

source
PeaceFounder.Server.Controllers.rollMethod
roll(ledger::BraidChainController)::Vector{Membership}

Return all member certificates from a braidchain ledger.

source

BallotBox and PollingStation

PeaceFounder.Server.Controllers.BallotBoxControllerType
mutable struct BallotBoxController
     ledger::BallotBoxLedger
     voters::Set{Pseudonym} # better than members
     collector::Pseudonym
@@ -26,7 +26,7 @@
     queue::Vector{Vote}
     tree::HistoryTree
     commit::Union{Commit{BallotBoxState}, Nothing}
-end

Represents a ballot box for a proposal. Contains proposal, a set of eligiable voters a collector who collects the votes and a seed which is selected at random when the voting starts. queue contains a list of valid votes which yet to be comitted to a ledger. A history tree is built on leafs of ledger's receipts (see a receipt method). A commit contains a collector seal on the current ballotbox state.

Interface: reset_tree!, generator, uuid, ledger, spine, index, seed, leaf, root, receipt, commit, tally, set_seed!, ack_leaf, ack_root, ack_cast, commit_index, commit_state, push!, state, validate, record!, commit!

source
PeaceFounder.Server.Controllers.PollingStationType
struct PollingStation
+end

Represents a ballot box for a proposal. Contains proposal, a set of eligiable voters a collector who collects the votes and a seed which is selected at random when the voting starts. queue contains a list of valid votes which yet to be comitted to a ledger. A history tree is built on leafs of ledger's receipts (see a receipt method). A commit contains a collector seal on the current ballotbox state.

Interface: reset_tree!, generator, uuid, ledger, spine, index, seed, leaf, root, receipt, commit, tally, set_seed!, ack_leaf, ack_root, ack_cast, commit_index, commit_state, push!, state, validate, record!, commit!

source
PeaceFounder.Server.Controllers.PollingStationType
struct PollingStation
     halls::Vector{BallotBoxController}
     crypto::CryptoSpec
-end

Represents a pooling station which hosts ballotbox ledgers for every proposal collector manages.

Interface: init!, record!, commit!, commit, ack_leaf, ack_root, ack_cast, receipt, spine, ledger, tally, set_seed!

source
Base.getMethod
get(station::PollingStation, uuid::UUID)::BallotBoxController

Return a ballotbox ledger with a provided UUID. If none is found throws an error.

source
Base.getMethod
get(station::PollingStation, proposal::Digest)::BallotBoxController

Return a ballotbox which has proposal with provided digest.

source
Base.getindexMethod
getindex(ledger::BallotBoxController, index::Int)::CastRecord

Return a ledger record at provided index.

source
Base.lengthMethod
length(ledger::BallotBoxController)

Return a total length of the ledger including uncommited records in the queue.

source
Base.push!Method
push!(ledger::BallotBoxController, record::CastRecord)

Push a record to the ledger bypassing integrity checks. Used when loading the ledger from a trusted source such as local disk or an archive with a signed root cheksum.

source
HistoryTrees.leafMethod
leaf(ledger::BallotBoxController, N::Int)::Digest

Return a record digest used to form a history tree.

source
HistoryTrees.rootMethod
root(ledger::BallotBoxController[, N::Int])::Digest

Calculate a root for history tree at given index N. If index is not specified returns the current value.

source
PeaceFounder.Core.Model.commitMethod
commit(ledger::BallotBoxController)

Return a commit for the ballotbox ledger.

source
PeaceFounder.Core.Model.commitMethod
commit(station::PollingStation, uuid::UUID)::Commit

Return a ballotbox commit.

source
PeaceFounder.Core.Model.generatorMethod
generator(ledger::BallotBoxController)

Return a relative generator which members use to sign votes anchored by the proposal.

source
PeaceFounder.Core.Model.indexMethod
index(ledger::BallotBoxController)

Return the current index of the ledger. See also length.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(vote::Vote, ack::CastAck, hasher)

Check whether acknowledgment is bound to the provided vote.

source
PeaceFounder.Core.Model.receiptMethod
receipt(ledger::BallotBoxController, index::Int)::CastReceipt

Return a receipt for a ledger element.

source
PeaceFounder.Core.Model.receiptMethod
receipt(station::PollingStation, uuid::UUID, N::Int)::CastReceipt

Return a receipt for a record with index N at ballotbox with uuid.

source
PeaceFounder.Core.Model.seedMethod
seed(ledger::BallotBoxController)::Union{Digest, Nothing}

Return a random selected seed used in the voting.

source
PeaceFounder.Core.Model.tallyMethod
tally(station::PollingStation, uuid::UUID)

Compute a tally from ledger records a ballotbox with uuid.

source
PeaceFounder.Core.Model.uuidMethod
uuid(ledger::BallotBoxController)

Return a UUID of the proposal.

source
PeaceFounder.Core.Model.votersMethod
voters(ledger::BallotBoxController)

Return a list of member pseudonyms with which members authetificate their votes.

source
PeaceFounder.Server.Controllers.ack_castMethod
ack_cast(ledger::BallotBoxController, index::Int)::CastAck

Compute an acknowledgment for record inclusion at index.

source
PeaceFounder.Server.Controllers.ack_castMethod
ack_cast(station::PollingStation, uuid::UUID, N::Int)::CastAck

Return inclusion proof with receipt and current tree commit for a leaf at index N and ballotbox with uuid.

source
PeaceFounder.Server.Controllers.ack_leafMethod
ack_leaf(ledger::BallotBoxController, index::Int)::AckInclusion

Compute an inclusion proof ::AckInclusion for record element at given index.

source
PeaceFounder.Server.Controllers.ack_leafMethod
ack_leaf(station::PollingStation, uuid::UUID, N::Int)::AckInclusion

Return history tree inclusion proof for a tree leaf at index N in ballotbox with uuid.

source
PeaceFounder.Server.Controllers.ack_rootMethod
ack_root(ledger::BallotBoxController, index::Int)::AckConsistency

Compute a history tree consistency proof at index.

source
PeaceFounder.Server.Controllers.ack_rootMethod
ack_root(station::PollingStation, uuid::UUID, N::Int)::AckConsistency

Return history tree consitency proof tree root at index N in ballotbox with uuid.

source
PeaceFounder.Server.Controllers.commit!Method
commit!(ledger::BallotBoxController[, timestamp::DataTime], signer::Signer; with_tally=nothing)

Flushes ballotbox ledger's queue and creates a commit for a current ballotbox ledger state with provided timestamp and signer. A keyword argument with_tally has three values true|false to include or exclude a tally from a commited state and nothing which uses a previous commit preference.

source
PeaceFounder.Server.Controllers.commit!Method
commit!(station::PollingStation, uuid::UUID, collector::Signer; with_tally = nothing)

Select a ballotbox with provided uuid and commit it's state with collector.

source
PeaceFounder.Server.Controllers.commit_indexMethod
commit_index(ledger::BallotBoxController)::Union{Index, Nothing}

Index at which commit is issued. See also length and index

source
PeaceFounder.Server.Controllers.commit_stateMethod
commit_state(ledger::BallotBoxController)

Return a committed state for a ballotbox ledger.

source
PeaceFounder.Server.Controllers.init!Method
init!(station::PollingStation, proposal::Proposal, voters::Set{Pseudonym}[, collector::Pseudonym])

Creates a new ballotbox for given proposal with provided member pseudonyms at a relative generator anchored in the proposal. A collector is optional and provided only when it differs from one specified in the proposal.

source
PeaceFounder.Server.Controllers.ledgerMethod
ledger(ballotbox::BallotBoxController)::Vector{CastRecord}

Return all records from a ballotbox ledger.

source
PeaceFounder.Server.Controllers.ledgerMethod
ledger(station::PollingStation, uuid::UUID)::Vector{CastRecord}

Return a vector of records from a ballotbox with uuid.

source
PeaceFounder.Server.Controllers.record!Method
record!(ledger::BallotBoxController, record::CastRecord)

Check the vote in the record for validity and include that in the ledger directly bypassing queue. This method is useful for replaying and debugging ballotbox ledger state changes. See also record!

source
PeaceFounder.Server.Controllers.record!Method
record!(ledger::BallotBoxController, vote::Vote)

Check the vote for validity and pushes it to the queue. Returns an index N at which the vote will be recorded in the ledger. See also push!

source
PeaceFounder.Server.Controllers.record!Method
record!(station::PollingStation, uuid::UUID, vote::Vote)::Int

Records a vote in a ballotbox with provided proposal UUID. Throws an error if a ballotbox can't be found.

source
PeaceFounder.Server.Controllers.record!Method
record!(station::PollingStation, uuid::UUID, vote::Vote)::Int

Record a vote in a ballotbox found by proposal diggest stored in the vote. Throws an error if a ballotbox can't be found.

source
PeaceFounder.Server.Controllers.reset_tree!Method
reset_tree!(ledger::BallotBoxController)

Recompute history tree root and cache from the elements in the ledger. This is a useful for loading the ledger all at once.

source
PeaceFounder.Server.Controllers.set_seed!Method
set_seed!(ledger::BallotBoxController, seed::Digest)

Set's a seed of the ballotbox.

source
PeaceFounder.Server.Controllers.set_seed!Method
set_seed!(station::PollingStation, uuid::UUID, seed::Digest)

Sets a seed for a ballotbox with provided uuid.

source
PeaceFounder.Server.Controllers.spineMethod
spine(ledger::BallotBoxController)::Vector{Digest}

Return a history tree leaf vector.

source
PeaceFounder.Server.Controllers.spineMethod
spine(station::PollingStation, uuid::UUID)::Vector{Digest}

Return a leaf vector for a ballotbox with proposal uuid.

source
PeaceFounder.Server.Controllers.validateMethod
validate(ledger::BallotBoxController, vote::Vote)

Check that vote can be included in the ballotbox. Is well formed, signed by a member pseudonym and cryptographic signature is valid. Raises error if either of checks fail.

source
+end

Represents a pooling station which hosts ballotbox ledgers for every proposal collector manages.

Interface: init!, record!, commit!, commit, ack_leaf, ack_root, ack_cast, receipt, spine, ledger, tally, set_seed!

source
Base.getMethod
get(station::PollingStation, uuid::UUID)::BallotBoxController

Return a ballotbox ledger with a provided UUID. If none is found throws an error.

source
Base.getMethod
get(station::PollingStation, proposal::Digest)::BallotBoxController

Return a ballotbox which has proposal with provided digest.

source
Base.getindexMethod
getindex(ledger::BallotBoxController, index::Int)::CastRecord

Return a ledger record at provided index.

source
Base.lengthMethod
length(ledger::BallotBoxController)

Return a total length of the ledger including uncommited records in the queue.

source
Base.push!Method
push!(ledger::BallotBoxController, record::CastRecord)

Push a record to the ledger bypassing integrity checks. Used when loading the ledger from a trusted source such as local disk or an archive with a signed root cheksum.

source
HistoryTrees.leafMethod
leaf(ledger::BallotBoxController, N::Int)::Digest

Return a record digest used to form a history tree.

source
HistoryTrees.rootMethod
root(ledger::BallotBoxController[, N::Int])::Digest

Calculate a root for history tree at given index N. If index is not specified returns the current value.

source
PeaceFounder.Core.Model.commitMethod
commit(ledger::BallotBoxController)

Return a commit for the ballotbox ledger.

source
PeaceFounder.Core.Model.commitMethod
commit(station::PollingStation, uuid::UUID)::Commit

Return a ballotbox commit.

source
PeaceFounder.Core.Model.generatorMethod
generator(ledger::BallotBoxController)

Return a relative generator which members use to sign votes anchored by the proposal.

source
PeaceFounder.Core.Model.indexMethod
index(ledger::BallotBoxController)

Return the current index of the ledger. See also length.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(vote::Vote, ack::CastAck, hasher)

Check whether acknowledgment is bound to the provided vote.

source
PeaceFounder.Core.Model.receiptMethod
receipt(ledger::BallotBoxController, index::Int)::CastReceipt

Return a receipt for a ledger element.

source
PeaceFounder.Core.Model.receiptMethod
receipt(station::PollingStation, uuid::UUID, N::Int)::CastReceipt

Return a receipt for a record with index N at ballotbox with uuid.

source
PeaceFounder.Core.Model.seedMethod
seed(ledger::BallotBoxController)::Union{Digest, Nothing}

Return a random selected seed used in the voting.

source
PeaceFounder.Core.Model.tallyMethod
tally(station::PollingStation, uuid::UUID)

Compute a tally from ledger records a ballotbox with uuid.

source
PeaceFounder.Core.Model.uuidMethod
uuid(ledger::BallotBoxController)

Return a UUID of the proposal.

source
PeaceFounder.Core.Model.votersMethod
voters(ledger::BallotBoxController)

Return a list of member pseudonyms with which members authetificate their votes.

source
PeaceFounder.Server.Controllers.ack_castMethod
ack_cast(ledger::BallotBoxController, index::Int)::CastAck

Compute an acknowledgment for record inclusion at index.

source
PeaceFounder.Server.Controllers.ack_castMethod
ack_cast(station::PollingStation, uuid::UUID, N::Int)::CastAck

Return inclusion proof with receipt and current tree commit for a leaf at index N and ballotbox with uuid.

source
PeaceFounder.Server.Controllers.ack_leafMethod
ack_leaf(ledger::BallotBoxController, index::Int)::AckInclusion

Compute an inclusion proof ::AckInclusion for record element at given index.

source
PeaceFounder.Server.Controllers.ack_leafMethod
ack_leaf(station::PollingStation, uuid::UUID, N::Int)::AckInclusion

Return history tree inclusion proof for a tree leaf at index N in ballotbox with uuid.

source
PeaceFounder.Server.Controllers.ack_rootMethod
ack_root(ledger::BallotBoxController, index::Int)::AckConsistency

Compute a history tree consistency proof at index.

source
PeaceFounder.Server.Controllers.ack_rootMethod
ack_root(station::PollingStation, uuid::UUID, N::Int)::AckConsistency

Return history tree consitency proof tree root at index N in ballotbox with uuid.

source
PeaceFounder.Server.Controllers.commit!Method
commit!(ledger::BallotBoxController[, timestamp::DataTime], signer::Signer; with_tally=nothing)

Flushes ballotbox ledger's queue and creates a commit for a current ballotbox ledger state with provided timestamp and signer. A keyword argument with_tally has three values true|false to include or exclude a tally from a commited state and nothing which uses a previous commit preference.

source
PeaceFounder.Server.Controllers.commit!Method
commit!(station::PollingStation, uuid::UUID, collector::Signer; with_tally = nothing)

Select a ballotbox with provided uuid and commit it's state with collector.

source
PeaceFounder.Server.Controllers.commit_indexMethod
commit_index(ledger::BallotBoxController)::Union{Index, Nothing}

Index at which commit is issued. See also length and index

source
PeaceFounder.Server.Controllers.commit_stateMethod
commit_state(ledger::BallotBoxController)

Return a committed state for a ballotbox ledger.

source
PeaceFounder.Server.Controllers.init!Method
init!(station::PollingStation, proposal::Proposal, voters::Set{Pseudonym}[, collector::Pseudonym])

Creates a new ballotbox for given proposal with provided member pseudonyms at a relative generator anchored in the proposal. A collector is optional and provided only when it differs from one specified in the proposal.

source
PeaceFounder.Server.Controllers.ledgerMethod
ledger(ballotbox::BallotBoxController)::Vector{CastRecord}

Return all records from a ballotbox ledger.

source
PeaceFounder.Server.Controllers.ledgerMethod
ledger(station::PollingStation, uuid::UUID)::Vector{CastRecord}

Return a vector of records from a ballotbox with uuid.

source
PeaceFounder.Server.Controllers.record!Method
record!(ledger::BallotBoxController, record::CastRecord)

Check the vote in the record for validity and include that in the ledger directly bypassing queue. This method is useful for replaying and debugging ballotbox ledger state changes. See also record!

source
PeaceFounder.Server.Controllers.record!Method
record!(ledger::BallotBoxController, vote::Vote)

Check the vote for validity and pushes it to the queue. Returns an index N at which the vote will be recorded in the ledger. See also push!

source
PeaceFounder.Server.Controllers.record!Method
record!(station::PollingStation, uuid::UUID, vote::Vote)::Int

Records a vote in a ballotbox with provided proposal UUID. Throws an error if a ballotbox can't be found.

source
PeaceFounder.Server.Controllers.record!Method
record!(station::PollingStation, uuid::UUID, vote::Vote)::Int

Record a vote in a ballotbox found by proposal diggest stored in the vote. Throws an error if a ballotbox can't be found.

source
PeaceFounder.Server.Controllers.reset_tree!Method
reset_tree!(ledger::BallotBoxController)

Recompute history tree root and cache from the elements in the ledger. This is a useful for loading the ledger all at once.

source
PeaceFounder.Server.Controllers.set_seed!Method
set_seed!(ledger::BallotBoxController, seed::Digest)

Set's a seed of the ballotbox.

source
PeaceFounder.Server.Controllers.set_seed!Method
set_seed!(station::PollingStation, uuid::UUID, seed::Digest)

Sets a seed for a ballotbox with provided uuid.

source
PeaceFounder.Server.Controllers.spineMethod
spine(ledger::BallotBoxController)::Vector{Digest}

Return a history tree leaf vector.

source
PeaceFounder.Server.Controllers.spineMethod
spine(station::PollingStation, uuid::UUID)::Vector{Digest}

Return a leaf vector for a ballotbox with proposal uuid.

source
PeaceFounder.Server.Controllers.validateMethod
validate(ledger::BallotBoxController, vote::Vote)

Check that vote can be included in the ballotbox. Is well formed, signed by a member pseudonym and cryptographic signature is valid. Raises error if either of checks fail.

source
diff --git a/dev/index.html b/dev/index.html index f74980a..2449337 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -PeaceFounder.jl · PeaceFounder.jl

PeaceFounder.jl

PeaceFounder is a centralised E2E verifiable e-voting system that leverages pseudonym braiding and history trees. The immutability of the bulletin board is maintained replication-free by voter’s client devices with locally stored consistency-proof chains. Meanwhile, pseudonym braiding done via an exponentiation mix before the vote allows anonymisation to be transactional with a single braider at a time. In contrast to existing E2E verifiable e-voting systems, it is much easier to deploy as the system is fully centralised, free from threshold decryption ceremonies, trusted setup phases and bulletin board replication. Furthermore, the body of a vote is signed with a braided pseudonym, enabling unlimited ballot types.

Introduction

everal end-to-end (E2E) verifiable e-voting systems exist, such as Helios, Scytl, Belenios, ElectionGuard, Estonia's system, and Verificatum, with many available under open-source licences. They all encrypt and mix votes through a re-encryption shuffle and use a threshold decryption ceremony. This allows voters to track their encrypted votes and the public to verify the final tally. However, it depends on the integrity of the bulletin board and the coordination of the threshold decryption ceremony, presenting challenges for smaller communities and organisations.

To make a point, let's consider a Helios voting system. The vote in Helios is stored in a group element, encrypted and signed by a digital signature provider, and then submitted to the bulletin board. When the vote closes, votes go through the reencryption shuffle and are decrypted in the threshold decryption ceremony. Voters can ensure that their vote has been counted by finding their encrypted vote within the list of inputs of the mix cascade. Furthermore, everyone can verify the final tally by counting the decrypted votes and verifying supplemented zero-knowledge proofs without compromising privacy. In this way, the integrity of the election result can be assured.

However, issues like forced abstention and potential vote substitution of unverified votes can happen if authorities are corrupt and auditing/monitoring does not occur. Publishing vote-casting signatures can alleviate many of those issues, but that violates participation privacy. The threshold decryption ceremony further compounds the system's complexity; if more than a few are corrupt, votes can remain encrypted, while a low threshold risks privacy breaches. These factors, coupled with the technical intricacies of deployment, make Helios less feasible for small to medium-sized communities, leading to a preference for simpler black box systems to prevent questions from being asked, which can foster trust at the expense of trustworthiness.

A significant improvement over Helios is the Selene system, which offers a voter-assigned tracking number and shows their votes next to them after the vote. Recent usability studies with Selene have demonstrated that voters appreciate the ability to verify their vote in plaintext. This allows them to discard their trust in advanced cryptography as they can see how their vote is counted. As the tracking number is not published before the vote and is deniable, it is also coercion-resistant. In addition to clever cryptography, it can also detect malware interference. However, the threshold decryption ceremony still needs to be deployed along with the bulletin board and thus would generally suit only state-like elections.

Haenni & Spycher proposed a system using exponentiation mixes to anonymise voters' pseudonyms, eliminating the need for a threshold decryption ceremony. However, the benefits of such a system have yet to be reaped as it requires a trusted bulletin board that does not discard unfavourable votes; thus, deployment of such a system needs to be distributed and hence offers minor deployment improvements over Helios. Furthermore, over 13 years, a single open-source system has yet to be implemented.

The innovative approach by PeaceFounder combines pseudonym braiding developed by Haenni & Spycher with a history trees-enabled bulletin board (Crosby & Wallach). When voters cast their vote, their devices receive inclusion proof of the vote, which can later be verified to be binding to the tally with consistency proof. By having only a few voters who request their device to check the proofs, the immutability of the bulletin board is guaranteed. Thus, once the server has assured that the vote is recorded, there is no way for it to be removed. This allows the system to be fully centralised and, thus, makes it easy to self-host.

However, such a system poses many challenges compared to the orthodox approach. To protect against a corrupt server that discards unfavourable votes, voters must have the option to route the vote through proxy/monitor, which adds a challenge with coercion/bribery. To reap the benefits of braiding pseudonyms with any other community/organisation worldwide, the voters must be registered long before the vote starts, which would produce a bad user experience. Therefore, disengaging anonymisation from voting requires long-standing accounts, which poses an issue for continuous member registration and termination; on top of that, the votes need to be delivered over an anonymous channel not to be traceable by a corrupt authority. All of them are addressed with the PeaceFounder project in innovative ways.

Demo

An 8-minute YouTube demonstration is available here:

IMAGE ALT TEXT HERE

References

  • Rolf Haenni and Oliver Spycher. Secure internet voting on limited devices with anonymized DSA public keys. 2011
  • Scott A. Crosby and Dan S. Wallach. Efficient data structures for tamper-evident logging. 2009
  • Björn Terelius and Douglas Wikström. Proofs of restricted shuffles. 2010.
+PeaceFounder.jl · PeaceFounder.jl

PeaceFounder.jl

PeaceFounder is a centralised E2E verifiable e-voting system that leverages pseudonym braiding and history trees. The immutability of the bulletin board is maintained replication-free by voter’s client devices with locally stored consistency-proof chains. Meanwhile, pseudonym braiding done via an exponentiation mix before the vote allows anonymisation to be transactional with a single braider at a time. In contrast to existing E2E verifiable e-voting systems, it is much easier to deploy as the system is fully centralised, free from threshold decryption ceremonies, trusted setup phases and bulletin board replication. Furthermore, the body of a vote is signed with a braided pseudonym, enabling unlimited ballot types.

Introduction

everal end-to-end (E2E) verifiable e-voting systems exist, such as Helios, Scytl, Belenios, ElectionGuard, Estonia's system, and Verificatum, with many available under open-source licences. They all encrypt and mix votes through a re-encryption shuffle and use a threshold decryption ceremony. This allows voters to track their encrypted votes and the public to verify the final tally. However, it depends on the integrity of the bulletin board and the coordination of the threshold decryption ceremony, presenting challenges for smaller communities and organisations.

To make a point, let's consider a Helios voting system. The vote in Helios is stored in a group element, encrypted and signed by a digital signature provider, and then submitted to the bulletin board. When the vote closes, votes go through the reencryption shuffle and are decrypted in the threshold decryption ceremony. Voters can ensure that their vote has been counted by finding their encrypted vote within the list of inputs of the mix cascade. Furthermore, everyone can verify the final tally by counting the decrypted votes and verifying supplemented zero-knowledge proofs without compromising privacy. In this way, the integrity of the election result can be assured.

However, issues like forced abstention and potential vote substitution of unverified votes can happen if authorities are corrupt and auditing/monitoring does not occur. Publishing vote-casting signatures can alleviate many of those issues, but that violates participation privacy. The threshold decryption ceremony further compounds the system's complexity; if more than a few are corrupt, votes can remain encrypted, while a low threshold risks privacy breaches. These factors, coupled with the technical intricacies of deployment, make Helios less feasible for small to medium-sized communities, leading to a preference for simpler black box systems to prevent questions from being asked, which can foster trust at the expense of trustworthiness.

A significant improvement over Helios is the Selene system, which offers a voter-assigned tracking number and shows their votes next to them after the vote. Recent usability studies with Selene have demonstrated that voters appreciate the ability to verify their vote in plaintext. This allows them to discard their trust in advanced cryptography as they can see how their vote is counted. As the tracking number is not published before the vote and is deniable, it is also coercion-resistant. In addition to clever cryptography, it can also detect malware interference. However, the threshold decryption ceremony still needs to be deployed along with the bulletin board and thus would generally suit only state-like elections.

Haenni & Spycher proposed a system using exponentiation mixes to anonymise voters' pseudonyms, eliminating the need for a threshold decryption ceremony. However, the benefits of such a system have yet to be reaped as it requires a trusted bulletin board that does not discard unfavourable votes; thus, deployment of such a system needs to be distributed and hence offers minor deployment improvements over Helios. Furthermore, over 13 years, a single open-source system has yet to be implemented.

The innovative approach by PeaceFounder combines pseudonym braiding developed by Haenni & Spycher with a history trees-enabled bulletin board (Crosby & Wallach). When voters cast their vote, their devices receive inclusion proof of the vote, which can later be verified to be binding to the tally with consistency proof. By having only a few voters who request their device to check the proofs, the immutability of the bulletin board is guaranteed. Thus, once the server has assured that the vote is recorded, there is no way for it to be removed. This allows the system to be fully centralised and, thus, makes it easy to self-host.

However, such a system poses many challenges compared to the orthodox approach. To protect against a corrupt server that discards unfavourable votes, voters must have the option to route the vote through proxy/monitor, which adds a challenge with coercion/bribery. To reap the benefits of braiding pseudonyms with any other community/organisation worldwide, the voters must be registered long before the vote starts, which would produce a bad user experience. Therefore, disengaging anonymisation from voting requires long-standing accounts, which poses an issue for continuous member registration and termination; on top of that, the votes need to be delivered over an anonymous channel not to be traceable by a corrupt authority. All of them are addressed with the PeaceFounder project in innovative ways.

Demo

An 8-minute YouTube demonstration is available here:

IMAGE ALT TEXT HERE

References

  • Rolf Haenni and Oliver Spycher. Secure internet voting on limited devices with anonymized DSA public keys. 2011
  • Scott A. Crosby and Dan S. Wallach. Efficient data structures for tamper-evident logging. 2009
  • Björn Terelius and Douglas Wikström. Proofs of restricted shuffles. 2010.
diff --git a/dev/model/index.html b/dev/model/index.html index 3fe318c..78db0bc 100644 --- a/dev/model/index.html +++ b/dev/model/index.html @@ -2,40 +2,40 @@ PeaceFounder.Core.Model · PeaceFounder.jl

PeaceFounder.Core.Model

Primitives

PeaceFounder.Core.Model.CryptoSpecType
struct CryptoSpec
     hasher::HashSpec
     group::GroupSpec
     generator::Generator
-end

Specification of cryptographic parameters which are used for public key cryptography, message hashing and authetification codes.

source
PeaceFounder.Core.Model.DigestType
struct Digest
+end

Specification of cryptographic parameters which are used for public key cryptography, message hashing and authetification codes.

source
PeaceFounder.Core.Model.GeneratorType
struct Generator
     data::Vector{UInt8}
-end

Datatype which stores cryptogrpahic group point in standart octet form intended to be used as a base. See also Pseudonym.

source
PeaceFounder.Core.Model.HMACType
struct HMAC
+end

Datatype which stores cryptogrpahic group point in standart octet form intended to be used as a base. See also Pseudonym.

source
PeaceFounder.Core.Model.SignerType
struct Signer
     spec::CryptoSpec
     pbkey::Pseudonym
     key::BigInt
-end

A signer type. See a method generate(Signer, spec) for initialization.

Interface: pseudonym, id, sign, seal, approve

source
PeaceFounder.Core.Model.digestMethod
digest(message::Vector{UInt8}, hasher::HashSpec)::Digest
-digest(document, spec) = digest(canonicalize(message)::Vector{UInt8}, hasher(spec)::HashSpec)

Return a resulting digest applying hasher on the given message. When message is not octet string a canonicalize method is applied first.

source
PeaceFounder.Core.Model.digestMethod
digest(bytes::Vector{UInt8}, hasher::HashSpec)::Digest
-digest(x, spec) = digest(canonicalize(x)::Vector{UInt8}, hasher(spec)::HashSpec)

Compute a hash digest. When input is not in bytes the canonicalize method is applied first.

source
PeaceFounder.Core.Model.sealMethod
seal(message::Vector{UInt8}[, generator::Generator], signer::Signer)::Seal

Sign a bytestring message with signer's private key and specification and return a signature as a Seal. When generator is provided it is used as a base for the signature. See also sign.

source
PeaceFounder.Core.Model.signMethod
sign(digest::Digest[, generator::Generator], signer::Signer)::Signature

Sign a digest as an integer with signer's private key and specification. This method avoids running hashing twice when that is done externally. When generator is provided it is used as a base for the signature.

source
PeaceFounder.Core.Model.signMethod
sign(message::Vector{UInt8}[, generator::Generator], signer::Signer)::Signature

Sign a bytestring message with signer's private key and specification. When generator is provided it is used as a base for the signature.

source
PeaceFounder.Core.Model.canonicalizeFunction

ToDo: a well specified encoding is essential here. Binary tree encoding may suffice here. More fancy approach would be to use a DER encoding. Meanwhile JSON shall be used.

source
PeaceFounder.Core.Model.pseudonymFunction
pseudonym(signer::Signer, [generator])::Pseudonym

Return a pseudonym of a signer at a given relative generator. If generator is not passed returns identity pseudonym. (See also id)


pseudonym(seal::Seal)::Pseudonym

Return a pseudonym of a seal. Note that it is not equal to identity when the signature is issued on a relative generator.


pseudonym(vote::Vote)::Pseudonym

Return a pseudonym used to seal the vote.

source
PeaceFounder.Core.Model.idFunction
id(document)::Pseudonym

Return identity pseudonym of a document issuer.


id(signer)::Pseudonym

Return identity pseudonym of a signer.

source
PeaceFounder.Core.Model.verifyFunction
verify(message, seal::Seal, [generator::Generator], crypto::CryptoSpec)::Bool
-verify(message, pk::Pseudonym, sig::Signature, [generator::Generator], crypto::CryptoSpec)::Bool

Verify the cryptographic signature of the message returning true if valid. An optional generator can be given when signature is issued on a relative generator differing from a base specification crypto.


verify(document[, generator::Generator], crypto::CryptoSpec)::Bool

Verify a cryptographic signature of the document returning true if valid.


verify(braidwork::BraidReceipt, crypto::CryptoSpec)::Bool

Verify a braider issued cryptographic signature for the braidwork and a zero knowledge proofs. Returns true if both checks succeed.

source

BraidChain

PeaceFounder.Core.Model.digestMethod
digest(message::Vector{UInt8}, hasher::HashSpec)::Digest
+digest(document, spec) = digest(canonicalize(message)::Vector{UInt8}, hasher(spec)::HashSpec)

Return a resulting digest applying hasher on the given message. When message is not octet string a canonicalize method is applied first.

source
PeaceFounder.Core.Model.digestMethod
digest(bytes::Vector{UInt8}, hasher::HashSpec)::Digest
+digest(x, spec) = digest(canonicalize(x)::Vector{UInt8}, hasher(spec)::HashSpec)

Compute a hash digest. When input is not in bytes the canonicalize method is applied first.

source
PeaceFounder.Core.Model.sealMethod
seal(message::Vector{UInt8}[, generator::Generator], signer::Signer)::Seal

Sign a bytestring message with signer's private key and specification and return a signature as a Seal. When generator is provided it is used as a base for the signature. See also sign.

source
PeaceFounder.Core.Model.signMethod
sign(digest::Digest[, generator::Generator], signer::Signer)::Signature

Sign a digest as an integer with signer's private key and specification. This method avoids running hashing twice when that is done externally. When generator is provided it is used as a base for the signature.

source
PeaceFounder.Core.Model.signMethod
sign(message::Vector{UInt8}[, generator::Generator], signer::Signer)::Signature

Sign a bytestring message with signer's private key and specification. When generator is provided it is used as a base for the signature.

source
PeaceFounder.Core.Model.canonicalizeFunction

ToDo: a well specified encoding is essential here. Binary tree encoding may suffice here. More fancy approach would be to use a DER encoding. Meanwhile JSON shall be used.

source
PeaceFounder.Core.Model.pseudonymFunction
pseudonym(signer::Signer, [generator])::Pseudonym

Return a pseudonym of a signer at a given relative generator. If generator is not passed returns identity pseudonym. (See also id)


pseudonym(seal::Seal)::Pseudonym

Return a pseudonym of a seal. Note that it is not equal to identity when the signature is issued on a relative generator.


pseudonym(vote::Vote)::Pseudonym

Return a pseudonym used to seal the vote.

source
PeaceFounder.Core.Model.idFunction
id(document)::Pseudonym

Return identity pseudonym of a document issuer.


id(signer)::Pseudonym

Return identity pseudonym of a signer.

source
PeaceFounder.Core.Model.verifyFunction
verify(message, seal::Seal, [generator::Generator], crypto::CryptoSpec)::Bool
+verify(message, pk::Pseudonym, sig::Signature, [generator::Generator], crypto::CryptoSpec)::Bool

Verify the cryptographic signature of the message returning true if valid. An optional generator can be given when signature is issued on a relative generator differing from a base specification crypto.


verify(document[, generator::Generator], crypto::CryptoSpec)::Bool

Verify a cryptographic signature of the document returning true if valid.


verify(braidwork::BraidReceipt, crypto::CryptoSpec)::Bool

Verify a braider issued cryptographic signature for the braidwork and a zero knowledge proofs. Returns true if both checks succeed.

source

BraidChain

PeaceFounder.Core.Model.DemeSpecType
struct DemeSpec <: Transaction
     uuid::UUID
     title::String
     crypto::CryptoSpec
@@ -47,33 +47,33 @@
     collector::Pseudonym
     timestamp::Union{DateTime, Nothing} = nothing
     signature::Union{Signature, Nothing} = nothing
-end

Represents a deme configuration parameters issued by the guardian.

  • uuid::UUID an unique random generated community identifier;
  • title::String a community name with which deme is represented;
  • crypto::CryptoSpec cryptographic parameters for the deme;
  • guardian::Pseudonym an issuer for this demespec file. Has authorithy to set a roster:
    • recorder::Pseudonym an authorithy which has rights to add new transactions and is responsable for braidchain's ledger integrity. Issues Commit{ChainState};
    • registrar::Pseudonym an authorithy which has rights to authorize new admissions to the deme. See Admission and Membership;
    • braider::Pseudonym an authorithy which can do a legitimate braid jobs for other demes. See BraidReceipt;
    • proposer::Pseudonym an authorithy which has rights to issue a proposals for the braidchain. See Proposal;
    • collector::Pseudonym an authorithy which is repsonsable for collecting votes for proposals. This is also recorded in the proposal itself.
  • timestamp::Union{DateTime, Nothing} time when signature is being issued;
  • signature::Union{Signature, Nothing} a guardian issued signature.
source
PeaceFounder.Core.Model.MembershipType
struct Membership <: Transaction
+end

Represents a deme configuration parameters issued by the guardian.

  • uuid::UUID an unique random generated community identifier;
  • title::String a community name with which deme is represented;
  • crypto::CryptoSpec cryptographic parameters for the deme;
  • guardian::Pseudonym an issuer for this demespec file. Has authorithy to set a roster:
    • recorder::Pseudonym an authorithy which has rights to add new transactions and is responsable for braidchain's ledger integrity. Issues Commit{ChainState};
    • registrar::Pseudonym an authorithy which has rights to authorize new admissions to the deme. See Admission and Membership;
    • braider::Pseudonym an authorithy which can do a legitimate braid jobs for other demes. See BraidReceipt;
    • proposer::Pseudonym an authorithy which has rights to issue a proposals for the braidchain. See Proposal;
    • collector::Pseudonym an authorithy which is repsonsable for collecting votes for proposals. This is also recorded in the proposal itself.
  • timestamp::Union{DateTime, Nothing} time when signature is being issued;
  • signature::Union{Signature, Nothing} a guardian issued signature.
source
PeaceFounder.Core.Model.MembershipType
struct Membership <: Transaction
     admission::Admission
     generator::Generator
     pseudonym::Pseudonym
     approval::Union{Signature, Nothing} 
-end

A new member certificate which rolls in (anouances) it's pseudonym at current generator signed with identity pseudonym certified with admission certificate issued by registrar. This two step process is necessary as a checkpoint in situations when braidchain ledger get's locked during a new member resgistration procedure.

source
PeaceFounder.Core.Model.TicketIDType
struct TicketID
+end

A new member certificate which rolls in (anouances) it's pseudonym at current generator signed with identity pseudonym certified with admission certificate issued by registrar. This two step process is necessary as a checkpoint in situations when braidchain ledger get's locked during a new member resgistration procedure.

source
PeaceFounder.Core.Model.TicketIDType
struct TicketID
     id::Vector{UInt8}
-end

Represents a unique identifier for which a recruit tooken is issued. In case of necessity id can contain a full document, for instance, registration form, proof of identity and etc. In case a privacy is an issue the id can contain a unique identifier which can be matched to an identity in an external database.

source
PeaceFounder.Core.Model.approveMethod
approve(x::T, signer::Signer)::T

Cryptographically sign a document x::T and returns a signed document with the same type. To check whether a document is signed see issuer method.

source
PeaceFounder.Core.Model.membersMethod
members(ledger::BraidChainLedger[, index::Int])::Set{Pseudonym}

Return a set of member pseudonyms at relative generator at braidchain ledger row index. If index is omitted return a current state value.

source
PeaceFounder.Core.Model.BraidReceiptType
struct BraidReceipt <: Transaction
+end

Represents a unique identifier for which a recruit tooken is issued. In case of necessity id can contain a full document, for instance, registration form, proof of identity and etc. In case a privacy is an issue the id can contain a unique identifier which can be matched to an identity in an external database.

source
PeaceFounder.Core.Model.approveMethod
approve(x::T, signer::Signer)::T

Cryptographically sign a document x::T and returns a signed document with the same type. To check whether a document is signed see issuer method.

source
PeaceFounder.Core.Model.membersMethod
members(ledger::BraidChainLedger[, index::Int])::Set{Pseudonym}

Return a set of member pseudonyms at relative generator at braidchain ledger row index. If index is omitted return a current state value.

source
PeaceFounder.Core.Model.BraidReceiptType
struct BraidReceipt <: Transaction
     braid::Simulator
     producer::DemeSpec
     approval::Union{Seal, Nothing}
-end

Represents a braider's computation which is supported with zero knowledge proof of shuffle and decryption assuring it's corectness stored in a braid field; producer denotes a deme where the braid is made. To assert latter the the braider signs the braidwork and stores that in the aproval field. See a braid method.

Interface: approve, verify, input_generator, input_members, output_generator, output_members

source
PeaceFounder.Core.Model.approveMethod
approve(braid::BraidReceipt, spec::DemeSpec, braider::Signer)

Sign a braidwork with a braider. Throws an error if braider is not in the producer demespec.

source
PeaceFounder.Core.Model.braidMethod
braid(generator::Generator, members::Union{Vector{Pseudonym}, Set{Pseudonym}}, consumer::DemeSpec, producer::DemeSpec; verifier = (g) -> ProtocolSpec(; g))

Selects a private exponent x at random and computes a new generator $g' = g^x$ and $member_i'=member_i^x$ returns the latter in a sorted order and provides a zero knowledge proof that all operations have been performed honestly. In partucular, not including/droping new member pseudonyms in the process. consumer attributes are necessary to interepret generator and pseudonym group elements with which the computation is performed.

By default a Verificatum compatable verifier is used for performing reencryption proof of shuffle

A verifier can be configured with a keyword argument. By default a Verificatum compatable verifier for a proof of shuffle is used.

source
PeaceFounder.Core.Model.verifyMethod
verify(braid::BraidReceipt, crypto::CryptoSpec)

Verifies a braid approval and then it's zero knowledge proofs. A crypto argument is provided to avoid downgrading attacks.

source

Ballot Box

PeaceFounder.Core.Model.approveMethod
approve(braid::BraidReceipt, spec::DemeSpec, braider::Signer)

Sign a braidwork with a braider. Throws an error if braider is not in the producer demespec.

source
PeaceFounder.Core.Model.braidMethod
braid(generator::Generator, members::Union{Vector{Pseudonym}, Set{Pseudonym}}, consumer::DemeSpec, producer::DemeSpec; verifier = (g) -> ProtocolSpec(; g))

Selects a private exponent x at random and computes a new generator $g' = g^x$ and $member_i'=member_i^x$ returns the latter in a sorted order and provides a zero knowledge proof that all operations have been performed honestly. In partucular, not including/droping new member pseudonyms in the process. consumer attributes are necessary to interepret generator and pseudonym group elements with which the computation is performed.

By default a Verificatum compatable verifier is used for performing reencryption proof of shuffle

A verifier can be configured with a keyword argument. By default a Verificatum compatable verifier for a proof of shuffle is used.

source
PeaceFounder.Core.Model.verifyMethod
verify(braid::BraidReceipt, crypto::CryptoSpec)

Verifies a braid approval and then it's zero knowledge proofs. A crypto argument is provided to avoid downgrading attacks.

source

Ballot Box

PeaceFounder.Core.Model.BallotBoxStateType
struct BallotBoxState
     proposal::Digest
     seed::Digest
     index::Int
     root::Digest
     tally::Union{Nothing, Tally} 
     view::Union{Nothing, BitVector} # 
-end

Represents a public ballot box state. Contains an immutable proposal and seed digest; a current ledger index, history tree root. When ellections end a tally is included in the state and a view is added listing all counted votes. Note that the view attribute is important for a client to know whether it's key have leaked and somone lese havbe superseeded it's vote by revoting.

source
PeaceFounder.Core.Model.CastReceiptType
struct CastReceipt
+end

Represents a public ballot box state. Contains an immutable proposal and seed digest; a current ledger index, history tree root. When ellections end a tally is included in the state and a view is added listing all counted votes. Note that the view attribute is important for a client to know whether it's key have leaked and somone lese havbe superseeded it's vote by revoting.

source
PeaceFounder.Core.Model.CastReceiptType
struct CastReceipt
     vote::Digest
     timestamp::DateTime
-end

Represents a ballotbox ledger receipt which is hashed for a history tree. It's sole purpose is to assure voters that their vote is included in the ledger while also adding additional metadata as timestamp and. In contrast to CastRecord it does not reveal how voter have voted thus can be published during ellections without violating fairness property. For some situations it may be useful to extend the time until the votes are published as that can disincentivice coercers and bribers as they would not know whether their coerced vote have been superseeded in revoting. See receipt method for it's construction from a CastRecord.

Note that a blind signature could be commited as H(signature|H(vote)) to avoid tagging the use of pseudonym during ellections while collector could issue only a one blind signature for a voter. Note that members whoose private key could have been stolen could not obtain a valid signature for participation and that could be a good thing!

source
PeaceFounder.Core.Model.CastRecordType
struct CastRecord
+end

Represents a ballotbox ledger receipt which is hashed for a history tree. It's sole purpose is to assure voters that their vote is included in the ledger while also adding additional metadata as timestamp and. In contrast to CastRecord it does not reveal how voter have voted thus can be published during ellections without violating fairness property. For some situations it may be useful to extend the time until the votes are published as that can disincentivice coercers and bribers as they would not know whether their coerced vote have been superseeded in revoting. See receipt method for it's construction from a CastRecord.

Note that a blind signature could be commited as H(signature|H(vote)) to avoid tagging the use of pseudonym during ellections while collector could issue only a one blind signature for a voter. Note that members whoose private key could have been stolen could not obtain a valid signature for participation and that could be a good thing!

source
PeaceFounder.Core.Model.CastRecordType
struct CastRecord
     vote::Vote
     timestamp::DateTime
-end

Represents a ballotbox ledger record. Adds a timestamp when the vote have been recorded. In future, the record will also contain a blind signature with which members could prove to everyone that they had cast their vote without revealing the link to the vote.

source
PeaceFounder.Core.Model.ProposalType
struct Proposal <: Transaction 
+end

Represents a ballotbox ledger record. Adds a timestamp when the vote have been recorded. In future, the record will also contain a blind signature with which members could prove to everyone that they had cast their vote without revealing the link to the vote.

source
PeaceFounder.Core.Model.ProposalType
struct Proposal <: Transaction 
     uuid::UUID
     summary::String
     description::String
@@ -83,23 +83,23 @@
     collector::Union{Pseudonym, Nothing} # 
     anchor::Union{ChainState, Nothing}
     approval::Union{Seal, Nothing} 
-end

Represents a proposal for a ballot specyfing voting window, unique identifier, summary, description. Set's the collector identity which collects votes and issues vote inclusion receipts and is responsable for maintaining the ledger's integrity. The proposal also includes an anchor which sets a relative generator with which members vote anonymously. To be considered valid is signed by proposer authorizing vote to take place.

source
PeaceFounder.Core.Model.SelectionType
struct Selection
+end

Represents a proposal for a ballot specyfing voting window, unique identifier, summary, description. Set's the collector identity which collects votes and issues vote inclusion receipts and is responsable for maintaining the ledger's integrity. The proposal also includes an anchor which sets a relative generator with which members vote anonymously. To be considered valid is signed by proposer authorizing vote to take place.

source
PeaceFounder.Core.Model.VoteType
struct Vote
     proposal::Digest
     seed::Digest
     selection::Selection
     seq::Int
     approval::Union{Seal, Nothing} 
-end

Represents a vote for a proposal issued by a member. The proposal is stored as hash digest ensuring that member have voted on an untampered proposal. seed contains a randon string issued by collector at the moment when a vote starts to eliminate early voting / shortening a time at which coercers could act uppon. selection contians voter's preference;

seq is a serquence number counting a number of votes at which vote have been approved for a given proposal. It starts at 1 and is increased by one for every single signature made on the proposal. This is an important measure which allows to detect possible leakage of a member's private key. Also provides means for revoting ensuring that latest vote get's counted.

The vote is considered valid when it is sealed by a member's private key at a relative generator stored in the proposal.

source
HistoryTrees.rootMethod
root(state::BallotBoxState)

Return a history tree root for a current ballotbox ledger state.

source
PeaceFounder.Core.Model.isconsistentMethod
isconsistent(selection::Selection, ballot::Ballot)

Verifies that voter's selection is consistent with ballot form. For instance, whether selection is withing the range of ballot options.

source
PeaceFounder.Core.Model.stateFunction
state(ledger::BallotBoxLedger; seed::Digest, root::Digest = root(ledger), with_tally::Union{Nothing, Bool} = nothing)::BallotBoxState

Return a state metadata for ballotbox ledger.

source
PeaceFounder.Core.Model.tallyMethod
tally(ballot::Ballot, ballots::AbstractVector{Selection})::Tally

Count ballots, check that they are filled consistently and return a final tally.

source
PeaceFounder.Core.Model.uuidMethod
uuid(proposal::Proposal)::UUID

UUID for a proposal. Issued by proposer and it's purpose is to croslink to an external system durring the proposal dreafting stage.

source
PeaceFounder.Core.Model.voteMethod
vote(proposal::Proposal, seed::Digest, selection::Selection, member::Signer; seq = 1)

Issue a vote on a proposal and provided collector seed for a member's selection.

source

Auditing

PeaceFounder.Core.ProtocolSchema

PeaceFounder.Core.ProtocolSchema.AckConsistencyType
struct AckConsistency{T}
+end

Represents a vote for a proposal issued by a member. The proposal is stored as hash digest ensuring that member have voted on an untampered proposal. seed contains a randon string issued by collector at the moment when a vote starts to eliminate early voting / shortening a time at which coercers could act uppon. selection contians voter's preference;

seq is a serquence number counting a number of votes at which vote have been approved for a given proposal. It starts at 1 and is increased by one for every single signature made on the proposal. This is an important measure which allows to detect possible leakage of a member's private key. Also provides means for revoting ensuring that latest vote get's counted.

The vote is considered valid when it is sealed by a member's private key at a relative generator stored in the proposal.

source
HistoryTrees.rootMethod
root(state::BallotBoxState)

Return a history tree root for a current ballotbox ledger state.

source
PeaceFounder.Core.Model.isconsistentMethod
isconsistent(selection::Selection, ballot::Ballot)

Verifies that voter's selection is consistent with ballot form. For instance, whether selection is withing the range of ballot options.

source
PeaceFounder.Core.Model.stateFunction
state(ledger::BallotBoxLedger; seed::Digest, root::Digest = root(ledger), with_tally::Union{Nothing, Bool} = nothing)::BallotBoxState

Return a state metadata for ballotbox ledger.

source
PeaceFounder.Core.Model.tallyMethod
tally(ballot::Ballot, ballots::AbstractVector{Selection})::Tally

Count ballots, check that they are filled consistently and return a final tally.

source
PeaceFounder.Core.Model.uuidMethod
uuid(proposal::Proposal)::UUID

UUID for a proposal. Issued by proposer and it's purpose is to croslink to an external system durring the proposal dreafting stage.

source
PeaceFounder.Core.Model.voteMethod
vote(proposal::Proposal, seed::Digest, selection::Selection, member::Signer; seq = 1)

Issue a vote on a proposal and provided collector seed for a member's selection.

source

Auditing

PeaceFounder.Core.ProtocolSchema

PeaceFounder.Core.ProtocolSchema.AckConsistencyType
struct AckConsistency{T}
     proof::ConsistencyProof
     commit::Commit{T}
-end

Represents an ackknowledgment from the issuer that a root is permanetly included in the ledger. This acknowledgemnt assures that ledger up to index(ack) is included in the current ledger which has has index index(commit(ack)). This is useful in a combination with AckInclusion to privatelly update it's validity rather than asking an explicit element. Also ensures that other elements in the ledger are not being tampered with.

Interface: root, id, issuer, commit, index, verify

source
PeaceFounder.Core.ProtocolSchema.AckInclusionType
struct AckInclusion{T}
+end

Represents an ackknowledgment from the issuer that a root is permanetly included in the ledger. This acknowledgemnt assures that ledger up to index(ack) is included in the current ledger which has has index index(commit(ack)). This is useful in a combination with AckInclusion to privatelly update it's validity rather than asking an explicit element. Also ensures that other elements in the ledger are not being tampered with.

Interface: root, id, issuer, commit, index, verify

source
PeaceFounder.Core.ProtocolSchema.CastAckType
struct CastAck
     receipt::CastReceipt
     ack::AckInclusion{BallotBoxState}
-end

Represents a reply to a voter when a vote have been included in the ballotbox ledger. Contains a receipt and inlcusion acknowledgment. In future would also include a blind signature in the reply for a proof of participation. To receive this reply (with a blind signature in the future) a voter needs to send a vote which is concealed during ellections and thus tagging votes with blind signatures from reply to monitor revoting would be as hard as monitoring the submitted votes.

source
HistoryTrees.leafMethod
leaf(ack::AckInclusion)

Access a leaf diggest for which the acknowledgment is made.

source
HistoryTrees.rootMethod
root(x::AckConsistency)

Access a root diggest for which the acknowledgment is made.

source
PeaceFounder.Core.Model.indexMethod
index(ack::AckConsistency)

Return an index for a root at which the consistency proof is made. To obtain the current ledger index use index(commit(ack)).

source
PeaceFounder.Core.Model.indexMethod
index(ack::AckInclusion)::Int

Return an index at which the leaf is recorded in the ledger. To obtain the current ledger index use index(commit(ack)).

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(receipt::CastReceipt, ack::AckInclusion, hasher::HashSpec)::Bool

Check that cast receipt is binding to received inclusion acknowledgment.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(record::Transaction, ack::AckInclusion{ChainState}, crypto::CryptoSpec)

A generic method checking whether transaction is included in the braidchain.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(ack::CastAck, proposal::Proposal, hasher::HashSpec)::Bool

Check that acknowledgment is legitimate meaning that it is issued by a collector listed in the proposal.

source
+end

Represents a reply to a voter when a vote have been included in the ballotbox ledger. Contains a receipt and inlcusion acknowledgment. In future would also include a blind signature in the reply for a proof of participation. To receive this reply (with a blind signature in the future) a voter needs to send a vote which is concealed during ellections and thus tagging votes with blind signatures from reply to monitor revoting would be as hard as monitoring the submitted votes.

source
PeaceFounder.Core.ProtocolSchema.TicketStatusType

struct TicketStatus ticketid::TicketID timestamp::DateTime admission::Union{Nothing, Admission} end

Represents a public state of a ticket. See isadmitted method.

source
HistoryTrees.leafMethod
leaf(ack::AckInclusion)

Access a leaf diggest for which the acknowledgment is made.

source
HistoryTrees.rootMethod
root(x::AckConsistency)

Access a root diggest for which the acknowledgment is made.

source
PeaceFounder.Core.Model.commitMethod
commit(x)

Access a commit of an object x.

source
PeaceFounder.Core.Model.commitMethod
commit(ack::CastAck)

Return a commit from a CastAck.

source
PeaceFounder.Core.Model.indexMethod
index(ack::AckConsistency)

Return an index for a root at which the consistency proof is made. To obtain the current ledger index use index(commit(ack)).

source
PeaceFounder.Core.Model.indexMethod
index(ack::AckInclusion)::Int

Return an index at which the leaf is recorded in the ledger. To obtain the current ledger index use index(commit(ack)).

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(receipt::CastReceipt, ack::AckInclusion, hasher::HashSpec)::Bool

Check that cast receipt is binding to received inclusion acknowledgment.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(record::Transaction, ack::AckInclusion{ChainState}, crypto::CryptoSpec)

A generic method checking whether transaction is included in the braidchain.

source
PeaceFounder.Core.Model.isbindingMethod
isbinding(ack::CastAck, proposal::Proposal, hasher::HashSpec)::Bool

Check that acknowledgment is legitimate meaning that it is issued by a collector listed in the proposal.

source
PeaceFounder.Core.Model.verifyMethod
verify(ack::CastAck, crypto::CryptoSpec)::Bool

Verify the cast acknowledgment cryptographic signature.

source
PeaceFounder.Core.ProtocolSchema.isadmittedMethod
isadmitted(status::TicketStatus)

Check whether ticket is addmitted.

source
diff --git a/dev/overview/index.html b/dev/overview/index.html index dad9438..535266a 100644 --- a/dev/overview/index.html +++ b/dev/overview/index.html @@ -8,4 +8,4 @@

The PeaceFounder's bulletin board is a microservice that accepts transactional records and votes. The primary transactional records include member certificates issued in prospective member interaction with the registrar, braid records which recompute pseudonym member list and corresponding relative generator issued by a braider and proposal records announcing a vote issued by a proposer. The system is configured with a guardian issued deme[1] record, which sets cryptographic parameters, and a rooster, which includes the proposer, registrar, and bulletin board authority identities.

The peacefounder bulletin board, proposer, and registrar microservices are internal and can be managed or delegated by a guardian. This separation accommodates customisation for varied political consensus, criteria for proposal submissions to the ballot box, choice of identity provider, and methods for disclosing registrar information to auditors to verify the authenticity of members. To make testing and deployment easier for new organisations, a bundle that includes a registrar, proposer and bulletin board will be available and deployable on a preferred server of choice and will offer web access for a guardian with sane defaults and configuration options.

Member's client devices actively monitor the bulletin board, ensuring the immutability of records by tracking bulletin board commits. This method of oversight is scalable, as members only request a history tree[2] consistency proofs, eliminating the need to replicate the actual bulletin board records. These proofs guarantee the protection of their votes and others, assuring that modifications to records are prevented when fresh entries are appended to the bulletin board. This streamlined approach enables prompt identification of bulletin board dishonesty, whether through removing or altering records or the malicious creation of a counterfeit ledger to exclude undesirable votes from the official tally.

Auditing

Integral to establishing trust, a pivotal role is the presence of an {\bf auditor}. The auditor is a judicial-like entity representing members and is vital for resolving conflicts. Member client devices create local proofs for altered or removed records or the presence of a counterfeit ledger, which are then sent to the auditor. Moreover, if votes aren't delivered, the auditor can act as a proxy, offering evidence that the bulletin board deliberately omitted specific votes. The auditor also ensures the integrity of the bulletin board's records, confirming each vote's eligibility and unlinkability and ensuring one vote per member.

Notably, the auditor can avoid a formal association with the guardian to verify the integrity of a resulting tally, as all relevant data is on the public bulletin board (except for the registration roll). This autonomy allows members the freedom to select their trusted auditors. If there are unresolved disputes with the bulletin board, members can even take on the auditor role and, if necessary, seek to replace the guardian. The system's transparency further allows auditors to cross-check each other's findings, promoting accuracy and preventing the spread of false claims.

The auditor plays a key role in assessing the registrar to confirm the authenticity of its members. The registrar maintains a registration roll, serving as evidence of every member's authenticity. Authenticity verification can be as simple as a trusted third party's digital signature on a document that includes the organisation's UUID and the index where a member's certificate is recorded. If a third-party identity provider isn't available, a photo or video of an individual displaying a page with the organisation's title and index might suffice. Regardless of the method, the recommended approach is to provide an auditor with a verifiably random subset of members where verifiable randomness, for instance, can be generated with DRAND service to avoid data aggregation.

Coercion and bribery resistance

Illustration of time restricted receipt freeness in the Peacefounder voting system. During the election period, the system maintains both receipt-freeness and fairness. However, after the tally is published, newly submitted votes lose their fairness. The votes themselves can be published on the buletin board latter to extend the time period for receipt-freeness, reducing the effectiveness of coercers and bribers. This comes at the expense of delaying the audit process for verifying that votes have been tallied as cast.
-

Another pillar that is necessary for ensuring democratic elections is to prevent coercion and vote buying. A significant risk to the PeaceFounder system is for a briber to ask members to forward their votes through a proxy channel they control. To counter this threat, the bulletin board hides the actual votes, showing only their hashes, and gives voters an option to revote, ensuring both receipt freeness and vote fairness. A sequence number along the vote ensures that only the latest cast vote on the device matters.

This method undermines the confidence of vote buyers and coercers, as it prevents them from ensuring that the votes they've acquired will be counted in the final tally. As a consequence, they can only return bribes after votes are published on the bulletin board. (During the vote, only receipt hashes are published on the bulletin board. This serves to both commit the votes while maintaining fairness and receipt-freeness.) This arrangement erodes the credibility of bribers and coercers, making it less likely for voters to engage with them in such transactions due to the lack of a guaranteed positive/negative outcome.

A secondary concern is the potential for a coercer to ask an individual to show how they had voted on their device. To address this, only a receipt is shown. However, this receipt can be linked to the specific vote on the bulletin board. If coercion becomes a significant threat, the receipt can be visible only briefly, such as 30 minutes after casting a vote. During this window, members can manually record their details in a logbook. While this approach may reduce user-friendliness, it still serves as a robust deterrent against malware.

Malware and spyware detection

A PICTURE WITH  A RECEIPT

The last piece of the puzzle is malware and spyware resistance. An adversary could issue votes without compromising the voter's device in case of key leakage. To counter this, every vote includes a sequence number, which records evidence on the bulletin board when a vote is cast from the voter's device. Moreover, if a vote with a sequence number of one is already on the ledger, the first will override any subsequent vote with the same sequence number. This mechanism prevents malware from silently replacing inactive voter's choices.

After voting concludes and the results are published, each voter receives a bitmask of the votes included in the final tally, along with consistency proofs. Given that this approach is scalable (e.g., 1kB can handle 8192 votes, and bit compression can further reduce size), voters device's compare this bitmask with the index from their most recent vote receipt. This allows them to detect any malware activity and display an alert to the voter.

To ensure the voting process's integrity, the voter's device must remain trustworthy. With the presence of malware, there's a risk that the device could falsely reassure the voter that their vote is cast as intended. To counter this threat, after the vote is submitted, the voter receives a receipt containing a timestamp of the vote's record, the pseudonym under which it was cast, and the index where the vote resides on the ledger. Once voting concludes and all votes are disclosed on the bulletin board, the voter can cross-reference their receipt with the bulletin board, verifying that the vote at the provided index aligns with their choice and matches the timestamp when the vote was cast, as well as checking that it was included in the final tally. By maintaining a written record, voters can ensure the accuracy of their vote, safeguarding against malware alterations, unauthorised revoting, or any attempts to redirect multiple voters to a singular vote.

However, it's essential to acknowledge that voters can only detect malware interference post-vote when comparing their receipt to the bulletin board. Additionally, a voter cannot provide evidence to others that their vote was compromised by malware, which means these instances aren't audited within the PeaceFounder system. As a result, members are encouraged and are responsible for utilising more secure devices less susceptible to malware attacks. For more advanced threats, like a briber mandating malware installation for monitoring or extracting the master key, the use of tamper-resistant hardware becomes essential – an extension larger organisations or states might consider.

Implementation details and responsibilities

To illustrate the responsibilities of different entities and the structure of the communication channels, we've provided a detailed diagram. In this representation, arrows indicate which entity holds responsibility for specific resources. The primary mode of communication is facilitated through JSON within an HTTP request/reply. The JSON is also chosen as a canonical byte string format for data signing, which is selected over the ASN1 DER format due to development resource constraints.

The architecture bifurcates the bulletin board into two distinct ledgers: the braidchain and the ballot boxes. This differentiation arises from the disparate pacing and metadata requirements of records. Additionally, casting votes remains inconsequential to the braidchain's state, justifying the ledger division.

Authorised entities, namely the braidchain recorder and the ballot box collector, as specified in the guardian-issued DemeSpec record, oversee each ledger. These controllers uphold the integrity of newly added records, ensuring their coherence with the existing state. For instance, votes must adhere to a specified time window and need to be appropriately signed with member pseudonyms. Braidchain transactions demand more intricate state management, which will be described later.

In the diagram, arrows necessitating anonymous channels are designated with a TOR label originating from the member. This is a countermeasure against potential adversaries attempting to link votes to members via IP addresses. Although alternative network anonymising solutions exist, TOR is the most prominent, and together with the recent release of the Arti project for Rust, it is ideal for client-side applications [...].

Members can view the bulletin board records through the HTTP Facade, which displays them in a browser-friendly HTML. This provides a secondary channel to verify that votes are cast as intended and counted as cast. A pure JavaScript-based HTTP facade is possible, which can be hosted on a static website, simplifying deployment.

It's imperative to recognise the absence of TLS in all communications. This choice stems from the fact that data from the bulletin board is supported with a signature on Merkle tree root, rendering requests tamper-proof. Moreover, using TLS session resumption for anonymous interactions between members and the bulletin board would unintentionally make the system vulnerable to DDOS attacks during the key establishment phase. Furthermore, eliminating the need for certificate issuance and management streamlines system maintenance and deployment, enhancing usability.

Planed Core Features

The PeaceFounder system is actively focusing on integrating key features in its upcoming iterations to enhance transparency. While not exhaustive, the current list includes well-defined proposals ready for implementation.

PeaceFounderBB

https://github.com/PeaceFounder/PeaceFounder.jl/issues/22

A small democratic community often faces the challenge of limited resources, particularly when it comes to hosting bulletin board data or maintaining a comprehensive website for public record access. However, a recent trend offers a practical solution with static website hosting platforms. These platforms allow the creation of a static website directly from source code stored in a git repository without the hassle of setting up and managing certificates. A popular example is GitHub Pages, which simplifies deployment using action scripts to compile websites from sources.

Integrating a GitHub workflow to compile a webpage makes it an ideal platform for hosting a bulletin board interface. This setup has a dual advantage. The GitHub repository can serve as an authentic storage space for bulletin board records. Secondly, these records are easily accessible to the public via a web interface. Continuous integration further enhances this with build scripts, ensuring the integrity and verification of the bulletin board's contents. Those interested in verifying the bulletin board's integrity independently can either fork the repository and run the action script or clone the data locally.

Additionally, the use of the Zenodo repository enriches this system. Zenodo provides excellent archival workflows and the capability to generate a DOI link. This link serves a similar purpose to dataset references in scientific research, offering a reliable and citable record.

Cast as intended verification during the vote

https://github.com/PeaceFounder/PeaceFounder.jl/issues/21

At present, voters can only confirm that their vote has been cast as intended and accurately counted after the vote has ended and the votes are published. As the publication of votes can be delayed as a measure against coercion, it might discourage voters' participation from verifying that their vote is indeed cast as intended and counted as cast. The key issue lies in the possibility of unnoticed malware on voting devices. If voters don't verify their votes, the likelihood of malware affecting a significant number of votes without detection increases. Thus, having a procedure that enables immediate verification of the voting process is essential to engage more voters to check their votes.

The PeaceFounder system can address this by providing voters with a token displayed on the client's screen for vote verification. This token can be used in a web browser to confirm that the vote has been cast as intended. It also indicates if the vote has been superseded by a subsequent vote or one with a higher sequence number, which may occur if the member's key is compromised. To maintain receipt-freeness, the token remains valid for only a short period, such as 15 minutes. The expiration is crucial; it allows voters to verify their votes while preventing coercion or bribery attempts. It also hinders any unsolicited checks on voters' choices.

Evidence auditing with terminal API

https://github.com/PeaceFounder/PeaceFounder.jl/issues/19

The PeaceFounder system is universally verifiable, a feature ensuring that every vote is cryptographically proven to come from a registered member, even if all involved parties are corrupt. To mitigate the influence of coercion or bribery, the authority can strategically delay the publication of votes, which weakens the link between coercers and their subjects before the voters lose receipt freeness. After the votes are published, every aspect of the voting process is transparent: all proofs of votes are made publicly available. This transparency allows any interested party to audit the election results and, at their convenience, independently reproduce the announced tally.

Membership Termination

https://github.com/PeaceFounder/PeaceFounder.jl/issues/18

Under the current state of PeaceFounder, administrators face a significant limitation: they lack the capability to terminate memberships. This function is crucial in various scenarios. For instance, when a member fails to submit necessary authenticity documents within the allotted time post-registration, their membership must be annulled. Additionally, this feature is vital for addressing privacy concerns, such as when members wish to withdraw and have their associated records deleted. Furthermore, an essential aspect of membership management involves issuing new credentials in cases where a member loses their device or experiences a security breach with their key being compromised.

The process of terminating a membership in PeaceFounder presents its own set of challenges. The core difficulty lies in the inability to link a member's real identity and their current pseudonym, which prevents the removal of it in subsequent braidings. This link is only known exclusively to the member's client device, as it only knows the private key that can generate them.

A straightforward approach to address this issue involves resetting the generator in the braidchain and taking identity pseudonyms of the membership certificates as inputs to subsequent braidings. However, this method presents a significant hurdle, particularly for larger organisations. Implementing this reset each time a member is terminated can be prohibitively expensive. In particular, taking into account that the frequency of membership termination cases increases proportionally with the number of members as well as the required compute to do braidings, making this approach to scale as $O(N^2)$. Therefore, a more sophisticated and nuanced solution is needed.

Extensions

In order to avoid over-commitment, the peacefounder project currently focuses on smaller-scale organisations. This implies that a single developer must be able to maintain the system, that coercion/bribery is not of the utmost importance, and that the electoral roll is not necessary to satisfy the requirements of a law. Thus, those features are not integrated into the current design and can be considered separately as system extensions.

Proof of participation

https://github.com/PeaceFounder/PeaceFounder.jl/issues/12

Some communities may wish to nudge their members to vote, providing benefits for those who have already cast a vote or punishing those who ignore democratic decision-making. In ordinary e-voting systems, that can be easily achieved through a voter’s registry. However, this is not possible for PeaceFounder because voters are completely anonymous when they cast a vote.

One way to address this issue is with a blind signature scheme. The voter takes his identity pseudonym, blinds it with a random factor and includes that in the vote when sent to the ballot box. The collector checks that the vote is valid and, if so, signs the blinded group element at the time when the vote is recorded in the ledger. The blind signature is reused if the voter has already cast a ballot.

The voter then receives an acknowledgement that the vote is permanently recorded in the chain together with the blind signature and timestamp. The voter unblinds the blind signature with its blinding factor and obtains a signature on his identity pseudonym as proof of participation. That can then be safely shown publicly for anyone who wants to see that the person has voted without being linked to the cast vote.

Selection's asymmetric encryption

https://github.com/PeaceFounder/PeaceFounder.jl/issues/16

To maintain the impartiality of auditors/monitors with regard to votes they oversee and further deter potential bribery attempts, an asymmetric encryption method for vote selection is advisable. Under this protocol, the voter's device encrypts a symmetric key asymmetrically and then proceeds to encrypt the vote selection using this symmetric key. The key and the encrypted selection are included in the vote, which is then signed using a pseudonym. Upon receiving the vote, after authenticating its signature, the system decrypts the symmetric key, followed by the vote selection. To ensure the decryption's integrity, a zero-knowledge proof is provided and subsequently published alongside the vote on the bulletin board.

Coerced vote tagging

https://github.com/PeaceFounder/PeaceFounder.jl/issues/16

A threat where coercers forcibly dictate voters' choices while confiscating their devices is a pressing concern beyond the PeaceFounder system. A common solution to such a problem is equipping voters with an option to create a secondary PIN code, which works exactly as the primary PIN code except that the votes are tagged as coerced.

To safeguard against coercers potentially discerning this distinction using a proxy vote submission method, the coercion tag can be asymmetrically encrypted as a group element before transmitting it to the ballot box collector. Upon receipt, the collector would record and then decrypt the coercion tag. A zero-knowledge proof of decryption would ensure the collector's integrity, published together with a vote on the bulletin board.

Votes are disclosed at the conclusion of the process, indicating any tags applied. By lengthening the gap between the tally announcement and the release of the votes, we can diminish the impact of coercive threats and deter unscrupulous voters from awaiting compensation, hinging on the assumption of the briber's credibility. Technically, this mechanism ensures receipt freeness until they appear on the ballot box ledger.

This strategy presumes that no adversarial entity has infiltrated the collector system. To mitigate such risks, deploying multiple collectors, to which voters are randomly pre-assigned, is advised. This introduces a level of inter-collector accountability, as aggregated results should align. Notably, while receipt freeness is limited, the method retains full transparency: all parties can validate the tally's accuracy and verify every vote's eligibility and unlinkability, as well as the validity of the coercion tag.

Sempled Electoral Roll Audits

https://github.com/PeaceFounder/PeaceFounder.jl/issues/17

In order to ensure the integrity of elections, it is crucial that independent auditors audit the legitimacy of members. However, the records that support the membership cannot be made public as it would violate the members' right to freedom of association and would also infringe on GDPR. Keeping these records confidential while ensuring they are sufficiently audited can be challenging and may require reducing openness to prevent any possible leaks.

To overcome this dilemma in favour of more openness, a sampling of the electoral roll could be used. A large enough sample size can provide sufficient confidence that a potentially corrupt registrar could not have affected the election result, whereas keeping it small reduces the impact of leaks from the auditors. This lowers the trust barrier and opens the electoral roll auditing for more independent parties.

Early leaked private key detection

In a situation where the adversary has acquired a member's private key, they can form valid votes that can be included in the bulletin board. To detect that a bitmask is included in the ballot box commit, which the voter retrieves together with consistency proofs. That allows us to see whether tallied votes have been cast from the member's device as it can look into the bitmask for tallied votes after the vote. However, when a member votes after the adversary, the bulletin board could inform about the fact in the receipt.

The problem is that showing on receipt whether the vote is a final submission considered for inclusion in the tally can impede the voter's ability to revote if the coercer/briber waits until the last minute before submitting their acquired vote. This circumvents a measure where publishing votes is delayed for an extended time after the tally is published for eroding trust in bribers and delaying punishment from coercers. Therefore, the response status needs to be asymmetrically encrypted.

The status code can be encrypted as a group element and decrypted on the voter's device. If the submitted vote is not final, the collector encrypts a group element representing status addressed to the pseudonym that cast the vote. The device receives the receipt, and as it only has the private key, the status code can be shown. That allows members to see early whether the vote was already cast with the provided sequence number and superseded it with possible recasting.

Sharded Ballots

In democratic processes, it's conceivable that voters may be presented with an extensive list of ballot questions to express their opinions. However, as evident with comprehensive surveys, there is a noticeable decline in response rates as the number of questions escalates. Further complicating matters is the phenomenon known as the 'voter's paradox,' wherein the impact of a singular vote diminishes in larger elections. Both challenges can be addressed by sharding lengthy ballots among the entire voter base.

In the PeaceFounder system, sharding is trivial due to votes being cast pseudonymously. The initial step in the sharding involves determining all feasible divisions of the ballot and methodically enumerating them. Subsequently, these shards are allocated to pseudonyms, achieved by systematically sorting and matching them in sequence.

Nevertheless, a pronounced security concern emerges. Suppose an adversary assumes control over the proposer and possesses knowledge of a select group of pseudonym owners and their inclinations. In that case, they can manipulate the election outcome by tailoring the proposal and shards. Specifically, critical questions can be allocated to a limited cohort, skewing results in their favour.

To counteract this vulnerability, it's imperative for the proposer to commit to both the ballot and its associated shards, followed by a lottery to randomise the pseudonym list. Leveraging a DRAND service, which collaborates with multiple entities to execute threshold decryption, ensures the generation of predetermined, incorruptible random numbers [...]. These numbers subsequently serve as salt for hashing pseudonyms, which are sorted and allocated to shards accordingly. A critical aspect of this method is making sure the proposal is committed before the lottery result is announced to prevent adversaries from taking advantage of waiting for a favourable lottery outcome. This necessitates the involvement of auditors/monitors to timestamp the braidchain ledger commitments externally.

+

Another pillar that is necessary for ensuring democratic elections is to prevent coercion and vote buying. A significant risk to the PeaceFounder system is for a briber to ask members to forward their votes through a proxy channel they control. To counter this threat, the bulletin board hides the actual votes, showing only their hashes, and gives voters an option to revote, ensuring both receipt freeness and vote fairness. A sequence number along the vote ensures that only the latest cast vote on the device matters.

This method undermines the confidence of vote buyers and coercers, as it prevents them from ensuring that the votes they've acquired will be counted in the final tally. As a consequence, they can only return bribes after votes are published on the bulletin board. (During the vote, only receipt hashes are published on the bulletin board. This serves to both commit the votes while maintaining fairness and receipt-freeness.) This arrangement erodes the credibility of bribers and coercers, making it less likely for voters to engage with them in such transactions due to the lack of a guaranteed positive/negative outcome.

A secondary concern is the potential for a coercer to ask an individual to show how they had voted on their device. To address this, only a receipt is shown. However, this receipt can be linked to the specific vote on the bulletin board. If coercion becomes a significant threat, the receipt can be visible only briefly, such as 30 minutes after casting a vote. During this window, members can manually record their details in a logbook. While this approach may reduce user-friendliness, it still serves as a robust deterrent against malware.

Malware and spyware detection

A PICTURE WITH  A RECEIPT

The last piece of the puzzle is malware and spyware resistance. An adversary could issue votes without compromising the voter's device in case of key leakage. To counter this, every vote includes a sequence number, which records evidence on the bulletin board when a vote is cast from the voter's device. Moreover, if a vote with a sequence number of one is already on the ledger, the first will override any subsequent vote with the same sequence number. This mechanism prevents malware from silently replacing inactive voter's choices.

After voting concludes and the results are published, each voter receives a bitmask of the votes included in the final tally, along with consistency proofs. Given that this approach is scalable (e.g., 1kB can handle 8192 votes, and bit compression can further reduce size), voters device's compare this bitmask with the index from their most recent vote receipt. This allows them to detect any malware activity and display an alert to the voter.

To ensure the voting process's integrity, the voter's device must remain trustworthy. With the presence of malware, there's a risk that the device could falsely reassure the voter that their vote is cast as intended. To counter this threat, after the vote is submitted, the voter receives a receipt containing a timestamp of the vote's record, the pseudonym under which it was cast, and the index where the vote resides on the ledger. Once voting concludes and all votes are disclosed on the bulletin board, the voter can cross-reference their receipt with the bulletin board, verifying that the vote at the provided index aligns with their choice and matches the timestamp when the vote was cast, as well as checking that it was included in the final tally. By maintaining a written record, voters can ensure the accuracy of their vote, safeguarding against malware alterations, unauthorised revoting, or any attempts to redirect multiple voters to a singular vote.

However, it's essential to acknowledge that voters can only detect malware interference post-vote when comparing their receipt to the bulletin board. Additionally, a voter cannot provide evidence to others that their vote was compromised by malware, which means these instances aren't audited within the PeaceFounder system. As a result, members are encouraged and are responsible for utilising more secure devices less susceptible to malware attacks. For more advanced threats, like a briber mandating malware installation for monitoring or extracting the master key, the use of tamper-resistant hardware becomes essential – an extension larger organisations or states might consider.

Implementation details and responsibilities

To illustrate the responsibilities of different entities and the structure of the communication channels, we've provided a detailed diagram. In this representation, arrows indicate which entity holds responsibility for specific resources. The primary mode of communication is facilitated through JSON within an HTTP request/reply. The JSON is also chosen as a canonical byte string format for data signing, which is selected over the ASN1 DER format due to development resource constraints.

The architecture bifurcates the bulletin board into two distinct ledgers: the braidchain and the ballot boxes. This differentiation arises from the disparate pacing and metadata requirements of records. Additionally, casting votes remains inconsequential to the braidchain's state, justifying the ledger division.

Authorised entities, namely the braidchain recorder and the ballot box collector, as specified in the guardian-issued DemeSpec record, oversee each ledger. These controllers uphold the integrity of newly added records, ensuring their coherence with the existing state. For instance, votes must adhere to a specified time window and need to be appropriately signed with member pseudonyms. Braidchain transactions demand more intricate state management, which will be described later.

In the diagram, arrows necessitating anonymous channels are designated with a TOR label originating from the member. This is a countermeasure against potential adversaries attempting to link votes to members via IP addresses. Although alternative network anonymising solutions exist, TOR is the most prominent, and together with the recent release of the Arti project for Rust, it is ideal for client-side applications [...].

Members can view the bulletin board records through the HTTP Facade, which displays them in a browser-friendly HTML. This provides a secondary channel to verify that votes are cast as intended and counted as cast. A pure JavaScript-based HTTP facade is possible, which can be hosted on a static website, simplifying deployment.

It's imperative to recognise the absence of TLS in all communications. This choice stems from the fact that data from the bulletin board is supported with a signature on Merkle tree root, rendering requests tamper-proof. Moreover, using TLS session resumption for anonymous interactions between members and the bulletin board would unintentionally make the system vulnerable to DDOS attacks during the key establishment phase. Furthermore, eliminating the need for certificate issuance and management streamlines system maintenance and deployment, enhancing usability.

Planed Core Features

The PeaceFounder system is actively focusing on integrating key features in its upcoming iterations to enhance transparency. While not exhaustive, the current list includes well-defined proposals ready for implementation.

PeaceFounderBB

https://github.com/PeaceFounder/PeaceFounder.jl/issues/22

A small democratic community often faces the challenge of limited resources, particularly when it comes to hosting bulletin board data or maintaining a comprehensive website for public record access. However, a recent trend offers a practical solution with static website hosting platforms. These platforms allow the creation of a static website directly from source code stored in a git repository without the hassle of setting up and managing certificates. A popular example is GitHub Pages, which simplifies deployment using action scripts to compile websites from sources.

Integrating a GitHub workflow to compile a webpage makes it an ideal platform for hosting a bulletin board interface. This setup has a dual advantage. The GitHub repository can serve as an authentic storage space for bulletin board records. Secondly, these records are easily accessible to the public via a web interface. Continuous integration further enhances this with build scripts, ensuring the integrity and verification of the bulletin board's contents. Those interested in verifying the bulletin board's integrity independently can either fork the repository and run the action script or clone the data locally.

Additionally, the use of the Zenodo repository enriches this system. Zenodo provides excellent archival workflows and the capability to generate a DOI link. This link serves a similar purpose to dataset references in scientific research, offering a reliable and citable record.

Cast as intended verification during the vote

https://github.com/PeaceFounder/PeaceFounder.jl/issues/21

At present, voters can only confirm that their vote has been cast as intended and accurately counted after the vote has ended and the votes are published. As the publication of votes can be delayed as a measure against coercion, it might discourage voters' participation from verifying that their vote is indeed cast as intended and counted as cast. The key issue lies in the possibility of unnoticed malware on voting devices. If voters don't verify their votes, the likelihood of malware affecting a significant number of votes without detection increases. Thus, having a procedure that enables immediate verification of the voting process is essential to engage more voters to check their votes.

The PeaceFounder system can address this by providing voters with a token displayed on the client's screen for vote verification. This token can be used in a web browser to confirm that the vote has been cast as intended. It also indicates if the vote has been superseded by a subsequent vote or one with a higher sequence number, which may occur if the member's key is compromised. To maintain receipt-freeness, the token remains valid for only a short period, such as 15 minutes. The expiration is crucial; it allows voters to verify their votes while preventing coercion or bribery attempts. It also hinders any unsolicited checks on voters' choices.

Evidence auditing with terminal API

https://github.com/PeaceFounder/PeaceFounder.jl/issues/19

The PeaceFounder system is universally verifiable, a feature ensuring that every vote is cryptographically proven to come from a registered member, even if all involved parties are corrupt. To mitigate the influence of coercion or bribery, the authority can strategically delay the publication of votes, which weakens the link between coercers and their subjects before the voters lose receipt freeness. After the votes are published, every aspect of the voting process is transparent: all proofs of votes are made publicly available. This transparency allows any interested party to audit the election results and, at their convenience, independently reproduce the announced tally.

Membership Termination

https://github.com/PeaceFounder/PeaceFounder.jl/issues/18

Under the current state of PeaceFounder, administrators face a significant limitation: they lack the capability to terminate memberships. This function is crucial in various scenarios. For instance, when a member fails to submit necessary authenticity documents within the allotted time post-registration, their membership must be annulled. Additionally, this feature is vital for addressing privacy concerns, such as when members wish to withdraw and have their associated records deleted. Furthermore, an essential aspect of membership management involves issuing new credentials in cases where a member loses their device or experiences a security breach with their key being compromised.

The process of terminating a membership in PeaceFounder presents its own set of challenges. The core difficulty lies in the inability to link a member's real identity and their current pseudonym, which prevents the removal of it in subsequent braidings. This link is only known exclusively to the member's client device, as it only knows the private key that can generate them.

A straightforward approach to address this issue involves resetting the generator in the braidchain and taking identity pseudonyms of the membership certificates as inputs to subsequent braidings. However, this method presents a significant hurdle, particularly for larger organisations. Implementing this reset each time a member is terminated can be prohibitively expensive. In particular, taking into account that the frequency of membership termination cases increases proportionally with the number of members as well as the required compute to do braidings, making this approach to scale as $O(N^2)$. Therefore, a more sophisticated and nuanced solution is needed.

Extensions

In order to avoid over-commitment, the peacefounder project currently focuses on smaller-scale organisations. This implies that a single developer must be able to maintain the system, that coercion/bribery is not of the utmost importance, and that the electoral roll is not necessary to satisfy the requirements of a law. Thus, those features are not integrated into the current design and can be considered separately as system extensions.

Proof of participation

https://github.com/PeaceFounder/PeaceFounder.jl/issues/12

Some communities may wish to nudge their members to vote, providing benefits for those who have already cast a vote or punishing those who ignore democratic decision-making. In ordinary e-voting systems, that can be easily achieved through a voter’s registry. However, this is not possible for PeaceFounder because voters are completely anonymous when they cast a vote.

One way to address this issue is with a blind signature scheme. The voter takes his identity pseudonym, blinds it with a random factor and includes that in the vote when sent to the ballot box. The collector checks that the vote is valid and, if so, signs the blinded group element at the time when the vote is recorded in the ledger. The blind signature is reused if the voter has already cast a ballot.

The voter then receives an acknowledgement that the vote is permanently recorded in the chain together with the blind signature and timestamp. The voter unblinds the blind signature with its blinding factor and obtains a signature on his identity pseudonym as proof of participation. That can then be safely shown publicly for anyone who wants to see that the person has voted without being linked to the cast vote.

Selection's asymmetric encryption

https://github.com/PeaceFounder/PeaceFounder.jl/issues/16

To maintain the impartiality of auditors/monitors with regard to votes they oversee and further deter potential bribery attempts, an asymmetric encryption method for vote selection is advisable. Under this protocol, the voter's device encrypts a symmetric key asymmetrically and then proceeds to encrypt the vote selection using this symmetric key. The key and the encrypted selection are included in the vote, which is then signed using a pseudonym. Upon receiving the vote, after authenticating its signature, the system decrypts the symmetric key, followed by the vote selection. To ensure the decryption's integrity, a zero-knowledge proof is provided and subsequently published alongside the vote on the bulletin board.

Coerced vote tagging

https://github.com/PeaceFounder/PeaceFounder.jl/issues/16

A threat where coercers forcibly dictate voters' choices while confiscating their devices is a pressing concern beyond the PeaceFounder system. A common solution to such a problem is equipping voters with an option to create a secondary PIN code, which works exactly as the primary PIN code except that the votes are tagged as coerced.

To safeguard against coercers potentially discerning this distinction using a proxy vote submission method, the coercion tag can be asymmetrically encrypted as a group element before transmitting it to the ballot box collector. Upon receipt, the collector would record and then decrypt the coercion tag. A zero-knowledge proof of decryption would ensure the collector's integrity, published together with a vote on the bulletin board.

Votes are disclosed at the conclusion of the process, indicating any tags applied. By lengthening the gap between the tally announcement and the release of the votes, we can diminish the impact of coercive threats and deter unscrupulous voters from awaiting compensation, hinging on the assumption of the briber's credibility. Technically, this mechanism ensures receipt freeness until they appear on the ballot box ledger.

This strategy presumes that no adversarial entity has infiltrated the collector system. To mitigate such risks, deploying multiple collectors, to which voters are randomly pre-assigned, is advised. This introduces a level of inter-collector accountability, as aggregated results should align. Notably, while receipt freeness is limited, the method retains full transparency: all parties can validate the tally's accuracy and verify every vote's eligibility and unlinkability, as well as the validity of the coercion tag.

Sempled Electoral Roll Audits

https://github.com/PeaceFounder/PeaceFounder.jl/issues/17

In order to ensure the integrity of elections, it is crucial that independent auditors audit the legitimacy of members. However, the records that support the membership cannot be made public as it would violate the members' right to freedom of association and would also infringe on GDPR. Keeping these records confidential while ensuring they are sufficiently audited can be challenging and may require reducing openness to prevent any possible leaks.

To overcome this dilemma in favour of more openness, a sampling of the electoral roll could be used. A large enough sample size can provide sufficient confidence that a potentially corrupt registrar could not have affected the election result, whereas keeping it small reduces the impact of leaks from the auditors. This lowers the trust barrier and opens the electoral roll auditing for more independent parties.

Early leaked private key detection

In a situation where the adversary has acquired a member's private key, they can form valid votes that can be included in the bulletin board. To detect that a bitmask is included in the ballot box commit, which the voter retrieves together with consistency proofs. That allows us to see whether tallied votes have been cast from the member's device as it can look into the bitmask for tallied votes after the vote. However, when a member votes after the adversary, the bulletin board could inform about the fact in the receipt.

The problem is that showing on receipt whether the vote is a final submission considered for inclusion in the tally can impede the voter's ability to revote if the coercer/briber waits until the last minute before submitting their acquired vote. This circumvents a measure where publishing votes is delayed for an extended time after the tally is published for eroding trust in bribers and delaying punishment from coercers. Therefore, the response status needs to be asymmetrically encrypted.

The status code can be encrypted as a group element and decrypted on the voter's device. If the submitted vote is not final, the collector encrypts a group element representing status addressed to the pseudonym that cast the vote. The device receives the receipt, and as it only has the private key, the status code can be shown. That allows members to see early whether the vote was already cast with the provided sequence number and superseded it with possible recasting.

Sharded Ballots

In democratic processes, it's conceivable that voters may be presented with an extensive list of ballot questions to express their opinions. However, as evident with comprehensive surveys, there is a noticeable decline in response rates as the number of questions escalates. Further complicating matters is the phenomenon known as the 'voter's paradox,' wherein the impact of a singular vote diminishes in larger elections. Both challenges can be addressed by sharding lengthy ballots among the entire voter base.

In the PeaceFounder system, sharding is trivial due to votes being cast pseudonymously. The initial step in the sharding involves determining all feasible divisions of the ballot and methodically enumerating them. Subsequently, these shards are allocated to pseudonyms, achieved by systematically sorting and matching them in sequence.

Nevertheless, a pronounced security concern emerges. Suppose an adversary assumes control over the proposer and possesses knowledge of a select group of pseudonym owners and their inclinations. In that case, they can manipulate the election outcome by tailoring the proposal and shards. Specifically, critical questions can be allocated to a limited cohort, skewing results in their favour.

To counteract this vulnerability, it's imperative for the proposer to commit to both the ballot and its associated shards, followed by a lottery to randomise the pseudonym list. Leveraging a DRAND service, which collaborates with multiple entities to execute threshold decryption, ensures the generation of predetermined, incorruptible random numbers [...]. These numbers subsequently serve as salt for hashing pseudonyms, which are sorted and allocated to shards accordingly. A critical aspect of this method is making sure the proposal is committed before the lottery result is announced to prevent adversaries from taking advantage of waiting for a favourable lottery outcome. This necessitates the involvement of auditors/monitors to timestamp the braidchain ledger commitments externally.

diff --git a/dev/schedulers/index.html b/dev/schedulers/index.html index 9544c56..3834468 100644 --- a/dev/schedulers/index.html +++ b/dev/schedulers/index.html @@ -20,6 +20,6 @@ catch retry!(scheduler) end -end

In the event loop one manages a state machine which can succed and fail. If it succeds a scheduled time is taken out from the scheduler and proceeds waiting the next event. In the case event at scheduled time had failed the scheduler is notified with retry! method and attempts to run the event loop againafter retry_interval until succeeds.

source
Base.lockMethod
lock(scheduler::Scheduler)

Lock a scheduler. This is necessary to avoid simultanous modifications of the schedule field. Note that other Scheduler fields are not protected with the lock as thoose are considered internal.

source
Base.notifyMethod
notify(scheduler::Scheduler[, value])

Notify a scheduler with a value which is returned at wait.

source
Base.waitMethod
wait(scheduler::Scheduler)

Wait until next event is reached and return it's value. In the case event have run through smoothelly the scheduler event is droped with the next wait call. See also retry! method.

source
PeaceFounder.Schedulers.next_eventMethod
next_event(scheduler::Scheduler)

Return the next event in seconds and coresponding event value. Return nothing if no events are scheduled.

source
PeaceFounder.Schedulers.retry!Method
retry!(scheduler::Scheduler)

Notifies the scheduler that event have run unsucesfully which reschedules it after specified retry_time(See Scheduler).

source
PeaceFounder.Schedulers.schedule!Method
schedule!(scheduler::Scheduler, timestamp::DateTime[, value])

Schedule an event at timestamp with a provided value. To avoid messing up a schedule acquire a scheduler's lock before adding the event as:

lock(scheduler) do
+end

In the event loop one manages a state machine which can succed and fail. If it succeds a scheduled time is taken out from the scheduler and proceeds waiting the next event. In the case event at scheduled time had failed the scheduler is notified with retry! method and attempts to run the event loop againafter retry_interval until succeeds.

source
Base.lockMethod
lock(scheduler::Scheduler)

Lock a scheduler. This is necessary to avoid simultanous modifications of the schedule field. Note that other Scheduler fields are not protected with the lock as thoose are considered internal.

source
Base.notifyMethod
notify(scheduler::Scheduler[, value])

Notify a scheduler with a value which is returned at wait.

source
Base.waitMethod
wait(scheduler::Scheduler)

Wait until next event is reached and return it's value. In the case event have run through smoothelly the scheduler event is droped with the next wait call. See also retry! method.

source
PeaceFounder.Schedulers.next_eventMethod
next_event(scheduler::Scheduler)

Return the next event in seconds and coresponding event value. Return nothing if no events are scheduled.

source
PeaceFounder.Schedulers.retry!Method
retry!(scheduler::Scheduler)

Notifies the scheduler that event have run unsucesfully which reschedules it after specified retry_time(See Scheduler).

source
PeaceFounder.Schedulers.schedule!Method
schedule!(scheduler::Scheduler, timestamp::DateTime[, value])

Schedule an event at timestamp with a provided value. To avoid messing up a schedule acquire a scheduler's lock before adding the event as:

lock(scheduler) do
     schedule!(scheduler, now() + Second(1), value)
-end
source
PeaceFounder.Schedulers.waituntilMethod
waituntil(time::DateTime)

Waits until given time is reached.

source
+endsource
PeaceFounder.Schedulers.waituntilMethod
waituntil(time::DateTime)

Waits until given time is reached.

source
diff --git a/dev/schema/index.html b/dev/schema/index.html index b33cf92..78141eb 100644 --- a/dev/schema/index.html +++ b/dev/schema/index.html @@ -29,4 +29,4 @@ dom_id: '#swagger-ui', }); }; - + diff --git a/dev/setup/index.html b/dev/setup/index.html index c15a4d5..e61d5c5 100644 --- a/dev/setup/index.html +++ b/dev/setup/index.html @@ -66,4 +66,4 @@ ) |> approve(PROPOSER) -ack = Mapper.submit_chain_record!(proposal)

Notice that state(commit) is added to the proposal. This anchors the relative generator on which the votes are cast.

+ack = Mapper.submit_chain_record!(proposal)

Notice that state(commit) is added to the proposal. This anchors the relative generator on which the votes are cast.