Example #1
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
Example #2
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)
Example #3
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)
Example #4
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
Example #5
0
def GenPolynomial(d, secparams):
    """
    Algorithm 7.8: Generates the coefficients a_0,...,a_d of a random polynomial A(X) = Sigma(i=0...d) a_i X^i mod p' of degree d >= 0.
    The algorithm also accepts d = -1 as input, which we interpret as the polynomial A(X) = 0.
    In this case, the algorithm returns the coefficient list a = (0).

    Args:
       d (int):                            Degree d >= -1
       secparams (SecurityParams):         Collection of public security parameters

    Returns:
       list of mpz:                        A list of coefficients a_0 ... a_d of polynomial A(X)
    """

    AssertInt(d)
    AssertClass(secparams, SecurityParams)
    assert (d >= -1)

    a_bold = []
    a_d = 0

    if (d == -1):
        return [0]

    else:
        for i in range(d):
            a_bold.append(randomMpz(secparams.p_prime, secparams))

        # generate the last coefficient != 0
        while a_d == 0:
            a_d = randomMpz(secparams.p_prime, secparams)

        a_bold.append(a_d)

    return a_bold
Example #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
Example #7
0
def GetPrimes(n, secparams):
    """
    Algorithm 7.1: Computes the first n prime numbers from G_q. The computation possibly
    fails if n is large and p is small, but this case is very unlikely in practice. In a more
    efficient implementation of this algorithm, the resulting list of primes is precomputed for
    the largest expected value n.

    Args:
       n (int):                             Number of primes to be calculated
       secparams (SecurityParams):          Collection of public security parameters

    Returns:
       list of mpz :                        A list with length n containing the first n prime numbers in G_p
    """

    AssertInt(n)
    AssertClass(secparams, SecurityParams)

    x = mpz(1)
    primes = []

    for i in range(n):  # i = 0, ... , n-1
        while True:
            x += 1 if x <= 2 else mpz(2)

            if x >= secparams.p:
                return []  # n is incompatible with p
            if gmpy2.is_prime(x) and IsMember(x, secparams):  # see Alg. 7.2
                break

        primes.append(x)

    return primes  # p \elementof G_p \cap P)^n
def GenConfirmationProof(y, y_prime, y_hat, secparams):
    """
    Algorithm 7.32: Generates a NIZKP of knowledge of the secret confirmation
    credential y that matches with a given public confirmation credential y_hat.
    Note that this proof is equivalent to a Schnorr identification proof. For the
    verification of pi, see Alg. 7.36.

    Args:
        y:                                   Secret confirmation credential
        y_prime:                             Secret validity credential
        y_hat:                               Public confirmation credential
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        π:          The NIZKP challenge
    """

    AssertMpz(y)
    AssertClass(secparams, SecurityParams)

    w = randomMpz(secparams.q_hat, secparams)
    t = gmpy2.powmod(secparams.g_hat, w, secparams.p_hat)
    c = GetNIZKPChallenge(y_hat, t, secparams.tau, secparams)
    s = w + c * (y + y_prime) % secparams.q_hat
    pi = (t, s)

    return pi
Example #9
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)
Example #10
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
Example #11
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
Example #12
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
Example #13
0
def GenPermutation(N, secparams):
    """
    Algorithm 7.42: Generates a random permutation ψ ∈ Ψ following Knuth's shuffle algorithm.

    Args:
       N (int):                           Permutation size
       secparams (SecurityParams):          Collection of public security parameters

    Returns:
        list of int:                        Permutation
    """

    AssertInt(N)
    AssertClass(secparams, SecurityParams)

    I = list(range(N))
    res = []

    for i in range(N):
        k = randomBoundedInt(i, N - 1, secparams)
        j_i = I[k]
        I[k] = I[i]

        res.append(j_i)

    return res
Example #14
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
Example #15
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
Example #16
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
Example #17
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
Example #18
0
def GetNIZKPChallenges(n, y, kappa, secparams):
    """
    Algorithm 7.5: Computes n challenges c ∈ Z_q for a given of public value y. The domain
    Y of the input value is unspecified. The results in c = (c_1, ..., c_n) are identical to
    c_i = RecHash(y, i), but precomputing H makes the algorithm more efficient.

    Args:
        y (unspecified):                    Public value
        t (unspecified):                    Commitment
        kappa (int):                        Soundness strength 1 <= kappa <= 8L
        secparams (SecurityParams):         Collection of public security parameters

    Retuns:
        list of mpz:                        List containing n computed challenges (mpz)
    """

    AssertInt(n)
    AssertInt(kappa)
    assert kappa >= 1 and kappa <= 8 * secparams.L, "Constraint for kappa: 1 <= kappa <= 8L"
    AssertClass(secparams, SecurityParams)

    H = RecHash(y, secparams)
    c = []

    for i in range(1, n + 1):
        I = RecHash(i, secparams)
        c.append(mpz(ToInteger(secparams.hash(H + I)) % 2 ^ kappa))

    return c
Example #19
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
Example #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)
Example #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])
Example #22
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
Example #23
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)
Example #24
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)
Example #25
0
def CheckFinalizationCode(FC, FC_prime, secparams):
    """
    Algorithm 7.39: Checks if the displayed finalization code FC1 matches with the finalization
    code FC from the voting card. Note that this algorithm is executed by humans.

    Args:
        FC (string):                         Printed finalization code
        FC_prime (string):                   Displayed finalization code
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        bool:                                FC == FC_prime
    """

    AssertClass(secparams, SecurityParams)

    return FC == FC_prime
Example #26
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)
Example #27
0
def GenKeyPair(secparams):
    """
    Algorithm 7.15: Generates a random ElGamal encryption key pair (sk, pk) ∈ Z_q x G_q.
    This algorithm is used in Prot. 6.3 by the authorities to generate private shares of a common public encryption key.

    Args:
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        tuple:                               Key Pair (sk, pk) in Z_q x G_q
    """
    AssertClass(secparams, SecurityParams)

    sk = randomMpz(secparams.q, secparams)
    pk = gmpy2.powmod(secparams.g, sk, secparams.p)

    assert IsMember(pk, secparams)

    return (sk, pk)
Example #28
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
Example #29
0
def IsMember(x, secparams):
    """
    Algorithm 7.2: Checks if x is an element of G_q.
    The core of the algorithm is the computation of the Jacobi symbol for which we refer to existing algorithms

    Args:
       x (mpz):                             The number to test x \in N
       secparams (SecurityParams):          Collection of public security parameters

    Returns:
       bool:                                True if x is a member of G_q, False if not
    """

    AssertNumeric(x)
    AssertClass(secparams, SecurityParams)

    if 1 <= x and x < secparams.p:
        return jacobi(x, secparams.p) == 1

    return False
Example #30
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