Пример #1
0
def GetPointMatrix(beta_bold, s_bold, r_bold, secparams):
    """
    Algorithm 7.26: Computes the k-by-s matrix P_s = (P_ij)k x s of the points obtained from
    the s authorities for the selection s. The points are derived from the messages included
    in the OT responses beta = (beta_1, ..., beta_s)

    Args:
        beta_bold (list of Response):       Oblivious Transfer Responses
        k_bold (list of int):               Number of selections
        s_bold (list of int):               Selections
        r_bold (list of mpz):               Randomizations
        secparams (SecurityParams):         Collection of public security parameters

    Returns:
        list                                Points
    """

    AssertList(beta_bold)
    AssertList(s_bold)
    AssertList(r_bold)
    AssertClass(secparams, SecurityParams)

    s = len(beta_bold)
    P_s_bold = [None] * s

    for i in range(s):
        P_s_bold[i] = GetPoints(beta_bold[i], s_bold, r_bold, secparams)

    # Check that the length of P_s is s x k
    for elem in P_s_bold:
        assert len(elem) == len(s_bold)

    return P_s_bold
Пример #2
0
def GetDecryptions(e_bold, B_prime_bold, secparams):
    """
    Algorithm 7.53: Computes the list of decryptions m = (m_1, ..., m_N) by assembling the
    partial decryptions b_prime_ij obtained from s different authorities.

    Args:
       e_bold (list of ElGamalEncryption): ElGamal encryptions
       B_prime_bold (list of list):        Partial decryptions
       secparams (SecurityParams):         Collection of public security parameters

    Returns:
        list of mpz                        Partial decryptions
    """

    AssertList(e_bold)
    AssertList(B_prime_bold)
    AssertClass(secparams, SecurityParams)

    m_bold = []
    N = len(e_bold)
    for i in range(N):
        b_prime_i = mpz(1)
        for j in range(secparams.s):
            b_prime_i = (b_prime_i * B_prime_bold[j][i]) % secparams.p

        m_bold.append((e_bold[i][0] * gmpy2.invert(b_prime_i, secparams.p)) %
                      secparams.p)

    return m_bold
Пример #3
0
def GetFinalization(v, P_bold, B, secparams):
    """
    Algorithm 7.36: Computes the finalization code F_v for voter v from the given points p_i
    and returns F_v together with the randomizations r_v used in the OT response.

    Args:
        v (int):                             Voter index
        p_bold (list of points):             Points
        B (list):                            Ballot list
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        tuple:                               delta (F_v, r_bold_v)
    """

    AssertInt(v)
    AssertList(P_bold)
    AssertList(B)
    AssertClass(secparams, SecurityParams)


    p_bold_v = P_bold[v]
    F = Truncate(RecHash(p_bold_v, secparams), secparams.L_F)

    for i in range(len(B)):
        if (B[i].voterId == v):
            z_i = B[i].randomizations

    delta = (F, z_i)
    return delta
Пример #4
0
def GenPermutationCommitment(psi, h_bold, secparams):
    """
    Algorithm 7.45: Generates a commitment c = com(psi, r_bold) to a permutation psi by committing
    to the columns of the corresponding permutation matrix. This algorithm is used in Alg. 7.44.

    Args:
       psi (list of int):                   Permutation
       h_bold (list of mpz):                Independent generators h = (h_1, ..., h_N), h_i in G_q\{1}
       secparams (SecurityParams):          Collection of public security parameters

    Returns:
        tuple:                              (c,r)
    """

    AssertList(psi)
    AssertList(h_bold)
    AssertClass(secparams, SecurityParams)

    r_bold = [None] * len(psi)
    c_bold = [None] * len(psi)

    N = len(psi)
    for i in range(N):
        r_bold[psi[i]] = randomMpz(secparams.q, secparams)
        c_bold[psi[i]] = (gmpy2.powmod(secparams.g, r_bold[psi[i]],
                                       secparams.p) * h_bold[i]) % secparams.p

    return (c_bold, r_bold)
Пример #5
0
def CheckShuffleProofs(pi_bold, e_0_bold, E_bold, pk, i, secparams):
    """
    Algorithm 7.47: Checks if a chain of shuffle proofs generated by s different authorities is
    correct.

    Args:
       pi_bold (list of ShuffleProof):          Shuffle proof
       e_0_bold (list):                         ElGamal Encryptions
       E_bold (list):                           Shuffled ElGamal Encryptions
       pk (mpz):                                Encryption key pk
       i (int):                                 Authority index
       secparams (SecurityParams):              Collection of public security parameters

    Returns:
        bool
    """
    AssertList(pi_bold)
    AssertList(e_0_bold)
    AssertList(E_bold)
    AssertMpz(pk)
    AssertInt(i)
    AssertClass(secparams, SecurityParams)

    N = len(e_0_bold)
    e_bold_tmp = []
    e_bold_tmp.append(e_0_bold)
    e_bold_tmp.extend(E_bold)

    for j in range(secparams.s):
        if i != j:
            if not CheckShuffleProof(pi_bold[j], e_bold_tmp[j], e_bold_tmp[j+1],pk, secparams):
                return False
    return True
Пример #6
0
def CheckDecryptionProofs(pi_prime_bold, pk_bold, e_bold, B_prime_bold,
                          secparams):
    """
    Algorithm 7.51: Checks if the decryption proofs generated by s different authorities are
    correct.

    Args:
        pi_prime_bold (list of DecryptionProof):    Decryption proofs
        pk_bold (list of mpz):                      Encryption key shares
        e_bold (list of ElGamalEncryption):         ElGamal encryptions
        B_prime_bold (list):                        Partial decryptions
        secparams (SecurityParams):                 Collection of public security parameters

    Returns:
        bool
    """
    AssertList(pi_prime_bold)
    AssertList(pk_bold)
    AssertList(e_bold)
    AssertList(B_prime_bold)
    AssertClass(secparams, SecurityParams)

    s = len(pk_bold)
    for j in range(s):
        if not CheckDecryptionProof(pi_prime_bold[j], pk_bold[j], e_bold,
                                    B_prime_bold[j], secparams):
            return False
    return True
Пример #7
0
def GetReturnCodes(s_bold, P_s_bold, secparams):
    """
    Algorithm 7.28: Computes the k return codes rcs = (RC_s_1, ... , RC_s_k) for the selected
    candidates by combining the hash values of the transferred points p_ij in P_s from different authorities.

    Args:
        s_bold (list of int):                Selections
        P_s_bold (list of Point):            Points
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        list                                 Points
    """

    AssertList(s_bold)
    AssertList(P_s_bold)
    AssertClass(secparams, SecurityParams)

    rc_s_bold = []

    k = len(s_bold)
    s = len(P_s_bold)

    for i in range(k):
        R_j = []

        for j in range(s):
            R_j.append(Truncate(RecHash(P_s_bold[j][i], secparams), secparams.L_R))

        R = MarkByteArray(XorByteArray(R_j), s_bold[i], secparams.n_max)
        rc_s_bold.append(ByteArrayToString(R, secparams.A_R))

    return rc_s_bold
Пример #8
0
def GetEncryptions(B, C, n_bold, w_bold, secparams):
    """
    Algorithm 7.40: Computes a sorted list of ElGamal encryptions from the list of submitted
    ballots, for which a valid confirmation is available. Sorting this list is necessary
    to guarantee a unique order. For this, we define a total order over G_q^2 by e_i <= e_j
    <-> (a_i < a_j) or (a_i = a_a and b_i <= b_j), for e_i = (a_i, b_i) and e_j = (a_j, b_j)

    Args:
        B (list of Ballot):                Ballot List
        C (list of tuple):                 Confirmation list C
        n_bold (list):                     Number of candidates n
        w_bold (list):                     Counting circles w
        secparams (SecurityParams):         Collection of public security parameters


    Returns:
        list of ElGamalEncryption:         ElGamal Encryptions
    """

    AssertList(B)
    AssertList(C)
    AssertList(n_bold)
    AssertList(w_bold)
    AssertClass(secparams, SecurityParams)

    n = sum(n_bold)
    w = max(w_bold)
    p_bold = GetPrimes(n + w, secparams)
    i = 0

    e_bold = []
    for j in range(len(B)):
        #(v, alpha, z) = B[j]
        v = B[j].voterId
        alpha = B[j].ballot
        z = B[j].randomizations

        a_1 = mpz(1)
        a_2 = mpz(1)
        if HasConfirmation(v, C, secparams):
            a_j_1_product = mpz(1)
            for j in range(len(alpha.a_bold)):
                a_j_1_product = (a_j_1_product *
                                 alpha.a_bold[j][0]) % secparams.p
                a_2 = (a_2 * alpha.a_bold[j][1]) % secparams.p
            a_1 = (p_bold[(n - 1) + w_bold[v]] * a_j_1_product) % secparams.p
            e_bold.append(ElGamalEncryption(a_1, a_2))

            i += 1

    e_bold.sort(key=lambda enc: (enc.a, enc.b), reverse=False)

    return e_bold
Пример #9
0
def GetVotes(m_bold, n_bold, w_bold, secparams):
    """
    Algorithm 7.54: Computes the election result matrix V = (v_ij) N x n from the products
    of encoded selections m = (m_1, ..., m_N) by retrieving the prime factors of each mi.
    Each resulting vector vi represents somebody’s vote, and each value vij  1 represents
    somebody’s vote for a specific candidate j in {1, ..., n}

    Args:
       m_bold (List):                       Products of encoded selections m = (m_1, ..., m_N), m_i in G_q
       n_bold (List):                       Number of candidates n >= 2
       w_bold (List):                       Counting circles w = (w_1, ..., w_N_E), w_i \in N
       secparams (SecurityParams):          Collection of public security parameters

    Returns:
        list of int:                        Election result matrix V = (v_ij) N x n
    """

    AssertList(m_bold)
    for m in m_bold:
        assert IsMember(m, secparams), "m_bold elements must be in G_q"
    AssertList(n_bold)
    for n in n_bold:
        assert n >= 2, "n must be greater than or equal 2"
    AssertList(w_bold)
    AssertClass(secparams, SecurityParams)

    n = sum(n_bold)
    w = max(w_bold)
    N = len(m_bold)

    V_bold = []
    W_bold = []

    p_bold = GetPrimes(n + w, secparams)
    for i in range(N):
        v_bold_i = [None] * n
        for j in range(n):
            if m_bold[i] % p_bold[j] == 0:
                v_bold_i[j] = 1
            else:
                v_bold_i[j] = 0
        V_bold.append(v_bold_i)

        w_bold_i = [None] * w
        for j in range(w):
            if m_bold[i] % p_bold[n + j] == 0:
                w_bold_i[j] = 1
            else:
                w_bold_i[j] = 0
        W_bold.append(w_bold_i)

    return (V_bold, W_bold)
Пример #10
0
def GetPoints(beta, s_bold, r_bold, secparams):
    """
    Algorithm 7.26: Computes the k-by-s matrix P_s = (P_ij)k x s of the points obtained from
    the s authorities for the selection s. The points are derived from the messages included
    in the OT responses beta = (beta_1, ..., beta_s)

    Args:
        beta (Response):                     Oblivious Transfer Response
        s_bold (list of int):                Selections
        r_bold (list of mpz):                Randomizations
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        list                                 Points
    """

    AssertClass(beta, Response)
    AssertList(s_bold)
    AssertList(r_bold)
    AssertClass(secparams, SecurityParams)

    (b_bold, C_bold, d) = beta

    k = len(s_bold)

    l_M = ceil(secparams.L_M // secparams.L)

    p_bold = []

    for j in range(k):
        k_j = (b_bold[j] *
               gmpy2.powmod(d, -r_bold[j], secparams.p)) % secparams.p

        K_j = bytearray()
        for c in range(l_M):
            K_j += RecHash([k_j, c], secparams)

        K_j = Truncate(K_j, secparams.L_M)
        M_j = XorByteArray([C_bold[s_bold[j]][j], K_j])
        x_j = ToInteger(Truncate(M_j, secparams.L_M // 2))
        y_j = ToInteger(Skip(M_j, secparams.L_M // 2))

        if x_j >= secparams.p_prime or y_j >= secparams.p_prime:
            return None

        p_bold.append(Point(x_j, y_j))

    return p_bold
Пример #11
0
def GetVotingPage(v, c_bold, n_bold, k_bold):
    """
    Algorithm 7.17: Computes a string P in A_UCS^*, which represents the voting page displayed
    to voter. Specifying the details of presenting the information on the voting page is beyond
    the scope of this document.

    Args:
        v (int):         Voter index
        c_bold (list):   Candidate descriptions c = (C_1, ..., C_n), c_v ∈ A_UCS^*
        n_bold (list):   Number of candidates n =(n_1, ..., n_t), n_j >= 2
        k_bold (list):   Number of selections k = (k_1, ..., k_t), 0 <= k_j < n_j

    Returns:
        string:     String P ∈ A_UCS^* displayed to the voter
    """

    AssertInt(v)
    AssertList(c_bold)
    AssertList(n_bold)
    AssertList(k_bold)

    electionString = ""
    candidateIndex = 0

    for j in range(len(k_bold)):
        electionString += "# Election {}\n".format(j)

        for l in range(n_bold[j]):
            electionString += "Candidate {}: {}\n".format(
                candidateIndex, c_bold[candidateIndex])
            candidateIndex += 1

        electionString += "You can make {} selection(s) for this particular election\n\n".format(
            k_bold[j])

    P = \
"""
Voting page for voter {v}:

Simultaneous elections:

{elections}
""".format(
          v = v
        , elections = electionString
        )

    return P
Пример #12
0
def GenQuery(q_bold, pk, secparams):
    """
    Algorithm 7.20: Generates an OT query a from the prime numbers representing the
    voter's selection and a for a given public encryption key (which serves as a
    generator).

    Args:
        q_bold (list):                       Selected primes
        pk (mpz):                            Encryption key
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        (a, r):                              The OT query
    """

    AssertList(q_bold)
    AssertMpz(pk)
    AssertClass(secparams, SecurityParams)

    k = len(q_bold)
    a_bold = [None] * k
    r_bold = [None] * k

    for j in range(k):
        r_bold[j] = randomMpz(secparams.q, secparams)
        a_j_1 = (q_bold[j] *
                 gmpy2.powmod(pk, r_bold[j], secparams.p)) % secparams.p
        a_j_2 = gmpy2.powmod(secparams.g, r_bold[j], secparams.p)
        a_bold[j] = (a_j_1, a_j_2)

    return (a_bold, r_bold)
Пример #13
0
def GenShuffle(e_bold, pk, secparams):
    """
    Algorithm 7.41: Generates a random permutation psi and uses it to shuffle a given
    list e = (e_1, ..., e_n) of ElGamal encryptions e_i = (a_i, b_i) in G_q^2.
    With psi_N = {(j_1, ..., j_N) : j_i in {1,...,N}, j_i_1 != j_i_2, forAll i_1 != i2}
    we denote the set of all N! possible permutations of the values {1, ..., N}

    Args:
       e_bold (list):                      ElGamal Encryptions
       pk (mpz):                           Encryption key pk
       secparams (SecurityParams):         Collection of public security parameters

    Returns:
        tuple                              (e_prime, r_prime, psi)
    """

    AssertList(e_bold)
    AssertMpz(pk)

    psi_bold = GenPermutation(len(e_bold), secparams)
    e_prime_bold = []
    r_prime_bold = []

    N = len(e_bold)
    for i in range(N):
        (e_prime_i, r_prime_i) = GenReEncryption(e_bold[i], pk, secparams)
        e_prime_bold.append(e_prime_i)
        r_prime_bold.append(r_prime_i)

    e_prime_shuffled = [None] * len(e_prime_bold)
    for i in range(N):
        e_prime_shuffled[i] = e_prime_bold[psi_bold[i]]
    return (e_prime_shuffled, r_prime_bold, psi_bold)
Пример #14
0
def GetValue(p_bold, secparams):
    """
    Algorithm 7.32: Computes a polynomial A(X) of degree k - 1 from given
    points p = (p_1, ..., p_k) using Lagrange's interpolation method and returns
    the value y = A(0).

    Args:
        p_bold (list of points):             Given points
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        y: y = A(0) of polynomial A(X)
    """

    AssertList(p_bold)
    AssertClass(secparams, SecurityParams)

    y = 0
    k = len(p_bold)

    for i in range(k):
        n = mpz(1)
        d = mpz(1)

        for j in range(k):
            if i != j:
                n = (n * p_bold[j].x) % secparams.p_prime
                d = (d * (p_bold[j].x - p_bold[i].x)) % secparams.p_prime

        y = (y + p_bold[i].y * n *
             gmpy2.invert(d, secparams.p_prime)) % secparams.p_prime

    return y
Пример #15
0
def GenSecretVoterData(p_bold, secparams):
    """
    Algorithm 7.10: Generates the secret data for a single voter, which is sent to the voter prior to an election event via the printing authority.

    Args:
       p_bold (list):                      A list of n points = (p_1, ... , p_n) in Z_p'
       secparams (SecurityParams):         Collection of public security parameters

    Returns:
       tuple:                              Secret voter data (x,y,F,r)
    """

    AssertList(p_bold)
    AssertClass(secparams, SecurityParams)

    q_hat_apos_x = floor(secparams.q_hat_X // secparams.s)
    q_hat_apos_y = floor(secparams.q_hat_Y // secparams.s)
    x = randomMpz(q_hat_apos_x, secparams)
    y = randomMpz(q_hat_apos_y, secparams)

    F = Truncate(RecHash(p_bold, secparams),
                 secparams.L_F)  # Finalization code
    r_bold = []  # Return codes

    n = len(p_bold)
    for i in range(n):
        r_bold.append(Truncate(RecHash(p_bold[i], secparams), secparams.L_R))

    return SecretVoterData(x, y, F, r_bold)
Пример #16
0
def GetYValue(x, a_bold, secparams):
    """
    Algorithm 7.9: Computes the value y = A(x) ∈ Z_p' obtained from evaluating the polynomial A(X) = Sigma(i=0...d) a_i X^i mod p' at position x.
    The algorithm is an implementation of Horners method.

    Args:
       x (mpz):                            value x \in Z_p', normally mpz is used except for x = 0
       a (list of mpz):                    list of coefficients
       secparams (SecurityParams):         Collection of public security parameters

    Returns:
       mpz:         the y value for x on the polynomial
    """

    AssertMpz(x)
    AssertList(a_bold)
    AssertClass(secparams, SecurityParams)

    if x == mpz(0):
        y = mpz(a_bold[0])
    else:
        y = mpz(0)

        for i in reversed(range(len(a_bold))):
            y = (a_bold[i] + x * y) % secparams.p_prime

    AssertMpz(y)

    return y
Пример #17
0
def GenConfirmation(Y, P_bold, secparams):
    """
    Algorithm 7.30: Generates the confirmation gamma, which consists of the
    public confirmation credential y_hat and a NIZKP of knowledge pi of the secret
    confirmation and validity credentials y and y_prime.

    Args:
        Y:                                   Confirmation code
        P_bold (list of points):             Points
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        gamma:                               Confirmation
    """

    AssertList(P_bold)
    AssertClass(secparams, SecurityParams)

    y_prime = 0
    for i in range(len(P_bold)):
        p_bold_i = P_bold[i]
        y_prime_i = GetValue(p_bold_i, secparams)
        y_prime += y_prime_i
        y_prime %= secparams.q_hat

    y = StringToInteger(Y, secparams.A_Y) % secparams.q_hat
    y_hat = gmpy2.powmod(secparams.g_hat, (y + y_prime) % secparams.q_hat,
                         secparams.p_hat)

    pi = GenConfirmationProof(y, y_prime, y_hat, secparams)
    gamma = Confirmation(y_hat, pi)

    return gamma
Пример #18
0
def ToString(x, k, A):
    """
    Algorithm 4.6: Computes a string representation of length k in big-endian order of a given non negative integer x in N

    Args:
       x (mpz):     Integer x ∈ N
       k (int)      String length k >= log_N (x)
       A (list)     Alphabet A = {c_1, ..., c_N}

    Returns:
       string:      The string representation of x
    """

    AssertMpz(x)
    AssertInt(k)
    AssertList(A)

    S = ""
    N = len(A)

    for i in reversed(range(k)):
        s_k = A[x % N]
        x = x // N
        S = s_k + S

    return S
Пример #19
0
def GenElectorateData(n_bold, k_bold, E_bold, secparams):
    """
    Algorithm 7.6: Generates the data for the whole electorate

    Args:
        n_bold (list of int):                A list containing the number of candidates: (n_1, ... , n_t)
        k_bold (list of int):                A list containing the number of possible selections per election: (k_1, ... , k_t)
        E_bold (list of list):               Eligibility matrix [N][t], 1 means eligible
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        tuple:                               (d, d^, P)
    """

    AssertList(n_bold)
    AssertList(k_bold)
    AssertList(E_bold)
    AssertClass(secparams, SecurityParams)

    n = sum(n_bold)
    N_E = len(E_bold)
    t = len(k_bold)

    d_bold = []
    d_hat_bold = []
    P_bold = []

    for i in range(N_E):  # loop over N (all voters)
        k_prime_i = 0
        for j in range(t):
            k_prime_i = k_prime_i + (
                E_bold[i][j] * k_bold[j]
            )  # if voter i is eligible to cast a vote in election j, multiply 1 * the number of selections in j

        # generate n random points
        p_bold_i, y_prime_i = GenPoints(n, k_prime_i, secparams)
        P_bold.append(p_bold_i)  # points on the polynomials

        # generate x, y values, finalization code and return codes
        d_i = GenSecretVoterData(p_bold_i, secparams)
        d_bold.append(d_i)  # private voter data

        d_hat_i = GetPublicVoterData(d_i.x_i, d_i.y_i, y_prime_i, secparams)
        d_hat_bold.append(d_hat_i)  # public voter data

    return (d_bold, d_hat_bold, P_bold)
Пример #20
0
def GenBallot(X,
              s,
              pk,
              secparams,
              manipulatedPublicCredential=None,
              manipulatedPublicKey=None):
    """
    Algorithm 7.18: Generates a ballot based on the selection s and the voting code X. The
    ballot includes an OT query a and a proof pi. The algorithm also returns the random
    values used to generate the OT query. These random values are required in Alg. 7.27
    to derive the transferred messages from the OT response, which itself is generated by Alg. 7.25.

    Args:
        X (str):                            Voting Code X ∈ A_X^l_X
        s (list of int):                    Selection s = (s_1, ... , s_k), 1 <= s_1 < ... < s_k
        pk (mpz):                           ElGamal key pk ∈ G_p \ {1}
       secparams (SecurityParams):          Collection of public security parameters

    Returns:
        tuple:                              alpha = (r, Ballot) = (r, (x_hat, a, b, pi))
    """

    AssertMpz(pk)
    AssertList(s)
    AssertClass(secparams, SecurityParams)

    x = mpz(StringToInteger(X, secparams.A_X))
    x_hat = gmpy2.powmod(secparams.g_hat, x, secparams.p_hat)
    if manipulatedPublicCredential != None:
        x_hat = mpz(manipulatedPublicCredential)
    if manipulatedPublicKey != None:
        pk = mpz(manipulatedPublicKey)

    q_bold = GetSelectedPrimes(s, secparams)  # q = (q_1, ... , q_k)
    (a_bold, r_bold) = GenQuery(q_bold, pk, secparams)

    m = mpz(1)
    for j in range(len(q_bold)):
        m = m * q_bold[j]

    if m >= secparams.p:
        return None

    #a = mpz(1)
    #b = mpz(1)
    r = mpz(0)

    for j in range(len(q_bold)):
        #a = (a * a_bold[j][0]) % secparams.p
        #b = (b * a_bold[j][1]) % secparams.p
        r = (r + r_bold[j]) % secparams.q

    #e = (a, b)
    pi = GenBallotProof(x, m, r, x_hat, a_bold, pk, secparams)
    alpha = Ballot(x_hat, a_bold, pi)

    return (alpha, r_bold)
Пример #21
0
def CheckBallot(v, alpha, pk, k_bold, E_bold, x_hat_bold, B, secparams):
    """
    Algorithm 7.22: Checks if a ballot alpha obtained from voter v is valid. For this, voter i
    must not have submitted a valid ballot before, pi must be valid, and x_hat must be the public
    voting credential of voter v. Note that parameter checking |a|  ki for ki  °tj1 kij is an important initial step of this algorithm.

    Args:
        v (int):                             Voter index
        alpha (Ballot):                      Ballot
        pk (mpz):                            Public Key
        k_bold (list):                       Number of selections
        E_bold (list):                       Eligibility matrix E
        x_hat_bold (list):                   Public voting credentials
        B (list):                            Ballot List
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        bool:                                True if the ballot is valid, False if not
    """

    AssertInt(v)
    AssertClass(alpha, Ballot)
    AssertMpz(pk)
    assert IsMember(pk, secparams), "pk must be in G_q"
    AssertList(k_bold)
    AssertList(x_hat_bold)
    AssertList(B)
    AssertClass(secparams, SecurityParams)

    k_prime = 0
    for j in range(len(k_bold)):
        k_prime = k_prime + E_bold[v][j] * k_bold[
            j]  # if voter i is eligible to cast a vote in election j, multiply 1 * the number of selections in j

    hasBallot = HasBallot(v, B, secparams)
    credentialCheck = x_hat_bold[v] == alpha.x_hat
    queryLength = len(alpha.a_bold) == k_prime
    if not hasBallot and credentialCheck and queryLength:
        ballotProofCheck = CheckBallotProof(alpha.pi, alpha.x_hat,
                                            alpha.a_bold, pk, secparams)
        if ballotProofCheck:
            return True, []

    return (False, [False, hasBallot, credentialCheck, queryLength])
Пример #22
0
def GenDecryptionProof(sk_j, pk_j, e_bold, b_prime_bold, secparams):
    """
    Algorithm 7.50: Generates a decryption proof relative to ElGamal encryptions e and
    partial decryptions b'. This is essentially a NIZKP of knowledge of the private key share
    sk_j satisfying b'_i = b_i^sk_j for all input encryptions e_i = (a_i, b_i) and pk_j = g^sk_j.
    Proof verification, see Alg. 7.52.

    Args:
        sj_j (mpz):                             Decryption key share
        pk_j (mpz):                             Encryption key share
        e_bold (list of ElGamalEncryption):     ElGamal encryptions e_bold
        b_prime_bold (list):                    Partial decryptions
        secparams (SecurityParams):             Collection of public security parameters

    Returns:
        DecryptionProof
    """
    AssertMpz(sk_j)
    AssertMpz(pk_j)
    AssertList(e_bold)
    AssertList(b_prime_bold)
    AssertClass(secparams, SecurityParams)

    w = randomMpz(secparams.q, secparams)
    t_0 = gmpy2.powmod(secparams.g, w, secparams.p)

    t_1_to_N = []
    N = len(e_bold)
    for i in range(N):
        t_1_to_N.append(gmpy2.powmod(e_bold[i].b, w, secparams.p))

    t = (t_0, t_1_to_N)

    b_bold = [e.b for e in e_bold]

    y = (pk_j, b_bold, b_prime_bold)
    c = GetNIZKPChallenge(y, t, secparams.tau, secparams)

    s = (w + c * sk_j) % secparams.q
    pi = DecryptionProof(t, s)

    return pi
Пример #23
0
def CheckDecryptionProof(pi_prime, pk_j, e_bold, b_prime_bold, secparams):
    """
    Algorithm 7.52: Checks the correctness of a decryption proof  generated by Alg. 7.50.
    The public values are the ElGamal encryptions e, the partial decryptions b1, and the
    share pkj of the public encryption key.

    Args:
        pi_prime (DecryptionProof):                 Decryption
        pk_j (mpz):                                 Encryption key share
        e_bold (list of ElGamalEncryption):         ElGamal encryptions
        b_prime_bold (list):                        Partial decryptions
        secparams (SecurityParams):                 Collection of public security parameters

    Returns:
        bool:                                       (t_0 = t_prime_0) and for i = 1..N: t_i = t_prime_i
    """
    #AssertMpz(pi_prime)
    AssertMpz(pk_j)
    AssertList(e_bold)
    AssertList(b_prime_bold)
    AssertClass(secparams, SecurityParams)

    t_0 = pi_prime.t[0]
    t_1_to_N = pi_prime.t[1]

    b_bold = [e.b for e in e_bold]
    y = (pk_j, b_bold, b_prime_bold)
    c = GetNIZKPChallenge(y, pi_prime.t, secparams.tau, secparams)
    t_prime_0 = (gmpy2.powmod(pk_j, -c, secparams.p) * gmpy2.powmod(
        secparams.g, pi_prime.s, secparams.p)) % secparams.p

    t_prime_bold = []
    N = len(e_bold)
    for i in range(N):
        t_prime_bold.append(
            (gmpy2.powmod(b_prime_bold[i], -c, secparams.p) *
             gmpy2.powmod(b_bold[i], pi_prime.s, secparams.p)) % secparams.p)

    return (t_0 == t_prime_0 and t_prime_bold == t_1_to_N)
Пример #24
0
def CheckConfirmation(v, gamma, y_hat_bold, B, C, secparams):
    """
    Algorithm 7.33: Checks if a confirmation γ obtained from voter v is valid. For
    this, voter v must have submitted a valid ballot before, but not a valid
    confirmation. The check then succeeds if π is valid and if y_hat is the public
    confirmation credential of voter v.

    Args:
        v (int):                             Voter index
        gamma:                               Confirmation
        y_hat_bold (list):                   Public confirmation credentials
        B (list):                            Ballot list
        C (list):                            Confirmation list
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        bool                                 True if the given confirmation is valid, False otherwise.
    """

    AssertNumeric(v)
    AssertList(y_hat_bold)
    AssertList(B)
    AssertList(C)
    AssertClass(secparams, SecurityParams)

    #(y_hat_, pi) = gamma

    hasBallot = HasBallot(v, B, secparams)
    hasConfirmation = HasConfirmation(v, C, secparams)
    credentialCheck = gamma.y_hat == y_hat_bold[v]
    if hasBallot and not hasConfirmation and credentialCheck:
        confirmationProofCheck = CheckConfirmationProof(gamma.pi, gamma.y_hat, secparams)
        if confirmationProofCheck:
            return (True, [])

    return (False, [False, hasBallot, hasConfirmation, credentialCheck])
Пример #25
0
def CheckVerificationCodes(rc_bold, rc_prime_bold, s_bold):
    """
    Algorithm 7.29: Checks if every displayed verification code RC'_i i matches with the return code
    RC_s_i of the selected candidate s_i as printed on the code sheet.
    Note that this algorithm is executed by humans.

    Args:
        rc_bold (list):                     Printed return codes
        rc_prime_bold (list):               Displayed return codes rc'
        s_bold (list):                      Selections

    Returns:
        bool
    """

    AssertList(rc_bold)
    AssertList(rc_prime_bold)
    AssertList(s_bold)

    for i in range(len(s_bold)):
        if rc_bold[s_bold[i]] != rc_prime_bold[i]:
            return False

    return True
Пример #26
0
def CheckBallotProof(pi, x_hat, a_bold, pk, secparams):
    """
    Algorithm 7.24: Checks the correctness of a ballot proof Pi generated by Alg. 7.21. The
    public values of this proof are the public voting credential x_hat and the ElGamal encryption (a,b)

    Args:
        pi (BallotProof):                    Ballot proof pi = (t,s)
        x_hat (mpz):                         Voting credential x_hat
        a_bold (list):                       OT query a_bold
        pk (mpz):                            ElGamal key pk
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        bool:                                True if (t_1 == t'_1 and t_2 == t'_2 and t_3 == t'_3) holds
    """

    AssertClass(pi, BallotProof)
    AssertMpz(x_hat)
    AssertList(a_bold)
    AssertMpz(pk)
    AssertClass(secparams, SecurityParams)

    y = (x_hat, a_bold)
    t = pi[0]
    (t_1, t_2, t_3) = t
    s = pi[1]
    (s_1, s_2, s_3) = s

    c = GetNIZKPChallenge(y, t, secparams.tau, secparams)

    a_1 = mpz(1)
    a_2 = mpz(1)

    for j in range(len(a_bold)):
        a_1 = (a_1 * a_bold[j][0]) % secparams.p
        a_2 = (a_2 * a_bold[j][1]) % secparams.p
        # e = (a, b)

    t_prime_1 = (gmpy2.powmod(x_hat, -c, secparams.p_hat) * gmpy2.powmod(
        secparams.g_hat, s_1, secparams.p_hat)) % secparams.p_hat
    t_prime_2 = (gmpy2.powmod(a_1, -c, secparams.p) * s_2 *
                 gmpy2.powmod(pk, s_3, secparams.p)) % secparams.p
    t_prime_3 = (gmpy2.powmod(a_2, -c, secparams.p) *
                 gmpy2.powmod(secparams.g, s_3, secparams.p)) % secparams.p

    return t_1 == t_prime_1 and t_2 == t_prime_2 and t_3 == t_prime_3
Пример #27
0
def GenBallotProof(x, m, r, x_hat, a_bold, pk, secparams):
    """
    Algorithm 7.21: Generates a NIZKP, which proves that the ballot has been formed properly.
    This proof includes a proof of knowledge of the secret voting credential x that matches with
    the public voting credential x_hat. Note that this is equivalent to a Schnorr Identification proof.

    Args:
        x (mpz):                            Voting credential ∈ Z_q_hat
        m (mpz):                            Product of selected primes m ∈ G_q
        r (mpz):                            Randomization r ∈ Z_q
        a_bold (list):                      OT queries
        pk (mpz):                           Encryption key pk ∈ G_q
        secparams (SecurityParams):         Collection of public security parameters

    Returns:
        tuple:                              ((t_1, t_2, t_3), (s_1, s_2, s_3))
    """

    AssertMpz(x)
    AssertMpz(m)
    AssertMpz(r)
    AssertMpz(x_hat)
    AssertList(a_bold)
    AssertMpz(pk)
    AssertClass(secparams, SecurityParams)

    w_1 = randomMpz(secparams.q_hat, secparams)
    w_2 = randomQuadResMpz(secparams)
    w_3 = randomMpz(secparams.q, secparams)
    t_1 = gmpy2.powmod(secparams.g_hat, w_1, secparams.p_hat)
    t_2 = (w_2 * gmpy2.powmod(pk, w_3, secparams.p)) % secparams.p
    t_3 = gmpy2.powmod(secparams.g, w_3, secparams.p)

    y = (x_hat, a_bold)
    t = (t_1, t_2, t_3)
    c = GetNIZKPChallenge(y, t, secparams.tau, secparams)

    s_1 = (w_1 + c * x) % secparams.q_hat
    s_2 = (w_2 * gmpy2.powmod(m, c, secparams.p)) % secparams.p
    s_3 = (w_3 + c * r) % secparams.q

    s = (s_1, s_2, s_3)

    return BallotProof(t,s)
Пример #28
0
def GetFinalizationCode(delta_bold, secparams):
    """
    Algorithm 7.38: Computes a finalization code FC by combining the values Fj received
    from the authorities.

    Args:
        delta_bold (list):                   Finalizations
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        string:                              Finalization code
    """

    AssertList(delta_bold)
    AssertClass(secparams, SecurityParams)

    F_j = [delta_bold[j][0] for j in range(len(delta_bold))]

    FC = ByteArrayToString(XorByteArray(F_j), secparams.A_F)

    return FC
Пример #29
0
def GetSelectedPrimes(s_bold, secparams):
    """
    Algorithm 7.19: Selects k prime numbers from Gq corresponding to the given
    indices s = (s_1, ..., s_k). For example, s = (1, 3, 7) means selecting the
    first, the third, and the seventh prime from G_q.

    Args:
        s_bold (list of int):                Selections
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        list of mpz:                         List of the selected prime numbers
    """

    AssertList(s_bold)
    AssertClass(secparams, SecurityParams)

    s_k = max(s_bold) + 1
    p_bold = GetPrimes(s_k, secparams)
    q_bold = [p_bold[s_i] for s_i in s_bold]

    return q_bold
Пример #30
0
def HasConfirmation(v, C, secparams):
    """
    Algorithm 7.34: Checks if the confirmation list C contains an entry for v.

    Args:
        v (int):                           Voter Index v in N
        C (list of Confirmation):          Confirmation list C
        secparams (SecurityParams):        Collection of public security parameters

    Returns:
        bool:                              True if the list C contains a Confirmation of voter i
    """

    AssertNumeric(v)
    AssertList(C)
    AssertClass(secparams, SecurityParams)

    for voterConfirmation in C:
        if v == voterConfirmation.voterId:
            return True

    return False