def add_char(): new_key = input('API key: ') new_vcode = input('Verification Code: ') api = evelink.api.API(api_key=(new_key, new_vcode)) acc = evelink.account.Account(api) try: chars = acc.characters() number = 0 num2char = {} for charID in chars.result: char = chars.result[charID] print('{id}) {name} ({corp})'.format(id=number, name=char['name'], corp=char['corp']['name'])) num2char[number] = charID number += 1 try: charNumber = int(input('Select a Character: ')) email = input('Associated email address: ') name = chars.result[num2char[charNumber]]['name'] km = KeyManager(key_store_path) km.add(new_key, new_vcode, num2char[charNumber], name, email) print('Added character {name} successfully'.format(name=name)) except ValueError: print('wrong input') exit(2) except APIError: exit(1) print('Authentication failure.') exit(0)
def accept_minion_key(minion_id): try: k = KeyManager() k.accept_key(minion_id) except: raise return
def rm_char(): list_char() try: rm = int(input('which character should be deleted: ')) km = KeyManager(key_store_path) km.remove(rm) except (ValueError, IndexError): print('wrong input') exit(2)
def save_my_pem(): self.km = KeyManager() my_pem = self.km.export_key_pair(p_phrase.get()) my_pem_hex = binascii.hexlify(my_pem).decode('ascii') # とりあえずファイル名は固定 path = 'my_key_pair.pem' f1 = open(path, 'a') f1.write(my_pem_hex) f1.close() f.destroy() self.um = UTXOManager(self.km.my_address()) self.um.my_balance = 0 self.update_balance()
def auth_user_to_app(self): keys = KeyManager(self.TWITTER_KEYS) auth = tweepy.OAuthHandler(keys.CONSUMER_KEY, keys.CONSUMER_SECRET) print(auth.get_authorization_url()) verifier = input('Verifier:').strip() token = auth.get_access_token(verifier) print(token)
def list_char(): km = KeyManager(key_store_path) num = 0 if len(km.keys) == 0: print('no keys, add one with the add command') exit(3) for key in km.keys: print('{num}) {name}, API key: {apiK}, email: {email}'.format( num=num, name=key[3], apiK=key[0], email=key[4])) num += 1
def initApp(self): """ ClientCoreとの接続含めて必要な初期化処理はここで実行する """ print('SimpleBitcoin client is now activating ...: ') self.km = KeyManager() self.um = UTXOManager(self.km.my_address()) # テスト用途(本来はこんな処理しない) t1 = CoinbaseTransaction(self.km.my_address()) t2 = CoinbaseTransaction(self.km.my_address()) t3 = CoinbaseTransaction(self.km.my_address()) transactions = [] transactions.append(t1.to_dict()) transactions.append(t2.to_dict()) transactions.append(t3.to_dict()) self.um.extract_utxos(transactions) self.update_balance()
def acc_autoconf(id, server_address): """ Auto configure the arduino ACC-Client. :param id: Id of the arduino. :param server_address: Domotics server IP address. :return: Configured KeyManager. """ try: # generate the http get request for the auto configuration request = "http://" + server_address + "/acc?autoconf=request&id=" + id # execute the http get request response = urlopen(request).read() # load the http response as json data = json.loads(response) # if the json response contains the right parameters if 'key' in data and 'id' in data and 'server_address' in data: # create the key manager with the parameters return KeyManager(id=data['id'], key=data['key'], server_address=data['server_address']) except: pass # if something goes wrong, create the key manager, with the id return KeyManager(id=id)
def __init__(self, name, handler=None): NetworkPart.__init__(self) self.name = name self.messageSent = None self.messageGot = None self.responseSent = None self.responseGot = None self.keyManager = KeyManager() if handler is None: self.setCallbackHandler(BasicHandler()) else: self.setCallbackHandler(handler) self.associateCallback(Callback.KEY_USER, self.storeKeyUser) self.associateCallback(Callback.USER_MESSAGE, self.readMessage) self.associateCallback(Callback.USER_MESSAGE_STATUS, self.messageStatus) self.associateCallback(Callback.USER_RESPONSE, self.readResponse)
def do_stuff(): global iteration, notify_store km = KeyManager(key_store_path) logging.info('starting scan') s = smtplib.SMTP_SSL(credentials.smtp_server, credentials.smtp_port) s.ehlo() s.login(credentials.email_user, credentials.email_password) logging.info('connected to mail server') for key in km.keys: kit = iteration[tuple(key)] api = evelink.api.API(api_key=(key[0], key[1])) char = evelink.char.Char(char_id=key[2], api=api) res = char.notifications() rec_name = key[3] receiver = key[4] new_results = {} for r in res.result: # filter old notifications if not notify_store.contains(rec_name, res.result[r]['id']): new_results[r] = res.result[r] if len(new_results) == 0: kit += 1 if kit == 24: subject = 'No new notifications for {name}'.format( name=rec_name) text = 'No new notifications within the last 24 hours for character {name}.'.format( name=rec_name) logging.info( '24 hour check in for char {char}'.format(char=rec_name)) else: logging.info('nothing new for {char} ({tries}/24)'.format( char=rec_name, tries=kit)) iteration[tuple(key)] = kit continue else: lines = [] for r in new_results: noti = new_results[r] if noti['read'] == 1: notify_store.remove(rec_name, noti['id']) continue # was already read in client and should not come again lines.append('{time}: {type}'.format( time=datetime.utcfromtimestamp(int( noti['timestamp'])).isoformat().replace('T', ' '), type=notificationIDmap.map_id_to_text(noti['type_id']))) notify_store.add(rec_name, noti['id']) if len(lines) == 0: continue # every notification was already read, nothing new subject = '{nonn} new notification(s) for {name}'.format( name=rec_name, nonn=len(lines)) logging.info('{subj}'.format(subj=subject)) text = 'Character {name} has the following new notifications: \r\n'.format( name=rec_name) text += '\r\n'.join(lines) iteration[tuple( key )] = 0 # reset iteration counter, either 24h have passed or new notifications msg = '\r\n'.join([ 'From: {email}'.format(email='EVE Notifications'), 'To: {recv}'.format(recv=receiver), 'Subject: {sub}'.format(sub=subject), '', '{text}'.format(text=text) ]) sent = s.sendmail(credentials.email, [receiver], msg) if len(sent) == 0: logging.info( 'successfully sent mail to {recv}: {subj} - {text}'.format( recv=receiver, subj=subject, text=text.replace('\r\n', '\\r\\n'))) else: logging.warning('error with receiver {recv}: {error}'.format( recv=receiver, error=str(sent))) s.close() logging.info('scan done, mail server connection closed')
class SimpleBC_Gui(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.parent.protocol('WM_DELETE_WINDOW', self.quit) self.coin_balance = StringVar(self.parent, '0') self.status_message = StringVar(self.parent, 'Ready') self.initApp() self.setupGUI() def quit(self, event=None): """ アプリの終了 """ self.parent.destroy() def initApp(self): """ ClientCoreとの接続含めて必要な初期化処理はここで実行する """ print('SimpleBitcoin client is now activating ...: ') self.km = KeyManager() self.um = UTXOManager(self.km.my_address()) # テスト用途(本来はこんな処理しない) t1 = CoinbaseTransaction(self.km.my_address()) t2 = CoinbaseTransaction(self.km.my_address()) t3 = CoinbaseTransaction(self.km.my_address()) transactions = [] transactions.append(t1.to_dict()) transactions.append(t2.to_dict()) transactions.append(t3.to_dict()) self.um.extract_utxos(transactions) self.update_balance() def display_info(self, title, info): """ ダイアログボックスを使ったメッセージの表示 """ f = Tk() label = Label(f, text=title) label.pack() info_area = Text(f, width=70, height=50) info_area.insert(INSERT, info) info_area.pack() def update_status(self, info): """ 画面下部のステータス表示内容を変更する """ self.status_message.set(info) def update_balance(self): """ 総額表示の内容を最新状態に合わせて変更する """ bal = str(self.um.my_balance) self.coin_balance.set(bal) def create_menu(self): """ メニューバーに表示するメニューを定義する """ top = self.winfo_toplevel() self.menuBar = Menu(top) top['menu'] = self.menuBar self.subMenu = Menu(self.menuBar, tearoff=0) self.menuBar.add_cascade(label='Menu', menu=self.subMenu) self.subMenu.add_command(label='Show My Address', command=self.show_my_address) self.subMenu.add_command( label='Load my Keys', command=self.show_input_dialog_for_key_loading) self.subMenu.add_command(label='Update Blockchain', command=self.update_block_chain) self.subMenu.add_separator() self.subMenu.add_command(label='Quit', command=self.quit) self.subMenu2 = Menu(self.menuBar, tearoff=0) self.menuBar.add_cascade(label='Settings', menu=self.subMenu2) self.subMenu2.add_command(label='Renew my Keys', command=self.renew_my_keypairs) self.subMenu2.add_command(label='Connection Info', command=self.edit_conn_info) self.subMenu3 = Menu(self.menuBar, tearoff=0) self.menuBar.add_cascade(label='Advance', menu=self.subMenu3) self.subMenu3.add_command(label='Show logs', command=self.open_log_window) self.subMenu3.add_command(label='Show Blockchain', command=self.show_my_block_chain) def show_my_address(self): f = Tk() label = Label(f, text='My Address') label.pack() key_info = Text(f, width=70, height=10) my_address = self.km.my_address() key_info.insert(INSERT, my_address) key_info.pack() def show_input_dialog_for_key_loading(self): def load_my_keys(): # ファイル選択ダイアログの表示 f2 = Tk() f2.withdraw() fTyp = [("", "*.pem")] iDir = os.path.abspath(os.path.dirname(__file__)) messagebox.showinfo('Load key pair', 'please choose your key file') f_name = filedialog.askopenfilename(filetypes=fTyp, initialdir=iDir) try: file = open(f_name) data = file.read() target = binascii.unhexlify(data) # TODO: 本来は鍵ペアのファイルが不正などの異常系処理を考えるべき self.km.import_key_pair(target, p_phrase.get()) except Exception as e: print(e) finally: file.close() f.destroy() f2.destroy() self.um = UTXOManager(self.km.my_address()) self.um.my_balance = 0 self.update_balance() f = Tk() label0 = Label(f, text='Please enter pass phrase for your key pair') frame1 = ttk.Frame(f) label1 = ttk.Label(frame1, text='Pass Phrase:') p_phrase = StringVar() entry1 = ttk.Entry(frame1, textvariable=p_phrase) button1 = ttk.Button(frame1, text='Load', command=load_my_keys) label0.grid(row=0, column=0, sticky=(N, E, S, W)) frame1.grid(row=1, column=0, sticky=(N, E, S, W)) label1.grid(row=2, column=0, sticky=E) entry1.grid(row=2, column=1, sticky=W) button1.grid(row=3, column=1, sticky=W) def update_block_chain(self): pass def renew_my_keypairs(self): """ 利用する鍵ペアを更新する。 """ def save_my_pem(): self.km = KeyManager() my_pem = self.km.export_key_pair(p_phrase.get()) my_pem_hex = binascii.hexlify(my_pem).decode('ascii') # とりあえずファイル名は固定 path = 'my_key_pair.pem' f1 = open(path, 'a') f1.write(my_pem_hex) f1.close() f.destroy() self.um = UTXOManager(self.km.my_address()) self.um.my_balance = 0 self.update_balance() f = Tk() f.title('New Key Gene') label0 = Label(f, text='Please enter pass phrase for your new key pair') frame1 = ttk.Frame(f) label1 = ttk.Label(frame1, text='Pass Phrase:') p_phrase = StringVar() entry1 = ttk.Entry(frame1, textvariable=p_phrase) button1 = ttk.Button(frame1, text='Generate', command=save_my_pem) label0.grid(row=0, column=0, sticky=(N, E, S, W)) frame1.grid(row=1, column=0, sticky=(N, E, S, W)) label1.grid(row=2, column=0, sticky=E) entry1.grid(row=2, column=1, sticky=W) button1.grid(row=3, column=1, sticky=W) def edit_conn_info(self): """ Coreノードへの接続情報の編集 """ pass def open_log_window(self): """ 別ウィンドウでログ情報を表示する。デバッグ用 """ pass def show_my_block_chain(self): """ 自分が保持しているブロックチェーンの中身を確認する """ pass def setupGUI(self): """ 画面に必要なパーツを並べる """ self.parent.bind('<Control-q>', self.quit) self.parent.title("SimpleBitcoin GUI") self.pack(fill=BOTH, expand=1) self.create_menu() lf = LabelFrame(self, text='Current Balance') lf.pack(side=TOP, fill='both', expand='yes', padx=7, pady=7) lf2 = LabelFrame(self, text="") lf2.pack(side=BOTTOM, fill='both', expand='yes', padx=7, pady=7) #所持コインの総額表示領域のラベル self.balance = Label(lf, textvariable=self.coin_balance, font='Helvetica 20') self.balance.pack() #受信者となる相手の公開鍵 self.label = Label(lf2, text='Recipient Address:') self.label.grid(row=0, pady=5) self.recipient_pubkey = Entry(lf2, bd=2) self.recipient_pubkey.grid(row=0, column=1, pady=5) # 送金額 self.label2 = Label(lf2, text='Amount to pay :') self.label2.grid(row=1, pady=5) self.amountBox = Entry(lf2, bd=2) self.amountBox.grid(row=1, column=1, pady=5, sticky='NSEW') # 手数料 self.label3 = Label(lf2, text='Fee (Optional) :') self.label3.grid(row=2, pady=5) self.feeBox = Entry(lf2, bd=2) self.feeBox.grid(row=2, column=1, pady=5, sticky='NSEW') # 間隔の開け方がよくわからんので空文字で場所確保 self.label4 = Label(lf2, text='') self.label4.grid(row=3, pady=5) # 送金実行ボタン self.sendBtn = Button(lf2, text='\nSend Coin(s)\n', command=self.sendCoins) self.sendBtn.grid(row=4, column=1, sticky='NSEW') # 下部に表示するステータスバー stbar = Label(self.winfo_toplevel(), textvariable=self.status_message, bd=1, relief=SUNKEN, anchor=W) stbar.pack(side=BOTTOM, fill=X) # 送金実行ボタン押下時の処理実体 def sendCoins(self): sendAtp = self.amountBox.get() recipientKey = self.recipient_pubkey.get() sendFee = self.feeBox.get() if not sendAtp: messagebox.showwarning('Warning', 'Please enter the Amount to pay.') elif len(recipientKey) <= 1: messagebox.showwarning('Warning', 'Please enter the Recipient Address.') elif not sendFee: sendFee = 0 else: result = messagebox.askyesno( 'Confirmation', 'Sending {} SimpleBitcoins to :\n {}'.format( sendAtp, recipientKey)) if result: if 0 < len(self.um.utxo_txs): print('Sending {} SimpleBitcoins to reciever:\n {}'.format( sendAtp, recipientKey)) else: messagebox.showwarning('Short of Coin.', 'Not enough coin to be sent...') return utxo, idx = self.um.get_utxo_tx(0) t = Transaction([TransactionInput(utxo, idx)], [TransactionOutput(recipientKey, sendAtp)]) counter = 1 # TransactionInputが送信額を超えるまで繰り返して取得しTransactionとして完成させる while t.is_enough_inputs(sendFee) is not True: new_utxo, new_idx = self.um.get_utxo_tx(counter) t.inputs.append(TransactionInput(new_utxo, new_idx)) counter += 1 if counter > len(self.um.utxo_txs): messagebox.showwarning('Short of Coin.', 'Not enough coin to be sent...') break # 正常なTransactionが生成できた時だけ秘密鍵で署名を実行する if t.is_enough_inputs(sendFee) is True: # まずお釣り用Transactionを作る change = t.compute_change(sendFee) t.outputs.append( TransactionOutput(self.km.my_address(), change)) to_be_signed = json.dumps(t.to_dict(), sort_keys=True) signed = self.km.compute_digital_signature(to_be_signed) new_tx = json.loads(to_be_signed) new_tx['signature'] = signed # TODO: 本来はここで出来上がったTransactionを送信する処理を入れる print('signed new_tx:', json.dumps(new_tx)) # 実験的にお釣り分の勘定のため新しく生成したTransactionをUTXOとして追加しておくが # 本来はブロックチェーンの更新に合わせて再計算した方が適切 self.um.put_utxo_tx(t.to_dict()) to_be_deleted = 0 del_list = [] while to_be_deleted < counter: del_tx = self.um.get_utxo_tx(to_be_deleted) del_list.append(del_tx) to_be_deleted += 1 for dx in del_list: self.um.remove_utxo_tx(dx) self.amountBox.delete(0, END) self.feeBox.delete(0, END) self.recipient_pubkey.delete(0, END) self.update_balance()
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ # Test for pin thread # - # @author giuliobosco # @version 1.0 (2019-04-21 - 2019-04-21) import sys sys.path.insert(0, '/usr/lib/python2.7/bridge') from pin_thread import PinThread from key_manager import KeyManager from bridgeclient import BridgeClient from time import sleep bridge = BridgeClient() key_manager = KeyManager('000000000000', '000000001234', '10.8.16.111:8080') pin_thread = PinThread(key_manager=key_manager, pin='D6', bridge=bridge) pin_thread.start() sleep(10) pin_thread.interrupt()
#print "instance_id: %s" % instance_id continue else: minion_mgr = MinionManager(region) minion_mgr.create_or_update_minion(instanceid=instance_id, modified=None, highstate_runner=None, highstate_ran=None, status=unicode(status)) sqs_minion.delete_a_message(message) print "removed sqs message about minion" except Exception, e: print "Error handling minion instances: %s" % e raise # Remove terminated minions keys from our salt master try: minion_mgr = MinionManager(region) minions_terminated_list = minion_mgr.get_terminated() k = KeyManager() k.delete_keys(minions_terminated_list) except Exception, e: raise time.sleep(POLL_CYCLE) if __name__ == "__main__": try: main() except Exception, e: print "Problem occurred. %s" % e
format='%(asctime)s - %(name)s - %(levelname)s: %(message)s', filename=args.log, filemode='w', level=logging.INFO) if args.action == 'add': add_char() elif args.action == 'list': list_char() elif args.action == 'remove': rm_char() elif args.action == 'start': km = KeyManager(key_store_path) if len(km.keys) == 0: print('no keys, add one with the add command') exit(3) for k in KeyManager(key_store_path).keys: iteration[tuple(k)] = 0 # init 24 hour counter for every key notify_store = StorageDictList(notify_store_path) scheduler = BlockingScheduler(timezone=utc) scheduler.add_job(do_stuff, 'interval', hours=1) try: print('starting scheduler...') scheduler.start() except (KeyboardInterrupt, SystemExit): scheduler.shutdown(wait=False) print('scheduler stopped')
import common.tms_logger as logger from common.tms_yaml import py2yaml, yaml2py import storage.tms_storage as storage from data_tree.tms_data_tree import DataTree from key_manager import KeyManager # aesgcm = aes.init("GCM", b"AES256Key-32Characters1234567890") # cipher_data, nonce = aesgcm.encrypt(b"Hello World") # logger.info("Result = " + str(aesgcm.decrypt(cipher_data, nonce))) key = b"AES256Key-32Characters1234567890" s = storage.init("./kms.db", "crypto", key) #s.save(b"123456789") #data = s.load() #logger.info("read data = " + str(data)) km = KeyManager(s) #km.add_key('/', 'a1', b'this is my key') print(km.get_key('/a1'))
def print_keys(req_pub_key, req_priv_key, prov_pub_key, prov_priv_key, conc_pub_key): print('REQUESTOR_PRIVATE_KEY = ', req_priv_key) print('REQUESTOR_PUBLIC_KEY = ', req_pub_key) print('') print('PROVIDER_PRIVATE_KEY = ', prov_priv_key) print('PROVIDER_PUBLIC_KEY = ', prov_pub_key) print('') print('CONCENT_PUBLIC_KEY = ', conc_pub_key) if __name__ == '__main__': args = parse_arguments() cluster_url = "{}/api/v1/{}/".format(args.cluster_url, args.endpoint) key_manager = KeyManager() requestor_public_key, requestor_private_key = key_manager.get_requestor_keys() provider_public_key, provider_private_key = key_manager.get_provider_keys() concent_public_key = key_manager.get_concent_public_key() if args.print_keys: print_keys( requestor_public_key, requestor_private_key, provider_public_key, provider_private_key, concent_public_key, ) message_handler = MessageHandler( requestor_private_key,
def __init__(self, b): NetworkPart.__init__(self) self.sharedKey = None self.b = b self.r = CyclicGroupDualArray(self.b) s = CyclicGroupDualArray(self.b) s1 = CyclicGroupDualArray(self.b) self.S = {'FOR': s, 'RET': s1} perm = range(0, b) shuffle(perm) permInverse = inversePermute(perm) self.permutation = {'FOR': perm, 'RET': permInverse} self.e = CyclicGroup.randomPair() self.mixMessageComponents = {'FOR': None, 'RET': None} self.preMixCallback = { 'FOR': Callback.PRE_FOR_MIX, 'RET': Callback.PRE_RET_MIX } self.realMixCallback = { 'FOR': Callback.REAL_FOR_MIX, 'RET': Callback.REAL_RET_MIX } self.mixCommitCallback = { 'FOR': Callback.REAL_FOR_MIX_COMMIT, 'RET': Callback.REAL_RET_MIX_COMMIT } self.prePostProcessCallback = { 'FOR': Callback.PRE_FOR_POSTPROCESS, 'RET': Callback.PRE_RET_POSTPROCESS } self.realPostProcessCallback = { 'FOR': Callback.REAL_FOR_POSTPROCESS, 'RET': Callback.REAL_RET_POSTPROCESS } self.decryptionShare = {'FOR': None, 'RET': None} self.realMixCommitment = {'FOR': None, 'RET': None} self.senders = None self.keyManager = KeyManager() self.associateCallback(Callback.KEY_SHARE, self.storeSharedKey, 1) self.associateCallback(Callback.PRE_FOR_MIX, self.preForwardMix, 1) self.associateCallback(Callback.PRE_FOR_POSTPROCESS, self.preForwardPostProcess, 1) self.associateCallback(Callback.PRE_RET_MIX, self.preReturnMix, 1) self.associateCallback(Callback.PRE_RET_POSTPROCESS, self.preReturnPostProcess, 1) self.associateCallback(Callback.KEY_USER, self.sendUserKey) self.associateCallback(Callback.REAL_FOR_PREPROCESS, self.realForPreProcess) self.associateCallback(Callback.REAL_FOR_MIX, self.realForMix) self.associateCallback(Callback.REAL_FOR_MIX_COMMIT, self.realForMixCommit) self.associateCallback(Callback.REAL_RET_MIX, self.realRetMix) self.associateCallback(Callback.REAL_RET_MIX_COMMIT, self.realRetMixCommit)
def main(): k_m = KeyManager() um = UTXOManager(k_m.my_address()) i_k_m = KeyManager() u_k_m = KeyManager() t1 = CoinbaseTransaction(k_m.my_address()) t2 = CoinbaseTransaction(k_m.my_address()) t3 = CoinbaseTransaction(k_m.my_address()) t4 = Transaction([TransactionInput(t1.to_dict(), 0)], [ TransactionOutput(u_k_m.my_address(), 10.0), TransactionOutput(i_k_m.my_address(), 20.0) ]) transactions = [] transactions.append(t1.to_dict()) transactions.append(t2.to_dict()) transactions.append(t3.to_dict()) transactions.append(t4.to_dict()) um.extract_utxos(transactions) balance = um.my_balance print(balance)
def create_auth(self): keys = KeyManager(self.TWITTER_KEYS) auth = tweepy.OAuthHandler(keys.CONSUMER_KEY, keys.CONSUMER_SECRET) auth.set_access_token(keys.ACCESS_KEY, keys.ACCESS_SECRET) return auth
class MixNode(NetworkPart): """ The class mainly consists of: - the key manager, whose keys are used to blind and un-blind messages/responses - 3 cyclic group dual arrays (array + inverse) used to blind and un-blind messages - the permutation array (self.perm) and its inverse (self.permInverse) - the tuple (key share in cyclic group, exponent of key share): self.e - the message components that the last node stores (forward and return): self.mixMessageComponents - the decryption shares that every node computes (forward and return): self.decryptionShare - the commitments (forward and return) of the last node stored by the other nodes: self.realMixCommitment """ def __init__(self, b): NetworkPart.__init__(self) self.sharedKey = None self.b = b self.r = CyclicGroupDualArray(self.b) s = CyclicGroupDualArray(self.b) s1 = CyclicGroupDualArray(self.b) self.S = {'FOR': s, 'RET': s1} perm = range(0, b) shuffle(perm) permInverse = inversePermute(perm) self.permutation = {'FOR': perm, 'RET': permInverse} self.e = CyclicGroup.randomPair() self.mixMessageComponents = {'FOR': None, 'RET': None} self.preMixCallback = { 'FOR': Callback.PRE_FOR_MIX, 'RET': Callback.PRE_RET_MIX } self.realMixCallback = { 'FOR': Callback.REAL_FOR_MIX, 'RET': Callback.REAL_RET_MIX } self.mixCommitCallback = { 'FOR': Callback.REAL_FOR_MIX_COMMIT, 'RET': Callback.REAL_RET_MIX_COMMIT } self.prePostProcessCallback = { 'FOR': Callback.PRE_FOR_POSTPROCESS, 'RET': Callback.PRE_RET_POSTPROCESS } self.realPostProcessCallback = { 'FOR': Callback.REAL_FOR_POSTPROCESS, 'RET': Callback.REAL_RET_POSTPROCESS } self.decryptionShare = {'FOR': None, 'RET': None} self.realMixCommitment = {'FOR': None, 'RET': None} self.senders = None self.keyManager = KeyManager() self.associateCallback(Callback.KEY_SHARE, self.storeSharedKey, 1) self.associateCallback(Callback.PRE_FOR_MIX, self.preForwardMix, 1) self.associateCallback(Callback.PRE_FOR_POSTPROCESS, self.preForwardPostProcess, 1) self.associateCallback(Callback.PRE_RET_MIX, self.preReturnMix, 1) self.associateCallback(Callback.PRE_RET_POSTPROCESS, self.preReturnPostProcess, 1) self.associateCallback(Callback.KEY_USER, self.sendUserKey) self.associateCallback(Callback.REAL_FOR_PREPROCESS, self.realForPreProcess) self.associateCallback(Callback.REAL_FOR_MIX, self.realForMix) self.associateCallback(Callback.REAL_FOR_MIX_COMMIT, self.realForMixCommit) self.associateCallback(Callback.REAL_RET_MIX, self.realRetMix) self.associateCallback(Callback.REAL_RET_MIX_COMMIT, self.realRetMixCommit) # called in network.init() before the precomputation phase, when the public key is collectively constructed def computeSecretShare(self): self.network.sendToNH(Message(Callback.KEY_SHARE, self.e[1])) # store the above shared key (that the NH broadcasts) def storeSharedKey(self, message): self.sharedKey = message.payload return Status.OK # callback that performs dummy key exchange with a user def sendUserKey(self, message): userId = message.payload self.keyManager.addSeeds(userId) payload = [ self.id, self.keyManager.getSeed(userId, KeyManager.MESSAGE), self.keyManager.getSeed(userId, KeyManager.RESPONSE) ] self.network.sendToUser(userId, Message(Callback.KEY_USER, payload)) return Status.OK # called in network.init(), initiates the precomputation process def precompute(self): self.network.sendToNH( Message(Callback.PRE_FOR_PREPROCESS, self.r.inverse.encrypt(self.sharedKey).vector)) # callback that performs the mixing process in the the forward path of precomputation phase def preForwardMix(self, message): status = self.__preMix(message=ElGamalVector(vector=message.payload), path='FOR') # the last node initiates the matching return path if self.__finalNode('FOR'): self.network.sendToPreviousNode( self.id, Message(Callback.PRE_RET_MIX, self.S['RET'].inverse.encrypt(self.sharedKey).vector)) return status # callback that computes the decryption share of the forward path def preForwardPostProcess(self, message): return self.__prePostProcess( randomComponents=CyclicGroupVector(vector=message.payload), path='FOR') # callback that performs mixing process in the the return path of precomputation phase def preReturnMix(self, message): return self.__preMix(message=ElGamalVector(vector=message.payload), path='RET') # callback that computes the decryption share of the return path def preReturnPostProcess(self, message): return self.__prePostProcess( randomComponents=CyclicGroupVector(vector=message.payload), path='RET') # callback that computes the value that gradually replaces "keys" with "r" values in blind "messages" def realForPreProcess(self, message): self.senders = message.payload cyclicVector = self.keyManager.getNextKeys(ids=self.senders, type=KeyManager.MESSAGE, inverse=False) product = CyclicGroupVector.multiply(cyclicVector, self.r.array) self.network.sendToNH( Message(Callback.REAL_FOR_PREPROCESS, product.vector)) return Status.OK # callback that performs the mixing process in the the forward path of real-time phase def realForMix(self, message): return self.__realMix(message=Vector( vector=[CyclicGroupVector(vector=v) for v in message.payload]), path='FOR') # callback that performs the mixing process in the the return path of real-time phase def realRetMix(self, message): def tempProcess(temp): return self.__returnPathKeyBlinding(temp) return self.__realMix(message=Vector( vector=[CyclicGroupVector(vector=v) for v in message.payload]), path='RET', tempProcess=tempProcess) # callback that stores the commitment of the last node regarding # the mixing process in the the forward path of real-time phase def realForMixCommit(self, message): def resultProcess(decrShare): return decrShare return self.__realMixCommit(message=Vector( vector=[CyclicGroupVector(vector=v) for v in message.payload]), path='FOR', resultProcess=resultProcess) # callback that stores the commitment of the last node regarding # the mixing process in the the return path of real-time phase def realRetMixCommit(self, message): def resultProcess(decrShare): return self.__returnPathKeyBlinding(decrShare) return self.__realMixCommit(message=Vector( vector=[CyclicGroupVector(vector=v) for v in message.payload]), path='RET', resultProcess=resultProcess) # performs the mixing process of the precomputation phase def __preMix(self, message, path): result = ElGamalVector.multiply( message.permute(self.permutation[path]), self.S[path].inverse.encrypt(self.sharedKey)) if not self.__finalNode(path): self.__toNextNode( path, Message(self.preMixCallback[path], result.vector)) else: self.mixMessageComponents[path] = result.messageComponents() message = Message(self.prePostProcessCallback[path], result.randomComponents().vector) self.network.broadcastToNodes(self.id, message) self.receive(message.toJSON()) return Status.OK # performs the mixing process of the real-time phase def __realMix(self, message, path, tempProcess=None): temp = message.permute(self.permutation[path]) result = Vector([ CyclicGroupVector.scalarMultiply(temp.at(i), self.S[path].array.at(i)) for i in range(0, self.b) ]) if not self.__finalNode(path): self.__toNextNode( path, Message(self.realMixCallback[path], [v.vector for v in result.vector])) else: self.network.broadcastToNodes( self.id, Message(self.mixCommitCallback[path], [v.vector for v in result.vector])) temp = CyclicGroupVector.multiply(self.decryptionShare[path], self.mixMessageComponents[path]) if tempProcess is not None: temp = tempProcess(temp) result = Vector([ CyclicGroupVector.scalarMultiply(result.at(i), temp.at(i)) for i in range(0, self.b) ]) self.network.sendToNH( Message(self.realPostProcessCallback[path], [True, [v.vector for v in result.vector]])) return Status.OK # computes the decryption share def __prePostProcess(self, randomComponents, path): self.decryptionShare[path] = randomComponents.exp(self.e[0]).inverse() return Status.OK # the blinding proceess that the mix node performs in the return path (that involves user keys) def __returnPathKeyBlinding(self, temp): return CyclicGroupVector.multiply( temp, self.keyManager.getNextKeys(ids=self.senders, type=KeyManager.RESPONSE, inverse=False)) # stores the mixing commitment def __realMixCommit(self, message, path, resultProcess): self.realMixCommitment[path] = message result = resultProcess(self.decryptionShare[path]) self.network.sendToNH( Message(self.realPostProcessCallback[path], [False, result.vector])) return Status.OK def __toNextNode(self, path, message): if path == 'FOR': return self.network.sendToNextNode(self.id, message) elif path == 'RET': return self.network.sendToPreviousNode(self.id, message) else: raise Exception("Wrong path!") def __finalNode(self, path): if path == 'FOR': return self.network.isLastNode(self.id) elif path == 'RET': return self.network.isFirstNode(self.id) else: raise Exception("Wrong path!")
class User(NetworkPart): """ The class consists of: - the key manager, whose keys are used to blind and un-blind messages/responses - the response handler, that reads a message and produces a response - the LAST message and response the user sent and received (or received and sent) """ def __init__(self, name, handler=None): NetworkPart.__init__(self) self.name = name self.messageSent = None self.messageGot = None self.responseSent = None self.responseGot = None self.keyManager = KeyManager() if handler is None: self.setCallbackHandler(BasicHandler()) else: self.setCallbackHandler(handler) self.associateCallback(Callback.KEY_USER, self.storeKeyUser) self.associateCallback(Callback.USER_MESSAGE, self.readMessage) self.associateCallback(Callback.USER_MESSAGE_STATUS, self.messageStatus) self.associateCallback(Callback.USER_RESPONSE, self.readResponse) # the key establishment takes place here def setUp(self): self.network.broadcastToNodes(self.id, Message(Callback.KEY_USER, self.id)) def setCallbackHandler(self, callbackHandler): self.callbackHandler = callbackHandler # store the keys that a node sent def storeKeyUser(self, message): nodeId = message.payload[0] messageKey = message.payload[1] responseKey = message.payload[2] self.keyManager.addSeeds(nodeId, (messageKey, responseKey)) self.callbackHandler.setUp(self) return Status.OK # send a message to a user through the mixnet def sendMessage(self, userId, messageId, messageVector): # store the message for future reference self.messageSent = messageVector.copyVector() # append the userId (the receiver) # the NH will read this id (after the message is un-blinded) and route the message accordingly messageVector.append(userId) # blind the message with the combined key and send it to the NH combinedKey = self.keyManager.getCombinedKey(type=KeyManager.MESSAGE, inverse=True) blindMessage = CyclicGroupVector.scalarMultiply( messageVector, combinedKey) self.network.sendToNH( Message(Callback.USER_MESSAGE, [self.id, messageId, blindMessage.vector])) # read a message from the mixnet and send a response def readMessage(self, message): index = message.payload[0] # the payload is the message (mapped to cyclic group members) messageVector = CyclicGroupVector(vector=message.payload[1]) # compute a response and send it to the mixnet responseVector = self.callbackHandler.messageHandler( self, messageVector) # store message and response for future reference self.messageGot = messageVector.copyVector() self.responseSent = responseVector.copyVector() self.network.sendToNH( Message(Callback.USER_RESPONSE, [index, responseVector.vector])) return Status.OK # read a response (after I sent a message) def readResponse(self, message): # un-blind the response and store it for future reference responseVector = CyclicGroupVector.scalarMultiply( CyclicGroupVector(vector=message.payload), self.keyManager.getCombinedKey(type=KeyManager.RESPONSE, inverse=True)) self.callbackHandler.responseHandler(self, responseVector) self.responseGot = responseVector.copyVector() return Status.OK def messageStatus(self, message): messageId = message.payload[0] status = message.payload[1] self.callbackHandler.messageStatusHandler(self, messageId, status) return Status.OK