def schnorr_NIZK(): # setup start = time.time() grp = PairingGroup('MNT224') ps = PS01(grp) end = time.time() print("Setup time elapse: ") print(end - start) # keygen start = time.time() (pk, sk) = ps.keygen(2) end = time.time() print("KeyGen over two attributes time elapse: ") print(end - start) # generate a secret secret = grp.random() # NIZK Schnorr prover start = time.time() na = grp.random() a = pk['Y1'][0] ** na # deterministic nb m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pk['Y1'][0] ** secret)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) # r r = na + nb * secret end = time.time() print("NIZK Schnorr on one attribute Prover time elapse: ") print(end - start) # NIZK Schnorr verifier start = time.time() m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pk['Y1'][0] ** secret)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) lh = pk['Y1'][0] ** r rh = a * (pk['Y1'][0] ** secret) ** nb end = time.time() print("NIZK Schnorr Verifier time elapse: ") print(end - start) if lh == rh: print('check success') else: print('lh:=', lh) print('rh:=', rh)
def test_ps_sign_schnorr(): grp = PairingGroup('MNT224') ps = PS01(grp) messages = ["hi there"] (pk, sk) = ps.keygen(len(messages) + 1) if debug: print("Keygen...") print("pk :=", pk) print("sk :=", sk) t, commitment = ps.commitment(pk, *messages) # append public information commitment = commitment * (pk['Y1'][-1] ** grp.hash('3600', ZR)) if debug: print("commitment: ", commitment) be_signed = commitment sig = ps.sign(sk, pk, commitment) if debug: print("Signature: ", sig) sig = ps.unblind_signature(t, sig) # append public information messages.append('3600') result = ps.verify(pk, sig, *messages) assert result, "INVALID signature!" if debug: print("Successful Verification!!!") # sec6.2 randomize s1, s2 = sig t = grp.random(ZR) r = grp.random(ZR) s1p = s1**r s2p = (s2*(s1**t))**r # sec6.2 verify lh = pair(s1p, pk['X2']) lh = lh * ps.product([pair(s1p, y**grp.hash(m, ZR)) for y, m in zip(pk['Y2'], messages)]) lh = lh * pair(s1p, pk['g2']**t) rh = pair(s2p, pk['g2']) if lh == rh: print('check success') else: print('lh:=', lh) print('rh:=', rh)
def schnorr_protocol(): grp = PairingGroup('MNT224') ps = PS01(grp) (pk, sk) = ps.keygen(2) t = grp.random() # A na = grp.random() a = pk['g2'] ** na # B nb = grp.random() # A r = na + nb * t # C lh = pk['g2'] ** r rh = a * (pk['g2'] ** t) ** nb if lh == rh: print('check success') else: print('lh:=', lh) print('rh:=', rh)
def schnorr_protocol_y_instead_of_g(): grp = PairingGroup('MNT224') ps = PS01(grp) (pk, sk) = ps.keygen(2) secret = grp.random() # A na = grp.random() a = pk['Y1'][0] ** na # B nb = grp.random() # A r = na + nb * secret # B lh = pk['Y1'][0] ** r rh = a * (pk['Y1'][0] ** secret) ** nb if lh == rh: print('check success') else: print('lh:=', lh) print('rh:=', rh)
async def main(): # group setup and secret generation setup_start_time = time.time() global grp, ps, pk, secret, messages, sig, gamma, expires_in grp = PairingGroup('MNT224') messages = ['random_string'] secret = grp.hash(messages[0], ZR) ps = PS01(grp) pk = None setup_end_time = time.time() print("Setup total time: {0}s ".format(str(setup_end_time - setup_start_time))) # communicate with IdP print("****Communication with IdP****") idp_start_time = time.time() async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: # first rt: get idp public key pk = await fetch(session, 'https://' + idp_ip + ':6000/') for key, value in pk.items(): if key in {'X2', 'g1', 'g2'}: pk[key] = grp.deserialize(value.encode()) else: pk[key] = [grp.deserialize(item.encode()) for item in value] if debug: print('idp pk:=', pk) # generate t and commitment start = time.time() t = grp.random(ZR) gt = (pk['g1'] ** t) commitment_secret = pk['Y1'][0] ** secret commitment = gt * commitment_secret if debug: print("commitment: ", commitment) end = time.time() print("CRED.PrepareBlindSign over {0} attributes time elapse: {1}s ".format(str(1), str(end - start))) # second rt: schnorr proof start = time.time() na = grp.random() a = pk['Y1'][0] ** na # schnorr NIZK: generate nb m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pk['Y1'][0] ** secret)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) r = na + nb * secret end = time.time() print("NIZK Schnorr Prover (User-IdP) over {0} element time elapse: {1}s ".format(str(1), str(end - start))) json_param = {'g_t': grp.serialize(gt).decode(), 'commitment_secret': grp.serialize(commitment_secret).decode(), 'a': grp.serialize(a).decode(), 'r': grp.serialize(r).decode()} json_rep = await fetch(session, 'https://' + idp_ip + ':6000/token', json_param) # parse the reply id_token = json_rep['id_token'] id_token = [grp.deserialize(item.encode()) for item in id_token] expires_in = json_rep['expires_in'] gamma = json_rep['gamma'] if debug: print('user id token:=', id_token) print('expires_in:=', expires_in) print('gamma:=', gamma) # unblind signature start = time.time() sig = ps.unblind_signature(t, id_token) end = time.time() print("CRED.Unblind time elapse: {0}s ".format(str(end - start))) messages.append(gamma) messages.append(expires_in) for i in range(3, len(pk['Y1'])): messages.append(str(i - 3) + 'th-element') if debug: print(messages) result = ps.verify(pk, sig, *messages) assert result, 'invalid signature' print('Successfully verification') gamma = grp.hash(gamma, ZR) idp_end_time = time.time() print("IdP total time: {0}s ".format(str(idp_end_time - idp_start_time))) # communicate with RP rp_start_time = time.time() for i in range(running_times): print("\n****Communication with RP****") async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: json_param = generate_params_for_RP() json_rep = await fetch(session, 'https://' + rp_ip + ':6001/authenticate', json_param) if debug: print(json_rep) rp_end_time = time.time() print("RP total time: {0}s ".format(str(rp_end_time - rp_start_time)))
def measure_time(attribute_num): # setup start = time.time() grp = PairingGroup('MNT224') ps = PS01(grp) end = time.time() print("Setup time elapse: ") print(end - start) # keygen start = time.time() (pk, sk) = ps.keygen(attribute_num) end = time.time() print("KeyGen over {0} attributes time elapse: {1}s ".format(str(attribute_num), str(end - start))) # generate a secret secret = grp.random() # NIZK Schnorr prover start = time.time() na = grp.random() a = pk['Y1'][0] ** na # deterministic nb m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pk['Y1'][0] ** secret)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) # r r = na + nb * secret end = time.time() print("NIZK Schnorr over {0} attributes Prover time elapse: {1}s".format(str(attribute_num), str((end - start)*attribute_num))) # NIZK Schnorr verifier start = time.time() m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pk['Y1'][0] ** secret)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) lh = pk['Y1'][0] ** r rh = a * (pk['Y1'][0] ** secret) ** nb end = time.time() print("NIZK Schnorr over {0} attributes Verifier time elapse: {1}s".format(str(attribute_num), str((end - start)*attribute_num))) if lh == rh: print('NIZK check success') else: print('NIZK check failure') # request ID messages = ["hello" + str(i) for i in range(0, attribute_num)] start = time.time() t, commitment = ps.commitment(pk, *messages) end = time.time() print("requestID over {0} attributes time elapse: {1}s".format(str(attribute_num), str(end - start))) # prove ID start = time.time() sig = ps.sign(sk, pk, commitment) end = time.time() print("ProvideID over {0} attributes time elapse: {1}s".format(str(attribute_num), str(end - start))) # unblind signature start = time.time() sig = ps.unblind_signature(t, sig) end = time.time() print("Unblind over {0} attributes time elapse: {1}s".format(str(attribute_num), str(end - start))) # prove ID start = time.time() rand_sig = ps.randomize_sig(sig) cipher_sk = grp.random() cipher_1 = pk['Y2'][1] ** cipher_sk cipher_pk = (pk['Y2'][1] ** grp.hash('authority')) ** cipher_sk cipher_2 = cipher_pk * (pk['Y2'][0] ** grp.hash(messages[0], ZR)) end = time.time() print("Credential Randomize over {0} attributes time elapse: {1}s".format(str(attribute_num), str(end - start))) # cred.verify start = time.time() result = ps.verify(pk, rand_sig, *messages) end = time.time() print("RP's Credential Verify over {0} attributes time elapse: {1}s".format(str(attribute_num), str(end - start)))
def test_ps_sign(): grp = PairingGroup('MNT224') ps = PS01(grp) # messages = ['Hi there', 'Not there', 'Some message ................', 'Dont know .............', 'great!!!!'] messages = ["hi there"] (pk, sk) = ps.keygen(20) if debug: print("Keygen...") print("pk :=", pk) print("sk :=", sk) pk_len = 0 sk_len = 0 pk_serial = dict(pk) sk_serial = dict(sk) for key, value in sk_serial.items(): sk_serial[key] = grp.serialize(value).decode() for key, value in pk_serial.items(): if key in {'X2', 'g1', 'g2'}: pk_serial[key] = grp.serialize(value).decode() else: pk_serial[key] = [grp.serialize(item).decode() for item in value] for key, value in pk_serial.items(): if key in {'X2', 'g1', 'g2'}: pk_len += len(pk_serial[key]) else: for item in pk_serial[key]: pk_len += len(item) for key, value in sk_serial.items(): sk_len += len(sk_serial[key]) print('public key bytes: ', str(pk_len)) print('private key bytes: ', str(sk_len)) t = grp.random() print(t) print('random number len') print(len(grp.serialize(t).decode())) zeta = grp.random(G1) zeta = zeta ** t print(zeta) print('group element len') print(len(grp.serialize(zeta).decode())) t, commitment = ps.commitment(pk, *messages) if debug: print("commitment: ", commitment) be_signed = commitment sig = ps.sign(sk, pk, commitment) if debug: print("Signature: ", sig) sig = ps.unblind_signature(t, sig) print(len(grp.serialize(sig[0]).decode())) print(len(grp.serialize(sig[1]).decode())) result = ps.verify(pk, sig, *messages) assert result, "INVALID signature!" if debug: print("Successful Verification!!!") rand_sig = ps.randomize_sig(sig) assert sig != rand_sig if debug: print("Randomized Signature: ", rand_sig) result = ps.verify(pk, rand_sig, *messages) assert result, "INVALID signature!" if debug: print("Successful Verification!!!")
def test_ps_sign_with_public_info(): # setup start = time.time() grp = PairingGroup('MNT224') ps = PS01(grp) end = time.time() print("Setup time elapse: ") print(end - start) # messages = ['Hi there', 'Not there', 'Some message ................', 'Dont know .............', 'great!!!!'] messages = ["hi there"] # keygen start = time.time() (pk, sk) = ps.keygen(len(messages) + 1) end = time.time() print("KeyGen time elapse: ") print(end - start) if debug: print("Keygen...") print("pk :=", pk) print("sk :=", sk) # requestID start = time.time() t, commitment = ps.commitment(pk, *messages) end = time.time() print("requestID time elapse: ") print(end - start) # append public information start = time.time() commitment = commitment * (pk['Y1'][-1] ** grp.hash('3600', ZR)) sig = ps.sign(sk, pk, commitment) end = time.time() print("ProvideID time elapse: ") print(end - start) if debug: print("commitment: ", commitment) if debug: print("Signature: ", sig) # unblind signature start = time.time() sig = ps.unblind_signature(t, sig) end = time.time() print("Unblind time elapse: ") print(end - start) # append public information messages.append('3600') result = ps.verify(pk, sig, *messages) assert result, "INVALID signature!" if debug: print("Successful Verification!!!") # prove ID start = time.time() rand_sig = ps.randomize_sig(sig) end = time.time() print("Credential Randomize time elapse: ") print(end - start) assert sig != rand_sig if debug: print("Randomized Signature: ", rand_sig) # cred.verify start = time.time() result = ps.verify(pk, rand_sig, *messages) end = time.time() print("RP's Credential Verify time elapse: ") print(end - start) assert result, "INVALID signature!" if debug: print("Successful Verification!!!")
def app_main(): app = Flask(__name__, template_folder="templates") # parameters grp = PairingGroup('MNT224') ps = PS01(grp) # get idp public key pk = requests.get('https://' + idp_ip + ':6000/', verify=False).json() for key, value in pk.items(): if key in {'X2', 'g1', 'g2'}: pk[key] = grp.deserialize(value.encode()) else: pk[key] = [grp.deserialize(item.encode()) for item in value] if debug: print('idp pk:=', pk, flush=True) @app.route('/authenticate', methods=['GET', 'POST']) def authenticate(): # For the purpose of throughput measurement global user_auth_start_tp, counter if user_auth_start_tp == 0: user_auth_start_tp = time.time() print("RP Throughput: {0}s for {1} authentications".format( str(time.time() - user_auth_start_tp), str(counter))) counter += 1 print("Authentication request content length: ", request.content_length, flush=True) authenticate_request = request.get_json() # first finish the Schnorr verification hidden_element_num = int( authenticate_request['additional_element_num']) schnorr_pas = [ grp.deserialize(authenticate_request['g2_t'].encode()), grp.deserialize(authenticate_request['user_id'].encode()), grp.deserialize( authenticate_request['commitment_secret'].encode()), grp.deserialize(authenticate_request['commitment_gamma'].encode()), ] cipher_1 = grp.deserialize( authenticate_request['el_cipher_1'].encode()) cipher_2 = grp.deserialize( authenticate_request['el_cipher_2'].encode()) schnorr_as = [ grp.deserialize(authenticate_request['g2_t_a'].encode()), grp.deserialize(authenticate_request['user_id_a'].encode()), grp.deserialize( authenticate_request['commitment_secret_a'].encode()), grp.deserialize( authenticate_request['commitment_gamma_a'].encode()), ] cipher_1_a = grp.deserialize( authenticate_request['el_cipher_1_a'].encode()) cipher_2_a = grp.deserialize( authenticate_request['el_cipher_2_a'].encode()) schnorr_rs = [ grp.deserialize(authenticate_request['g2_t_r'].encode()), grp.deserialize(authenticate_request['user_id_r'].encode()), grp.deserialize( authenticate_request['commitment_secret_r'].encode()), grp.deserialize( authenticate_request['commitment_gamma_r'].encode()), ] cipher_1_r = grp.deserialize( authenticate_request['el_cipher_1_r'].encode()) cipher_2_r1 = grp.deserialize( authenticate_request['el_cipher_2_r1'].encode()) cipher_2_r2 = grp.deserialize( authenticate_request['el_cipher_2_r2'].encode()) schnorr_bases = [ pk['g2'], grp.hash('domain', G1), pk['Y2'][0], pk['Y2'][1], ] for i in range(hidden_element_num): schnorr_pas.append( grp.deserialize(authenticate_request[str(i) + 'th-pa'].encode())) schnorr_as.append( grp.deserialize(authenticate_request[str(i) + 'th-a'].encode())) schnorr_rs.append( grp.deserialize(authenticate_request[str(i) + 'th-r'].encode())) schnorr_bases.append(pk['Y2'][3 + i]) if debug: print("Schnorr PAs: "******"Schnorr As: ") print(schnorr_as) print("Schnorr Rs: ") print(schnorr_rs) # generate nbs start = time.time() m = hashlib.sha256() m.update(grp.serialize(schnorr_bases[0])) m.update(grp.serialize(schnorr_as[0])) m.update(grp.serialize(schnorr_pas[0])) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) schnorr_result = True for i in range(len(schnorr_pas)): lh = schnorr_bases[i]**schnorr_rs[i] rh = schnorr_as[i] * schnorr_pas[i]**nb schnorr_result = (schnorr_result and (lh == rh)) if debug and schnorr_result is False: print(i) # ciphertext 1 lh = grp.hash('random2', G1)**cipher_1_r rh = cipher_1_a * cipher_1**nb schnorr_result = (schnorr_result and (lh == rh)) # ciphertext 2 authority_pk = pk['g1']**grp.hash('authority') lh = (authority_pk**cipher_2_r1) * (grp.hash('random1', G1)** cipher_2_r2) rh = cipher_2_a * cipher_2**nb schnorr_result = (schnorr_result and (lh == rh)) end = time.time() print( "NIZK Schnorr Verifier (User-RP) over {0} element time elapse: {1}s " .format(str(len(schnorr_pas) + 2), str(end - start)), flush=True) if schnorr_result is True: if debug: print('schnorr checking succeeds', flush=True) else: if debug: print('schnorr checking fails', flush=True) return jsonify(status='failure') # PS signature proof start = time.time() rand_sig = [ grp.deserialize(item.encode()) for item in authenticate_request['rand_sig'] ] expires_in = authenticate_request['expires_in'] s1p, s2p = rand_sig messages = [ schnorr_pas[2], schnorr_pas[3], pk['Y2'][2]**grp.hash(expires_in, ZR) ] for i in range(hidden_element_num): messages.append(schnorr_pas[4 + i]) for i in range(3 + hidden_element_num, len(pk['Y2'])): messages.append(pk['Y2'][i]**grp.hash(str(i - 3) + 'th-element')) lh = pair(s1p, pk['X2']) lh = lh * ps.product([pair(s1p, m) for m in messages]) lh = lh * pair(s1p, schnorr_pas[0]) # lh_2 = pk['X2'] # for m in messages: # lh_2 = lh_2 * m # lh_2 = lh_2 * schnorr_pas[0] # lh = pair(s1p, lh_2) rh = pair(s2p, pk['g2']) end = time.time() print("Cred.Verify over {0} element time elapse: {1}s ".format( str(len(pk['Y2'])), str(end - start)), flush=True) if lh == rh: if debug: print('PS proof check succeeds', flush=True) return jsonify(status='success') else: if debug: print('PS proof check fails', flush=True) print('lh:=', lh, flush=True) print('rh:=', rh, flush=True) return jsonify(status='failure') app.run(host='0.0.0.0', port=6001, ssl_context='adhoc')
async def main(): # group setup and secret generation setup_start_time = time.time() global grp, ps, pk, secret, messages, sig, gamma, expires_in grp = PairingGroup('MNT224') messages = ['random_string'] secret = grp.hash(messages[0], ZR) ps = PS01(grp) pk = None setup_end_time = time.time() print("Setup total time: {0}s ".format(str(setup_end_time - setup_start_time))) # communicate with IdP print("****Communication with IdP****") idp_start_time = time.time() async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: # first rt: get idp public key pk = await fetch(session, 'https://' + idp_ip + ':6000/') for key, value in pk.items(): if key in {'X2', 'g1', 'g2'}: pk[key] = grp.deserialize(value.encode()) else: pk[key] = [grp.deserialize(item.encode()) for item in value] if debug: print('idp pk:=', pk) # generate t and commitment start = time.time() t = grp.random(ZR) gt = (pk['g1'] ** t) commitment_secret = pk['Y1'][0] ** secret commitment = gt * commitment_secret if debug: print("commitment: ", commitment) end = time.time() print("CRED.PrepareBlindSign over {0} attributes time elapse: {1}s ".format(str(1), str(end - start))) # second rt: schnorr proof start = time.time() na = grp.random() a = pk['Y1'][0] ** na # schnorr NIZK: generate nb m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pk['Y1'][0] ** secret)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) r = na + nb * secret end = time.time() print("NIZK Schnorr Prover (User-IdP) over {0} element time elapse: {1}s ".format(str(1), str(end - start))) json_param = {'g_t': grp.serialize(gt).decode(), 'commitment_secret': grp.serialize(commitment_secret).decode(), 'a': grp.serialize(a).decode(), 'r': grp.serialize(r).decode()} average_time = 0 counter = 0 for i in range(0, 20): time1 = time.time() print(time.time()) json_rep = await fetch(session, 'https://' + idp_ip + ':6000/token', json_param) time2 = time.time() counter += 1 average_time += (time2 - time1) if 1/running_frequency - (time2 - time1) > 0: time.sleep(1/running_frequency - (time2 - time1)) print("average time per credential: ", str(average_time/counter)) idp_end_time = time.time() print("IdP total time: {0}s ".format(str(idp_end_time - idp_start_time)))
def app_main(): app = Flask(__name__) # BOOTSTRAP: generate pp and pk,sk global grp, ps, pk, sk start = time.time() grp = PairingGroup('MNT224') ps = PS01(grp) end = time.time() print("CRED.Setup time elapse: {0}s ".format(str(end - start)), flush=True) # KEYGEN start = time.time() (pk, sk) = ps.keygen(3 + credential_element_size) # messages format: [user_secret, gamma, expires_in] end = time.time() print("CRED.KeyGen over {0} attributes time elapse: {1}s ".format(str(3 + credential_element_size), str(end - start)), flush=True) if debug: print("Keygen...", flush=True) print("pk :=", pk, flush=True) print("sk :=", sk, flush=True) @app.route('/', methods=['GET', 'POST']) def index(): global pk_json if pk_json is None: pk_serial = dict(pk) for key, value in pk_serial.items(): if debug: print(key) if key in {'X2', 'g1', 'g2'}: pk_serial[key] = grp.serialize(value).decode() else: pk_serial[key] = [grp.serialize(item).decode() for item in value] pk_json = jsonify(pk_serial) return pk_json @app.route('/token', methods=['GET', 'POST']) def token(): # For the purpose of throughput measurement global credential_issuing_start_tp, counter if credential_issuing_start_tp == 0: credential_issuing_start_tp = time.time() print("IdP Throughput: {0}s for {1} credentials".format(str(time.time() - credential_issuing_start_tp), str(counter))) counter += 1 # IdP logic starts here print("Credential request content length: ", request.content_length, flush=True) request_json = request.get_json() gt = grp.deserialize(request_json['g_t'].encode()) a = grp.deserialize(request_json['a'].encode()) pa = grp.deserialize(request_json['commitment_secret'].encode()) r = grp.deserialize(request_json['r'].encode()) # generate nb start = time.time() m = hashlib.sha256() m.update(grp.serialize(pk['Y1'][0])) m.update(grp.serialize(a)) m.update(grp.serialize(pa)) m.update(b'userid') # replaced with real values nb = m.digest() nb = grp.hash(nb) # do the check lh = pk['Y1'][0] ** r rh = a * (pa ** nb) end = time.time() print("NIZK Schnorr verifier (User-IdP) over {0} " "attributes time elapse: {1}s ".format(str(1), str(end - start)), flush=True) if lh == rh: if debug: print('Successfully finish Schnorr protocol', flush=True) # Cred.Sign start = time.time() gamma = grp.random() user_commit = gt * pa user_id_token = ps_sign(user_commit, 3600 * 12 * 30, gamma) end = time.time() print("CRED.Sign over {0} attributes" " time elapse: {1}s ".format(str(3 + credential_element_size), str(end - start)), flush=True) user_id_token = [grp.serialize(item).decode() for item in user_id_token] return jsonify( gamma=str(gamma), expires_in=str(3600 * 12 * 30), id_token=user_id_token, ) else: if debug: print("lh:=", lh, flush=True) print('rh:=', rh, flush=True) return None app.run(host='0.0.0.0', port=6000, ssl_context='adhoc')