<s> from petlib . ec import EcGroup <EOL> from petlib . bn import Bn <EOL> from hashlib import sha256 <EOL> import pytest <EOL> def challenge ( elements ) : <EOL> """<STR_LIT>""" <EOL> elem = [ len ( elements ) ] + elements <EOL> elem_str = map ( str , elem ) <EOL> elem_len = map ( lambda x : "<STR_LIT>" % ( len ( x ) , x ) , elem_str ) <EOL> state = "<STR_LIT:|>" . join ( elem_len ) <EOL> H = sha256 ( ) <EOL> H . update ( state . encode ( "<STR_LIT:utf8>" ) ) <EOL> return H . digest ( ) <EOL> class Val : <EOL> """<STR_LIT>""" <EOL> def val ( self , env ) : <EOL> return env [ self . name ] <EOL> def tex ( self ) : <EOL> return "<STR_LIT>" % tex_encode ( self . name ) <EOL> class Pub ( Val ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , zkp , name ) : <EOL> self . name = name <EOL> self . zkp = zkp <EOL> assert name not in zkp . Pub <EOL> zkp . Pub [ name ] = self <EOL> def tex ( self ) : <EOL> return r"<STR_LIT>" % tex_encode ( self . name ) <EOL> class ConstPub ( Pub ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , zkp , name ) : <EOL> self . name = name <EOL> self . zkp = zkp <EOL> assert name not in zkp . Const <EOL> zkp . Const [ name ] = self <EOL> class Sec ( Val ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , zkp , name ) : <EOL> self . name = name <EOL> self . zkp = zkp <EOL> assert name not in zkp . Sec <EOL> zkp . Sec [ name ] = self <EOL> class Gen ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , zkp , name = None , prove = False , constuction = None ) : <EOL> self . name = name <EOL> self . zkp = zkp <EOL> if name : <EOL> assert name not in zkp . Pub <EOL> zkp . Pub [ name ] = self <EOL> self . prove = prove <EOL> self . constuction = constuction <EOL> def get_repr ( self ) : <EOL> if self . name or self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> return [ self ] <EOL> elif self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> return self . constuction [ <NUM_LIT:1> : ] <EOL> raise Exception ( "<STR_LIT>" ) <EOL> def __add__ ( self , other ) : <EOL> assert isinstance ( other , Gen ) <EOL> assert self . zkp == other . zkp <EOL> assert self . prove == other . prove <EOL> prove = self . prove or other . prove <EOL> c = [ "<STR_LIT>" ] + self . get_repr ( ) + other . get_repr ( ) <EOL> newG = Gen ( self . zkp , prove = prove , constuction = c ) <EOL> return newG <EOL> def __rmul__ ( self , other ) : <EOL> assert isinstance ( other , Val ) <EOL> assert not self . prove <EOL> assert self . zkp == other . zkp <EOL> prove = isinstance ( other , Sec ) <EOL> if self . constuction and self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> c = self . constuction + [ other ] <EOL> else : <EOL> c = [ "<STR_LIT>" , self , other ] <EOL> return Gen ( self . zkp , constuction = c , prove = prove ) <EOL> def tex ( self ) : <EOL> if self . name : <EOL> return r"<STR_LIT>" % ( tex_encode ( self . name ) ) <EOL> if self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> gather = [ v . tex ( ) for v in self . constuction [ <NUM_LIT:1> : ] ] <EOL> Sum = "<STR_LIT>" . join ( gather ) <EOL> return "<STR_LIT>" % Sum <EOL> if self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> base = self . constuction [ <NUM_LIT:1> ] . tex ( ) <EOL> exps = [ v . tex ( ) for v in self . constuction [ <NUM_LIT:2> : ] ] <EOL> exps = "<STR_LIT>" . join ( exps ) <EOL> ret = "<STR_LIT>" % ( base , exps ) <EOL> return ret <EOL> def val ( self , env ) : <EOL> """<STR_LIT>""" <EOL> if self . name : <EOL> return env [ self . name ] <EOL> if self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> gather = [ v . val ( env ) for v in self . constuction [ <NUM_LIT:1> : ] ] <EOL> Sum = None <EOL> for v in gather : <EOL> if Sum is None : <EOL> Sum = v <EOL> else : <EOL> Sum = v + Sum <EOL> return Sum <EOL> if self . constuction [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> base = self . constuction [ <NUM_LIT:1> ] . val ( env ) <EOL> exps = [ v . val ( env ) for v in self . constuction [ <NUM_LIT:2> : ] ] <EOL> Prod = <NUM_LIT:1> <EOL> for v in exps : <EOL> Prod = v * Prod <EOL> return Prod * base <EOL> raise Exception ( "<STR_LIT>" ) <EOL> class ConstGen ( Gen ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , zkp , name ) : <EOL> Gen . __init__ ( self , zkp , name = None ) <EOL> self . name = name <EOL> assert name not in self . zkp . Const <EOL> self . zkp . Const [ name ] = self <EOL> class ZKProof ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , G ) : <EOL> """<STR_LIT>""" <EOL> self . G = G <EOL> self . Const = { } <EOL> self . Pub = { } <EOL> self . Sec = { } <EOL> self . proofs = [ ] <EOL> self . arrays = { } <EOL> def add_proof ( self , lhs , rhs ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( lhs , Gen ) <EOL> assert lhs . prove == False <EOL> assert isinstance ( rhs , Gen ) <EOL> assert rhs . prove == True <EOL> assert self == lhs . zkp == rhs . zkp <EOL> self . proofs += [ ( lhs , rhs ) ] <EOL> def _check_name_ok ( self , name ) : <EOL> if __debug__ : <EOL> import re <EOL> a = re . compile ( "<STR_LIT>" ) <EOL> if a . match ( name ) is not None : <EOL> return True <EOL> return False <EOL> def get ( self , vtype , name , ignore_check = False ) : <EOL> """<STR_LIT>""" <EOL> assert vtype in [ Gen , ConstGen , Sec , Pub , ConstPub ] <EOL> if isinstance ( name , str ) : <EOL> assert self . _check_name_ok ( name ) or ignore_check <EOL> return self . _get ( vtype , name , ignore_check ) <EOL> if isinstance ( name , list ) : <EOL> assert all ( map ( self . _check_name_ok , name ) ) or ignore_check <EOL> return [ self . _get ( vtype , n , ignore_check ) for n in name ] <EOL> raise Exception ( "<STR_LIT>" ) <EOL> def _get ( self , vtype , name , ignore_check = False ) : <EOL> assert isinstance ( name , str ) <EOL> for D in [ self . Const , self . Pub , self . Sec ] : <EOL> if name in D : <EOL> assert isinstance ( D [ name ] , vtype ) <EOL> return D [ name ] <EOL> return vtype ( self , name ) <EOL> def get_array ( self , vtype , name , number , start = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> assert vtype in [ Gen , ConstGen , Sec , Pub , ConstPub ] <EOL> assert isinstance ( name , str ) <EOL> assert self . _check_name_ok ( name ) <EOL> if name in self . arrays : <EOL> assert self . arrays [ name ] == ( number , start ) <EOL> else : <EOL> self . arrays [ name ] = ( number , start ) <EOL> names = [ "<STR_LIT>" % ( name , i ) for i in range ( start , start + number ) ] <EOL> return self . get ( vtype , names , True ) <EOL> def all_vars ( self ) : <EOL> variables = list ( self . Const ) + list ( self . Pub ) + list ( self . Sec ) <EOL> return set ( variables ) <EOL> def _check_env ( self , env ) : <EOL> if __debug__ : <EOL> variables = self . all_vars ( ) <EOL> for v in variables : <EOL> if not v in env : <EOL> raise Exception ( "<STR_LIT>" % v ) <EOL> def render_proof_statement ( self ) : <EOL> s = r'<STR_LIT:$>' <EOL> if len ( self . Const ) > <NUM_LIT:0> : <EOL> variables = [ ] <EOL> for con in sorted ( list ( self . Const ) ) : <EOL> variables += [ "<STR_LIT>" % tex_encode ( con ) ] <EOL> s += r"<STR_LIT>" % ( '<STR_LIT:U+002CU+0020>' . join ( variables ) ) <EOL> if len ( self . Pub ) > <NUM_LIT:0> : <EOL> variables = [ ] <EOL> for pub in sorted ( list ( self . Pub ) ) : <EOL> variables += [ "<STR_LIT>" % tex_encode ( pub ) ] <EOL> s += r"<STR_LIT>" % ( '<STR_LIT:U+002CU+0020>' . join ( variables ) ) <EOL> s += r"<STR_LIT>" + """<STR_LIT:(>""" <EOL> variables = [ ] <EOL> for sec in sorted ( list ( self . Sec ) ) : <EOL> variables += [ "<STR_LIT>" % tex_encode ( sec ) ] <EOL> variables = '<STR_LIT:U+002CU+0020>' . join ( variables ) <EOL> s += variables <EOL> s += r"<STR_LIT>" <EOL> formulas = [ ] <EOL> for base , expr in self . proofs : <EOL> formulas += [ "<STR_LIT>" % ( base . tex ( ) , expr . tex ( ) ) ] <EOL> s += r"<STR_LIT>" . join ( formulas ) <EOL> s += r'<STR_LIT>' <EOL> return s <EOL> def build_proof ( self , env , message = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> self . _check_env ( env ) <EOL> if __debug__ : <EOL> for base , expr in self . proofs : <EOL> xGen = base . val ( env ) <EOL> xExpr = expr . val ( env ) <EOL> try : <EOL> assert xGen == xExpr <EOL> except : <EOL> raise Exception ( "<STR_LIT>" % base . name ) <EOL> G = self . G <EOL> order = G . order ( ) <EOL> state = [ '<STR_LIT>' , G . nid ( ) , message ] <EOL> for v in sorted ( self . Const . keys ( ) ) : <EOL> state += [ env [ v ] ] <EOL> for v in sorted ( self . Pub . keys ( ) ) : <EOL> state += [ env [ v ] ] <EOL> witnesses = dict ( env . items ( ) ) <EOL> for w in self . Sec . keys ( ) : <EOL> assert w in witnesses <EOL> witnesses [ w ] = order . random ( ) <EOL> for base , expr in self . proofs : <EOL> Cw = expr . val ( witnesses ) <EOL> state += [ Cw ] <EOL> hash_c = challenge ( state ) <EOL> c = Bn . from_binary ( hash_c ) % order <EOL> responses = dict ( env . items ( ) ) <EOL> for w in self . Sec . keys ( ) : <EOL> responses [ w ] = ( witnesses [ w ] - c * env [ w ] ) % order <EOL> for v in self . Const : <EOL> del responses [ v ] <EOL> return ( c , responses ) <EOL> def verify_proof ( self , env , sig , message = "<STR_LIT>" , strict = True ) : <EOL> """<STR_LIT>""" <EOL> env_l = [ ( k , v ) for k , v in env . items ( ) if k in self . Const ] <EOL> if __debug__ and strict : <EOL> env_not = [ k for k , v in env . items ( ) if k not in self . Const ] <EOL> if len ( env_not ) : <EOL> raise Exception ( "<STR_LIT>" + ( "<STR_LIT:U+002CU+0020>" . join ( env_not ) ) ) <EOL> c , responses = sig <EOL> responses = dict ( list ( responses . items ( ) ) + env_l ) <EOL> self . _check_env ( responses ) <EOL> G = self . G <EOL> order = G . order ( ) <EOL> state = [ '<STR_LIT>' , G . nid ( ) , message ] <EOL> for v in sorted ( self . Const . keys ( ) ) : <EOL> state += [ responses [ v ] ] <EOL> for v in sorted ( self . Pub . keys ( ) ) : <EOL> state += [ responses [ v ] ] <EOL> for base , expr in self . proofs : <EOL> Cr = expr . val ( responses ) <EOL> Cx = base . val ( responses ) <EOL> Cw = Cr + c * Cx <EOL> state += [ Cw ] <EOL> hash_c = challenge ( state ) <EOL> c_prime = Bn . from_binary ( hash_c ) % order <EOL> return ( c == c_prime ) <EOL> class ZKEnv ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , zkp ) : <EOL> """<STR_LIT>""" <EOL> object . __setattr__ ( self , "<STR_LIT>" , zkp ) <EOL> object . __setattr__ ( self , "<STR_LIT>" , { } ) <EOL> def __setattr__ ( self , name , value ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( value , list ) : <EOL> assert name in self . zkp . arrays <EOL> number , start = self . zkp . arrays [ name ] <EOL> assert len ( value ) == number <EOL> for i , v in enumerate ( value ) : <EOL> n = "<STR_LIT>" % ( name , start + i ) <EOL> self . _set_var ( n , v ) <EOL> else : <EOL> self . _set_var ( name , value ) <EOL> def _set_var ( self , name , value ) : <EOL> if not name in self . zkp . all_vars ( ) : <EOL> raise Exception ( "<STR_LIT>" % name ) <EOL> self . env [ name ] = value <EOL> def __getattr__ ( self , name ) : <EOL> if not name in self . zkp . all_vars ( ) : <EOL> raise Exception ( "<STR_LIT>" % name ) <EOL> return self . env [ name ] <EOL> def get ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . env <EOL> import re <EOL> def tex_encode ( name ) : <EOL> m = re . match ( r"<STR_LIT>" , name ) <EOL> if m != None : <EOL> return r"<STR_LIT>" % ( tex_encode ( m . group ( <NUM_LIT:1> ) ) , m . group ( <NUM_LIT:2> ) ) <EOL> m = re . match ( r"<STR_LIT>" , name ) <EOL> if m != None : <EOL> return r"<STR_LIT>" % ( tex_encode ( m . group ( <NUM_LIT:1> ) ) ) <EOL> m = re . match ( r"<STR_LIT>" , name ) <EOL> if m != None : <EOL> return r"<STR_LIT>" % ( tex_encode ( m . group ( <NUM_LIT:1> ) ) ) <EOL> return name <EOL> def test_tex ( ) : <EOL> assert "<STR_LIT>" in tex_encode ( "<STR_LIT>" ) <EOL> assert "<STR_LIT>" in tex_encode ( "<STR_LIT>" ) <EOL> assert r"<STR_LIT>" in tex_encode ( "<STR_LIT>" ) <EOL> def test_basic ( ) : <EOL> zk = ZKProof ( None ) <EOL> g = zk . get ( ConstGen , "<STR_LIT:g>" ) <EOL> g2 = zk . get ( ConstGen , "<STR_LIT:g>" ) <EOL> assert g == g2 <EOL> with pytest . raises ( Exception ) as excinfo : <EOL> zk . get ( Pub , "<STR_LIT:g>" ) <EOL> assert "<STR_LIT>" in str ( excinfo . value ) <EOL> h = zk . get ( ConstGen , "<STR_LIT:h>" ) <EOL> Gone = zk . get ( ConstGen , "<STR_LIT>" ) <EOL> x = zk . get ( Sec , "<STR_LIT:x>" ) <EOL> o = zk . get ( Sec , "<STR_LIT:o>" ) <EOL> y = zk . get ( Pub , "<STR_LIT:y>" ) <EOL> one = zk . get ( ConstPub , "<STR_LIT>" ) <EOL> Cx = zk . get ( Gen , "<STR_LIT>" ) <EOL> Cxp = x * g + o * ( y * h ) <EOL> zk . add_proof ( Cx , Cxp ) <EOL> print ( zk . Const . keys ( ) ) <EOL> print ( zk . Pub . keys ( ) ) <EOL> print ( zk . Sec . keys ( ) ) <EOL> def test_Pedersen ( ) : <EOL> G = EcGroup ( <NUM_LIT> ) <EOL> order = G . order ( ) <EOL> zk = ZKProof ( G ) <EOL> g , h = zk . get ( ConstGen , [ "<STR_LIT:g>" , "<STR_LIT:h>" ] ) <EOL> x , o = zk . get ( Sec , [ "<STR_LIT:x>" , "<STR_LIT:o>" ] ) <EOL> Cxo = zk . get ( Gen , "<STR_LIT>" ) <EOL> zk . add_proof ( Cxo , x * g + o * h ) <EOL> ec_g = G . generator ( ) <EOL> ec_h = order . random ( ) * ec_g <EOL> bn_x = order . random ( ) <EOL> bn_o = order . random ( ) <EOL> ec_Cxo = bn_x * ec_g + bn_o * ec_h <EOL> env = { <EOL> "<STR_LIT:g>" : ec_g , <EOL> "<STR_LIT:h>" : ec_h , <EOL> "<STR_LIT>" : ec_Cxo , <EOL> "<STR_LIT:x>" : bn_x , <EOL> "<STR_LIT:o>" : bn_o <EOL> } <EOL> sig = zk . build_proof ( env ) <EOL> env_verify = { <EOL> "<STR_LIT:g>" : ec_g , <EOL> "<STR_LIT:h>" : ec_h <EOL> } <EOL> assert zk . verify_proof ( env_verify , sig ) <EOL> def test_Pedersen_Env ( ) : <EOL> G = EcGroup ( <NUM_LIT> ) <EOL> order = G . order ( ) <EOL> zk = ZKProof ( G ) <EOL> g , h = zk . get ( ConstGen , [ "<STR_LIT:g>" , "<STR_LIT:h>" ] ) <EOL> x , o = zk . get ( Sec , [ "<STR_LIT:x>" , "<STR_LIT:o>" ] ) <EOL> Cxo = zk . get ( Gen , "<STR_LIT>" ) <EOL> zk . add_proof ( Cxo , x * g + o * h ) <EOL> print ( zk . render_proof_statement ( ) ) <EOL> ec_g = G . generator ( ) <EOL> ec_h = order . random ( ) * ec_g <EOL> bn_x = order . random ( ) <EOL> bn_o = order . random ( ) <EOL> ec_Cxo = bn_x * ec_g + bn_o * ec_h <EOL> env = ZKEnv ( zk ) <EOL> env . g , env . h = ec_g , ec_h <EOL> env . Cxo = ec_Cxo <EOL> env . x = bn_x <EOL> env . o = bn_o <EOL> sig = zk . build_proof ( env . get ( ) ) <EOL> env = ZKEnv ( zk ) <EOL> env . g , env . h = ec_g , ec_h <EOL> assert zk . verify_proof ( env . get ( ) , sig ) <EOL> def test_Pedersen_Env_missing ( ) : <EOL> G = EcGroup ( <NUM_LIT> ) <EOL> order = G . order ( ) <EOL> zk = ZKProof ( G ) <EOL> g , h = zk . get ( ConstGen , [ "<STR_LIT:g>" , "<STR_LIT:h>" ] ) <EOL> x , o = zk . get ( Sec , [ "<STR_LIT:x>" , "<STR_LIT:o>" ] ) <EOL> Cxo = zk . get ( Gen , "<STR_LIT>" ) <EOL> zk . add_proof ( Cxo , x * g + o * h ) <EOL> ec_g = G . generator ( ) <EOL> ec_h = order . random ( ) * ec_g <EOL> bn_x = order . random ( ) <EOL> bn_o = order . random ( ) <EOL> ec_Cxo = bn_x * ec_g + bn_o * ec_h <EOL> env = ZKEnv ( zk ) <EOL> env . g , env . h = ec_g , ec_h <EOL> env . Cxo = ec_Cxo <EOL> env . x = bn_x <EOL> with pytest . raises ( Exception ) as excinfo : <EOL> env . NOTEXISTING = bn_x <EOL> assert "<STR_LIT>" in str ( excinfo . value ) <EOL> with pytest . raises ( Exception ) as excinfo : <EOL> zk . build_proof ( env . get ( ) ) <EOL> assert '<STR_LIT>' in str ( excinfo . value ) <EOL> env . o = bn_o + <NUM_LIT:1> <EOL> with pytest . raises ( Exception ) as excinfo : <EOL> zk . build_proof ( env . get ( ) ) <EOL> assert "<STR_LIT>" in str ( excinfo . value ) <EOL> def test_latex_print ( ) : <EOL> G = EcGroup ( <NUM_LIT> ) <EOL> order = G . order ( ) <EOL> zk = ZKProof ( G ) <EOL> g , h = zk . get ( ConstGen , [ "<STR_LIT:g>" , "<STR_LIT:h>" ] ) <EOL> x , o = zk . get ( Sec , [ "<STR_LIT:x>" , "<STR_LIT:o>" ] ) <EOL> Cxo = zk . get ( Gen , "<STR_LIT>" ) <EOL> zk . add_proof ( Cxo , x * g + o * h ) <EOL> print ( zk . render_proof_statement ( ) ) </s>
