Esempio n. 1
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
Esempio n. 2
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
Esempio n. 3
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
Esempio n. 4
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
Esempio n. 5
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
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
0
def GenPoints(n, k, secparams):
    """
    Algorithm 7.7: Generates a list of n random points picket from t random polynomials
    A_j(X) of degree k_j - 1 (by picking n_j different random points from each polynomial).
    Additional, the values y_j = A_j(0) are computed for all random polynomials and returned together with the random points.

    Args:
        n (int):                            Number of candidates n >= 2
        k (int):                            Number of selections 0 < k < n
        secparams (SecurityParams):         Collection of public security parameters

    Returns:
        tuple:        (p,y'), points p ∈ (Z_p^2)^n, and the y value of x=0
    """

    AssertInt(n)
    AssertInt(k)

    p_bold = []

    a_bold = GenPolynomial(
        k - 1, secparams
    )  # the number of 1's in the eligibility matrix indicate how many selections the voter can make and therefore decides the degree of the polynomial
    X = []

    for i in range(n):
        x = mpz(0)
        # get a unique x from Z_p'
        while True:
            x = randomMpz(secparams.p_prime, secparams)
            if x not in X or secparams.deterministicRandomGen:  # if randomMpz is deterministic, we would be stuck in an endless loop
                X.append(x)
                break

        y = GetYValue(
            x, a_bold, secparams
        )  # get the corresponding y value of x on the polynomial a_j
        p_i = Point(x, y)  # Point tuple
        p_bold.append(p_i)  # part of the private voter data

        y_prime = GetYValue(mpz(0), a_bold, secparams)  # Point (0,Y(0))

    return (p_bold, y_prime)
Esempio n. 9
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
Esempio n. 10
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])
Esempio n. 11
0
def HasBallot(v, B_bold, secparams):
    """
    Algorithm 7.23: Checks if the ballot list B contains an entry for v.

    Args:
        v (int):                            Voter index
        B_bold (list):                      Ballot list
        secparams (SecurityParams):         Collection of public security parameters

    Returns:
        bool
    """

    AssertInt(v)
    AssertList(B_bold)
    AssertClass(secparams, SecurityParams)

    for j in range(len(B_bold)):
        # (v_j, alpha, r) = B_bold[j]
        if v == B_bold[j].voterId:
            return True

    return False
Esempio n. 12
0
def GetNIZKPChallenge(y, t, kappa, secparams):
    """
    Algorithm 7.4: Computes a NIZKP challenge c ∈ Z_q for a given public value
    y and a public commitment t. The domains Y and T of the input values are
    unspecified.

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

    Returns:
        mpz:                                The NIZKP challenge
    """

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

    c = mpz(ToInteger(RecHash([y, t], secparams)) % 2 ^ kappa)

    return c
Esempio n. 13
0
def GetGenerators(n, secparams):
    """
    Algorithm 7.3: Computes n independent generators of G_q. The algorithm is an adaption of the NIST standard FIPS PUB 186-4 [1, Appendix A.2.3].
    The string "chVote" guarantees that the resulting values are specific for chVote. In a more efficient implementation of this algorithm, the list of resulting generators is accumulated in a cache
    or precomputed for the largest expected value n_max >= n.

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

    Returns:
       list of mpz:                         a list with independent generators of G_p (mpz)
    """

    AssertInt(n)
    AssertClass(secparams, SecurityParams)
    assert n >= 0, "n must be greater than or equal 0"

    generators = []

    for i in range(n):
        x = 0

        while True:
            x += 1
            h = mpz(
                ToInteger(RecHash(["chVote", "ggen", i, x], secparams)) %
                secparams.p)
            h = (h**2) % secparams.p

            if h not in (0, 1):
                break

        generators.append(h)

    return generators
Esempio n. 14
0
 def securityLevel(self, value):
     AssertInt(value)
     self.state.securityLevel = value
Esempio n. 15
0
 def id(self, value):
     AssertInt(value)
     self.state.id = value
Esempio n. 16
0
 def numberOfParallelElections(self, value):
     AssertInt(value)
     self.state.numberOfParallelElections = value
Esempio n. 17
0
def GenResponse(v, a_bold, pk, n_bold, k_bold, E_bold, P_bold, secparams):
    """
    Algorithm 7.25: Generates the response beta for the given OT query a. The messages to
    transfer are byte array representations of the n points (p_v,1, ... p_v,n). Along with beta,
    the algorithm also returns the randomizations r used to generate the response.

    Args:
        v (int):                            Voter Index
        a_bold (list of mpz):               Queries
        pk (mpz):                           Encryption Key
        n_bold (list of int):               Number of candidates
        k_bold (list of int):               Number of selections
        E_bold (list of list):              Eligibility matrix
        P_bold (list of list):              Points N x n
        secparams (SecurityParams):         Collection of public security parameters

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

    AssertInt(v)
    AssertList(a_bold)
    for a in a_bold:
        assert IsMember(a[0],
                        secparams), "All elements of a_bold must be in G_q"
    for a in a_bold:
        assert IsMember(a[1],
                        secparams), "All elements of a_bold must be in G_q"
    AssertMpz(pk)
    assert IsMember(pk, secparams), "Public key must be in G_q"
    assert pk != mpz(1), "Public key cannot be equal to 1"
    AssertList(n_bold)
    AssertList(k_bold)
    AssertList(E_bold)
    AssertList(P_bold)
    AssertClass(secparams, SecurityParams)

    n = sum(n_bold)
    k = len(a_bold)
    t = len(n_bold)
    M = []

    z_1 = randomMpz(secparams.q, secparams)
    z_2 = randomMpz(secparams.q, secparams)

    beta = []
    b_bold = []

    for j in range(k):
        beta.append(randomQuadResMpz(secparams))
        b_j = gmpy2.powmod(a_bold[j][0], z_1, secparams.p)
        b_j *= gmpy2.powmod(a_bold[j][1], z_2, secparams.p)
        b_j *= beta[j]
        b_j %= secparams.p
        b_bold.append(b_j)

    l_M = ceil(secparams.L_M / secparams.L)
    p_bold = GetPrimes(n, secparams)

    n_prime = 0
    k_prime = 0

    C_bold = [[None for i in range(sum(k_bold))] for i in range(n)]

    for l in range(len(k_bold)):
        if E_bold[v][l] != 0:
            for i in range(n_prime, n_prime + n_bold[l]):
                p_prime_i = gmpy2.powmod(p_bold[i], z_1, secparams.p)
                M.append(
                    ToByteArrayN(P_bold[v][i].x, secparams.L_M // 2) +
                    ToByteArrayN(P_bold[v][i].y, secparams.L_M // 2))

                for j in range(k_prime, k_prime + E_bold[v][l] * k_bold[l]):
                    k_ij = p_prime_i * beta[j] % secparams.p
                    k_tmp = bytearray()

                    for c in range(l_M):
                        k_tmp += RecHash([k_ij, c], secparams)

                    K_ij = Truncate(k_tmp, secparams.L_M)
                    C_bold[i][j] = XorByteArray([M[i], K_ij])

            k_prime = k_prime + E_bold[v][l] * k_bold[l]
        n_prime = n_prime + n_bold[l]

    d = (gmpy2.powmod(pk, z_1, secparams.p) *
         gmpy2.powmod(secparams.g, z_2, secparams.p)) % secparams.p
    beta = Response(b_bold, C_bold, d)
    z = (z_1, z_2)

    return (beta, z)