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
예제 #2
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
예제 #3
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)
예제 #4
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
예제 #5
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)
예제 #6
0
def CheckConfirmationProof(pi, y_hat, secparams):
    """
    Algorithm 7.36: Checks the correctness of a NIZKP pi generated by Alg. 7.33.
    The public value of this proof is the public confirmation credential y_hat.

    Args:
        pi:                                  The NIZKP to check
        y_hat:                               The public confirmation credential
        secparams (SecurityParams):          Collection of public security parameters

    Returns:
        bool:                                True if the NIZKP is correct, False otherwise.
    """

    AssertClass(secparams, SecurityParams)

    (t, s) = pi
    c = GetNIZKPChallenge(y_hat, t, secparams.tau, secparams)
    t_prime = (gmpy2.powmod(y_hat, -c, secparams.p_hat) * gmpy2.powmod(
        secparams.g_hat, s, secparams.p_hat)) % secparams.p_hat

    return t == t_prime
예제 #7
0
def CheckShuffleProof(pi, e_bold, e_prime_bold, pk, secparams):
    """
    Algorithm 7.48: Checks the correctness of a NIZKP of a shuffle pi generated by Alg. 7.44.
    The public values are the ElGamal encryptions e and e' and the public encryption key pk.

    Args:
       pi (ShuffleProof):                       Shuffle proof
       e_bold (list):                           ElGamal Encryptions
       e_prime_bold (list):                     Shuffled ElGamal Encryptions e'
       pk (mpz):                                Encryption key pk
       secparams (SecurityParams):              Collection of public security parameters

    Returns:
        ShuffleProof
    """
    AssertClass(pi, ShuffleProof)
    AssertList(e_bold)
    AssertList(e_prime_bold)
    AssertMpz(pk)
    AssertClass(secparams, SecurityParams)

    N = len(e_bold)
    c_bold = pi.c_bold
    c_hat_bold = pi.c_hat_bold

    s_1 = pi.s[0]
    s_2 = pi.s[1]
    s_3 = pi.s[2]
    s_4 = pi.s[3]
    s_hat = pi.s[4]  # tuple
    s_prime = pi.s[5]  # list

    t_1 = pi.t[0]
    t_2 = pi.t[1]
    t_3 = pi.t[2]
    t_4_1 = pi.t[3][0]
    t_4_2 = pi.t[3][1]
    t_hat = pi.t[4]

    assert len(
        e_prime_bold
    ) == N, "The size of e_prime_bold must be identical to N ( = len(e_bold))"
    assert len(
        c_bold
    ) == N, "The size of c_bold must be identical to N ( = len(e_bold))"
    assert len(
        c_hat_bold
    ) == N, "The size of c_bold must be identical to N ( = len(e_bold))"
    assert len(pi.t[3]) == 2, "The size of t_4 must be identical to 2"
    assert len(
        t_hat
    ) == N, "The size of t_hat must be identical to N ( = len(e_bold))"
    assert len(
        s_hat
    ) == N, "The size of s_hat must be identical to N ( = len(e_bold))"

    h_bold = GetGenerators(N, secparams)
    u_bold = GetNIZKPChallenges(N, (e_bold, e_prime_bold, c_bold),
                                secparams.tau, secparams)
    y = (e_bold, e_prime_bold, c_bold, c_hat_bold, pk)
    c = GetNIZKPChallenge(y, pi.t, secparams.tau, secparams)

    c_product = mpz(1)
    for i in range(N):
        c_product = (c_product * pi.c_bold[i]) % secparams.p

    h_product = mpz(1)
    for i in range(N):
        h_product = (h_product * h_bold[i]) % secparams.p

    c_line = (c_product * gmpy2.invert(h_product, secparams.p)) % secparams.p

    u = mpz(1)
    for i in range(N):
        u = (u * u_bold[i]) % secparams.q

    c_hat = (c_hat_bold[N - 1] * gmpy2.invert(
        gmpy2.powmod(secparams.h, u, secparams.p), secparams.p)) % secparams.p

    c_product2 = mpz(1)
    for i in range(N):
        c_product2 = (c_product2 * gmpy2.powmod(c_bold[i], u_bold[i],
                                                secparams.p)) % secparams.p
    c_tilde = c_product2 % secparams.p

    a_prime = mpz(1)
    for i in range(N):
        a_prime = (a_prime * gmpy2.powmod(e_bold[i].a, u_bold[i],
                                          secparams.p)) % secparams.p

    b_prime = mpz(1)
    for i in range(N):
        b_prime = (b_prime * gmpy2.powmod(e_bold[i].b, u_bold[i],
                                          secparams.p)) % secparams.p

    t_prime_1 = (gmpy2.powmod(c_line, -c, secparams.p) *
                 gmpy2.powmod(secparams.g, s_1, secparams.p)) % secparams.p
    t_prime_2 = (gmpy2.powmod(c_hat, -c, secparams.p) *
                 gmpy2.powmod(secparams.g, s_2, secparams.p)) % secparams.p
    h_product2 = mpz(1)
    for i in range(N):
        h_product2 = (h_product2 * gmpy2.powmod(h_bold[i], s_prime[i],
                                                secparams.p)) % secparams.p
    t_prime_3 = (gmpy2.powmod(c_tilde, -c, secparams.p) * gmpy2.powmod(
        secparams.g, s_3, secparams.p) * h_product2) % secparams.p

    a_prime_product = mpz(1)
    for i in range(N):
        a_prime_product = (a_prime_product * gmpy2.powmod(
            e_prime_bold[i].a, s_prime[i], secparams.p)) % secparams.p
    t_prime_4_1 = (gmpy2.powmod(a_prime, -c, secparams.p) * gmpy2.powmod(
        pk, -s_4, secparams.p) * a_prime_product) % secparams.p

    b_prime_product = mpz(1)
    for i in range(N):
        b_prime_product = (b_prime_product * gmpy2.powmod(
            e_prime_bold[i].b, s_prime[i], secparams.p)) % secparams.p
    t_prime_4_2 = (gmpy2.powmod(b_prime, -c, secparams.p) * gmpy2.powmod(
        secparams.g, -s_4, secparams.p) * b_prime_product) % secparams.p

    c_hat_bold_tmp = []
    c_hat_bold_tmp.append(secparams.h)
    c_hat_bold_tmp.extend(c_hat_bold)

    t_hat_prime_bold = [None] * N
    for i in range(N):
        t_hat_prime_bold[i] = (
            gmpy2.powmod(c_hat_bold_tmp[i + 1], -c, secparams.p) *
            gmpy2.powmod(secparams.g, s_hat[i], secparams.p) * gmpy2.powmod(
                c_hat_bold_tmp[i], s_prime[i], secparams.p)) % secparams.p

    return (t_1 == t_prime_1) and (t_2 == t_prime_2) and (
        t_3 == t_prime_3) and (t_4_1 == t_prime_4_1) and (
            t_4_2 == t_prime_4_2) and (t_hat == t_hat_prime_bold)
예제 #8
0
def GenShuffleProof(e_bold, e_prime_bold, r_prime_bold, psi, pk, secparams):
    """
    Algorithm 7.44: Generates a NIZKP of shuffle relative to ElGamal encryptions e and e1,
    which is equivalent to proving knowledge of a permutation psi and randomizations r_prime such
    that e_prime = Shuffle_pk(e,r_prime,psi). The algorithm implements Wikström’s proof of a shuffle
    [19, 18], except for the fact that the offline and online phases are merged. For the proof
    verification, see Alg. 7.48. For further background information we refer to Section 5.5.

    Args:
       e_bold (list):                           ElGamal Encryptions
       e_prime_bold (list):                     Shuffled ElGamal Encryptions e'
       r_prime_bold (list):                     Re-encryption randomizations r'
       psi (list):                              Permutation
       pk (mpz):                                Encryption key pk
       secparams (SecurityParams):              Collection of public security parameters

    Returns:
        ShuffleProof
    """
    AssertList(e_bold)
    AssertList(e_prime_bold)
    AssertList(r_prime_bold)
    AssertList(psi)
    AssertMpz(pk)
    AssertClass(secparams, SecurityParams)

    N = len(e_bold)
    h_bold = GetGenerators(N, secparams)
    (c_bold, r_bold) = GenPermutationCommitment(psi, h_bold, secparams)
    u_bold = GetNIZKPChallenges(N, (e_bold, e_prime_bold, c_bold), secparams.tau, secparams)

    u_prime_bold = [None] * N
    for i in range(N):
        u_prime_bold[i] = u_bold[psi[i]]

    (c_hat_bold, r_hat_bold) = GenCommitmentChain(secparams.h, u_prime_bold, secparams)

    w_1 = randomMpz(secparams.q, secparams)
    w_2 = randomMpz(secparams.q, secparams)
    w_3 = randomMpz(secparams.q, secparams)
    w_4 = randomMpz(secparams.q, secparams)

    w_hat_bold = [None] * N
    w_prime_bold = [None] * N
    for i in range(N):
        w_hat_bold[i] = randomMpz(secparams.q, secparams)
        w_prime_bold[i] = randomMpz(secparams.q, secparams)


    # Computing the T values:

    t_1 = gmpy2.powmod(secparams.g, w_1, secparams.p)
    t_2 = gmpy2.powmod(secparams.g, w_2, secparams.p)

    h_product = mpz(1)
    for i in range(N):
        h_product = (h_product * gmpy2.powmod(h_bold[i],w_prime_bold[i], secparams.p) ) % secparams.p

    t_3 = (gmpy2.powmod(secparams.g, w_3, secparams.p) * h_product) % secparams.p

    a_prime_i_product = mpz(1)
    for i in range(N):
        a_prime_i_product = (a_prime_i_product * gmpy2.powmod(e_prime_bold[i].a, w_prime_bold[i], secparams.p)) % secparams.p
    t_4_1 = (gmpy2.powmod(pk, -w_4, secparams.p) * a_prime_i_product) % secparams.p

    b_prime_i_product = mpz(1)
    for i in range(N):
        b_prime_i_product = (b_prime_i_product * gmpy2.powmod(e_prime_bold[i].b, w_prime_bold[i], secparams.p)) % secparams.p
    t_4_2 = (gmpy2.powmod(secparams.g, -w_4, secparams.p) * b_prime_i_product) % secparams.p

    c_hat_bold_tmp = []
    c_hat_bold_tmp.append(secparams.h)
    c_hat_bold_tmp.extend(c_hat_bold)

    t_hat_bold = [None] * N
    for i in range(N):
        t_hat_bold[i] = (gmpy2.powmod(secparams.g, w_hat_bold[i], secparams.p) * gmpy2.powmod(c_hat_bold_tmp[i], w_prime_bold[i], secparams.p) ) % secparams.p

    del c_hat_bold_tmp[0]   # remove the element c_0 that we manually inserted ???????????

    t = (t_1, t_2, t_3, (t_4_1, t_4_2), t_hat_bold)

    # Computing the challenge:
    y = (e_bold, e_prime_bold, c_bold, c_hat_bold, pk)
    c = GetNIZKPChallenge(y, t, secparams.tau, secparams)

    # Computing the S values:
    r_line = mpz(0)
    for i in range(N):
        r_line = (r_line + r_bold[i]) % secparams.q

    s_1 = mpz(0)
    for i in range(N):
        s_1 = (w_1 + c * r_line) % secparams.q

    v_bold = [None] * N
    v_bold[N-1] = mpz(1)
    for i in reversed(range(N-1)):
        v_bold[i] = (u_prime_bold[i+1] * v_bold[i+1]) % secparams.q

    r_hat = mpz(0)
    for i in range(N):
        r_hat = (r_hat + (r_hat_bold[i] * v_bold[i])) % secparams.q
    s_2 = (w_2 + c * r_hat ) % secparams.q

    r_tilde = mpz(0)
    for i in range(N):
        r_tilde = (r_tilde + (r_bold[i] * u_bold[i])) % secparams.q
    s_3 = (w_3 + c* r_tilde ) % secparams.q

    r_prime = mpz(0)
    for i in range(N):
        r_prime = (r_prime + (r_prime_bold[i] * u_bold[i])) % secparams.q
    s_4 = (w_4 + c* r_prime ) % secparams.q

    s_hat_bold = [None] * N
    s_prime_bold = [None] * N
    for i in range(N):
        s_hat_bold[i] = (w_hat_bold[i] + (c * r_hat_bold[i])) % secparams.q
        s_prime_bold[i] = (w_prime_bold[i] + (c * u_prime_bold[i])) % secparams.q

    s = (s_1, s_2, s_3, s_4, s_hat_bold, s_prime_bold)

    pi = ShuffleProof(t,s,c_bold,c_hat_bold)

    return pi