Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unconditional showing protocol #13

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions coconut/proofs_up.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
""" Coconut zero-knowledge proofs. """
from petlib.bn import Bn
from bplib.bp import BpGroup
from hashlib import sha256
from binascii import hexlify
from coconut.utils import ec_sum


def to_challenge(elements):
""" generates a Bn challenge by hashing a number of EC points """
Cstring = b",".join([hexlify(x.export()) for x in elements])
Chash = sha256(Cstring).digest()
return Bn.from_binary(Chash)


def make_pi_s(params, gamma, ciphertext, cm, k, r, public_m, private_m):
""" prove correctness of ciphertext and cm """
(G, o, g1, hs, g2, e) = params
attributes = private_m + public_m
assert len(ciphertext) == len(k) and len(ciphertext) == len(private_m)
assert len(attributes) <= len(hs)
# create the witnesses
wr = o.random()
wk = [o.random() for _ in k]
wm = [o.random() for _ in attributes]
# compute h
h = G.hashG1(cm.export())
# compute the witnesses commitments
Aw = [wki*g1 for wki in wk]
Bw = [wk[i]*gamma + wm[i]*h for i in range(len(private_m))]
Cw = wr*g1 + ec_sum([wm[i]*hs[i] for i in range(len(attributes))])
# create the challenge
c = to_challenge([g1, g2, cm, h, Cw]+hs+Aw+Bw)
# create responses
rr = (wr - c * r) % o
rk = [(wk[i] - c*k[i]) % o for i in range(len(wk))]
rm = [(wm[i] - c*attributes[i]) % o for i in range(len(wm))]
return (c, rk, rm, rr)


def verify_pi_s(params, gamma, ciphertext, cm, proof):
""" verify orrectness of ciphertext and cm """
(G, o, g1, hs, g2, e) = params
(a, b) = zip(*ciphertext)
(c, rk, rm, rr) = proof
assert len(ciphertext) == len(rk)
# re-compute h
h = G.hashG1(cm.export())
# re-compute witnesses commitments
Aw = [c*a[i] + rk[i]*g1 for i in range(len(rk))]
Bw = [c*b[i] + rk[i]*gamma + rm[i]*h for i in range(len(ciphertext))]
Cw = c*cm + rr*g1 + ec_sum([rm[i]*hs[i] for i in range(len(rm))])
# compute the challenge prime
return c == to_challenge([g1, g2, cm, h, Cw]+hs+Aw+Bw)

def make_pi_s_up(params, Ls, commits, cm, r, public_m, private_m):
""" prove correctness of ciphertext and cm """
(G, o, g1, hs, h_blind, g2, e) = params
attributes = private_m + public_m
assert len(commits) == len(private_m)
assert len(attributes) <= len(hs)
# create the witnesses
wr = o.random()
wL = [o.random() for _ in Ls]
wm = [o.random() for _ in attributes]
# compute h
h = G.hashG1(cm.export())
# compute the witnesses commitments
Com_w = [wL[i]*h_blind + wm[i]*h for i in range(len(private_m))]
Cw = wr*g1 + ec_sum([wm[i]*hs[i] for i in range(len(attributes))])
# create the challenge
c = to_challenge([g1, g2, cm, h, Cw]+hs+commits+Com_w)
# create responses
rr = (wr - c * r) % o
rL = [(wL[i] - c*Ls[i]) % o for i in range(len(wL))]
rm = [(wm[i] - c*attributes[i]) % o for i in range(len(wm))]
return (c, rL, rm, rr)


def verify_pi_s_up(params, commits, cm, proof):
""" verify orrectness of ciphertext and cm """
(G, o, g1, hs, h_blind, g2, e) = params
(c, rL, rm, rr) = proof
assert len(commits) == len(rL)
# re-compute h
h = G.hashG1(cm.export())
# re-compute witnesses commitments
Com_w = [c*commits[i] + rL[i] * h_blind + rm[i] * h for i in range(len(commits))]
Cw = c*cm + rr*g1 + ec_sum([rm[i]*hs[i] for i in range(len(rm))])
# compute the challenge prime
return c == to_challenge([g1, g2, cm, h, Cw]+hs+commits+Com_w)


def make_pi_v(params, aggr_vk, sigma, private_m, t):
""" prove correctness of kappa and nu """
(G, o, g1, hs, g2, e) = params
(g2, alpha, beta) = aggr_vk
(h, s) = sigma
# create the witnesses
wm = [o.random() for _ in private_m]
wt = o.random()
# compute the witnesses commitments
Aw = wt*g2 + alpha + ec_sum([wm[i]*beta[i] for i in range(len(private_m))])
# create the challenge
c = to_challenge([g1, g2, alpha, Aw]+hs+beta)
# create responses
rm = [(wm[i] - c*private_m[i]) % o for i in range(len(private_m))]
rt = (wt - c*t) % o
return (c, rm, rt)

def verify_pi_v(params, aggr_vk, sigma, kappa, pi_v):
""" verify correctness of kappa """
(G, o, g1, hs, g2, e) = params
(g2, alpha, beta) = aggr_vk
(h, s) = sigma
(c, rm, rt) = pi_v
# re-compute witnesses commitments
Aw = c*kappa + rt*g2 + (1-c)*alpha + ec_sum([rm[i]*beta[i] for i in range(len(rm))])
# compute the challenge prime
return c == to_challenge([g1, g2, alpha, Aw]+hs+beta)
62 changes: 61 additions & 1 deletion coconut/scheme_up.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
from bplib.bp import BpGroup, G2Elem
from coconut.utils import *
from coconut.proofs import *
from coconut.proofs_up import *


def setup(q=1):
Expand Down Expand Up @@ -190,3 +190,63 @@ def agg_cred(params, aggr_vk, sigs, Ls, threshold=True):

aggr_sigma = (h[0], aggr_s)
return aggr_sigma




def prove_cred(params, aggr_vk, sigma, private_m):
"""
Build cryptographic material for blind verify.

Parameters:
- `params`: public parameters generated by `setup`
- `aggr_vk`: aggregated verification key
- `sigma`: credential
- `private_m` [Bn]: array containing the private attributes

Returns:
- `Theta`: randomized credential and cryptographic material to verify them
"""
assert len(private_m) > 0
(G, o, g1, hs, g2, e) = params
(g2, alpha, beta) = aggr_vk
(h, s) = sigma
assert len(private_m) <= len(beta)
r, r_prime = o.random(), o.random()
(h_prime , s_prime) = (r_prime*h , r_prime*s + r*r_prime*h)
sigma_prime =(h_prime, s_prime)
kappa = r*g2 + alpha + ec_sum([private_m[i]*beta[i] for i in range(len(private_m))])
pi_v = make_pi_v(params, aggr_vk, sigma_prime, private_m, r)
Theta = (kappa, sigma_prime, pi_v)
return Theta


def verify_cred(params, aggr_vk, Theta, public_m=[]):
"""
Verify credentials.

Parameters:
- `params`: public parameters generated by `setup`
- `aggr_vk`: aggregated verification key
- `Theta`: credential and cryptographic material to verify them
- `public_m` [Bn]: optional, array containing the public attributes

Returns:
- `ret` (bool): whether the credential verifies
"""
(G, o, g1, hs, g2, e) = params
(g2, _, beta) = aggr_vk
(kappa, sigma, pi_v) = Theta
(h, s) = sigma
private_m_len = len(pi_v[1])
coco_ensure(len(public_m)+private_m_len <= len(beta), "Too many parameters")
# verify proof of correctness
coco_ensure(verify_pi_v(params, aggr_vk, sigma, kappa, pi_v), "ZK proof failed")
# add clear text messages
aggr = G2Elem.inf(G)
if len(public_m) != 0:
aggr = ec_sum([public_m[i]*beta[i+private_m_len] for i in range(len(public_m))])
# verify
return not h.isinf() and e(h, kappa+aggr) == e(s, g2)


4 changes: 2 additions & 2 deletions tests/test_coconut_up.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from coconut.scheme_up import setup, prepare_blind_sign, keygen, agg_key, blind_sign, agg_cred
from coconut.scheme import prove_cred, verify_cred
from coconut.scheme_up import prove_cred, verify_cred

def test_multi_authority():
q = 7 # number of attributes
Expand Down Expand Up @@ -35,4 +35,4 @@ def test_multi_authority():
Theta = prove_cred(min_params, min_aggr_vk, sigma, private_m)

# verify credentials
verify_cred(min_params, min_aggr_vk, Theta, public_m=public_m)
assert verify_cred(min_params, min_aggr_vk, Theta, public_m=public_m)