def sendEncrypt(self): ''' Create a private message and send it ''' invalidID = True while invalidID: try: peer = logger.readline('Peer to send to: ') except KeyboardInterrupt: break else: if self.onionrUtils.validatePubKey(peer): invalidID = False else: logger.error('Invalid peer ID') else: try: message = logger.readline("Enter a message: ") except KeyboardInterrupt: pass else: logger.info("Sending message to: " + logger.colors.underline + peer) self.onionrUtils.sendPM(peer, message)
def start(self): logger.warn("Please note: everything said here is public, even if a random channel name is used.", terminal=True) message = "" self.flowRunning = True try: self.channel = logger.readline("Enter a channel name or none for default:").strip() except (KeyboardInterrupt, EOFError) as e: self.flowRunning = False newThread = threading.Thread(target=self.showOutput, daemon=True) newThread.start() while self.flowRunning: if self.channel == "": self.channel = "global" try: message = logger.readline('\nInsert message into flow:').strip().replace('\n', '\\n').replace('\r', '\\r') except EOFError: pass except KeyboardInterrupt: self.flowRunning = False else: if message == "q": self.flowRunning = False expireTime = epoch.get_epoch() + 43200 if len(message) > 0: logger.info('Inserting message as block...', terminal=True) onionrblocks.insert(message, header='brd', expire=expireTime, meta={'ch': self.channel}) logger.info("Flow is exiting, goodbye", terminal=True) return
def start(self): logger.warn( "Please note: everything said here is public, even if a random channel name is used." ) message = "" self.flowRunning = True newThread = threading.Thread(target=self.showOutput) newThread.start() try: self.channel = logger.readline( "Enter a channel name or none for default:") except (KeyboardInterrupt, EOFError) as e: self.flowRunning = False while self.flowRunning: try: message = logger.readline( '\nInsert message into flow:').strip().replace( '\n', '\\n').replace('\r', '\\r') except EOFError: pass except KeyboardInterrupt: self.flowRunning = False else: if message == "q": self.flowRunning = False expireTime = self.myCore._utils.getEpoch() + 43200 if len(message) > 0: self.myCore.insertBlock(message, header='txt', expire=expireTime, meta={'ch': self.channel}) logger.info("Flow is exiting, goodbye") return
def draft_message(self, recip=''): message = '' newLine = '' subject = '' entering = False if len(recip) == 0: entering = True while entering: try: recip = logger.readline( 'Enter peer address, or -q to stop:').strip() if recip in ('-q', 'q'): raise EOFError if not self.myCore._utils.validatePubKey(recip): raise onionrexceptions.InvalidPubkey( 'Must be a valid ed25519 base32 encoded public key' ) except onionrexceptions.InvalidPubkey: logger.warn('Invalid public key') except (KeyboardInterrupt, EOFError): entering = False else: break else: # if -q or ctrl-c/d, exit function here, otherwise we successfully got the public key return try: subject = logger.readline('Message subject: ') except (KeyboardInterrupt, EOFError): pass cancelEnter = False logger.info( 'Enter your message, stop by entering -q on a new line. -c to cancel' ) while newLine != '-q': try: newLine = input() except (KeyboardInterrupt, EOFError): cancelEnter = True if newLine == '-c': cancelEnter = True break if newLine == '-q': continue newLine += '\n' message += newLine if not cancelEnter: logger.info('Inserting encrypted message as Onionr block....') blockID = self.myCore.insertBlock(message, header='pm', encryptType='asym', asymPeer=recip, sign=self.doSigs, meta={'subject': subject})
def ban_block(): """Deletes a block, permanently blacklisting it""" blacklist = onionrblacklist.OnionrBlackList() try: ban = sys.argv[2] except IndexError: # Get the hash if its not provided as a CLI argument ban = logger.readline('Enter a block hash:').strip() # Make sure the hash has no truncated zeroes ban = reconstructhash.reconstruct_hash(ban) if stringvalidators.validate_hash(ban): if not blacklist.inBlacklist(ban): try: blacklist.addToDB(ban) removeblock.remove_block(ban) deleteBlock(ban) except Exception as error: logger.error('Could not blacklist block', error=error, terminal=True) else: logger.info('Block blacklisted', terminal=True) else: logger.warn('That block is already blacklisted', terminal=True) else: logger.error('Invalid block hash', terminal=True)
def getPassword(self, message='Enter password: '******''' Get a password without showing the users typing and confirm the input ''' # Get a password safely with confirmation and return it while True: print(message) pass1 = getpass.getpass() if confirm: print('Confirm password: ') pass2 = getpass.getpass() if pass1 != pass2: logger.error("Passwords do not match.") logger.readline() else: break else: break return pass1
def sendEncrypt(self): ''' Create a private message and send it ''' while True: try: peer = logger.readline('Peer to send to: ') except KeyboardInterrupt: break else: if self.onionrUtils.validateID(peer): break else: logger.error('Invalid peer ID') else: try: message = logger.readline("Enter a message: ") except KeyboardInterrupt: pass else: logger.info("Sending message to " + peer) self.onionrUtils.sendPM(peer, message)
def addMessage(self): ''' Broadcasts a message to the Onionr network ''' while True: messageToAdd = '-txt-' + logger.readline( 'Broadcast message to network: ') if len(messageToAdd) >= 1: break addedHash = self.onionrCore.setData(messageToAdd) self.onionrCore.addToBlockDB(addedHash, selfInsert=True) self.onionrCore.setBlockType(addedHash, 'txt') return
def ban_block(o_inst): try: ban = sys.argv[2] except IndexError: ban = logger.readline('Enter a block hash:') if o_inst.onionrUtils.validateHash(ban): if not o_inst.onionrCore._blacklist.inBlacklist(ban): try: o_inst.onionrCore._blacklist.addToDB(ban) o_inst.onionrCore.removeBlock(ban) except Exception as error: logger.error('Could not blacklist block', error=error) else: logger.info('Block blacklisted') else: logger.warn('That block is already blacklisted') else: logger.error('Invalid block hash')
def addMessage(self, header="txt"): ''' Broadcasts a message to the Onionr network ''' while True: try: messageToAdd = logger.readline( 'Broadcast message to network: ') if len(messageToAdd) >= 1: break except KeyboardInterrupt: return #addedHash = self.onionrCore.setData(messageToAdd) addedHash = self.onionrCore.insertBlock(messageToAdd, header='txt') #self.onionrCore.addToBlockDB(addedHash, selfInsert=True) #self.onionrCore.setBlockType(addedHash, 'txt') if addedHash != '': logger.info("Message inserted as as block %s" % addedHash) return
def menu(self): choice = '' while True: sigMsg = 'Message Signing: %s' logger.info(self.strings.programTag + '\n\nUser ID: ' + self.myCore._crypto.pubKey) if self.doSigs: sigMsg = sigMsg % ('enabled', ) else: sigMsg = sigMsg % ( 'disabled (Your messages cannot be trusted)', ) if self.doSigs: logger.info(sigMsg) else: logger.warn(sigMsg) logger.info(self.strings.mainMenu.title()) # print out main menu try: choice = logger.readline( 'Enter 1-%s:\n' % (len(self.strings.mainMenuChoices))).lower().strip() except (KeyboardInterrupt, EOFError): choice = '5' if choice in (self.strings.mainMenuChoices[0], '1'): self.inbox() elif choice in (self.strings.mainMenuChoices[1], '2'): self.sentbox() elif choice in (self.strings.mainMenuChoices[2], '3'): self.draft_message() elif choice in (self.strings.mainMenuChoices[3], '4'): self.toggle_signing() elif choice in (self.strings.mainMenuChoices[4], '5'): logger.info('Goodbye.') break elif choice == '': pass else: logger.warn('Invalid choice.') return
def commandInstallPlugin(): if len(sys.argv) >= 3: check() pluginname = sys.argv[2] pkobh = None # public key or block hash version = None if ':' in pluginname: details = pluginname pluginname = sanitize(details[0]) version = details[1] sanitize(pluginname) if len(sys.argv) >= 4: # public key or block hash specified pkobh = sys.argv[3] else: # none specified, check if in config file pkobh = getKey(pluginname) if pkobh is None: # still nothing found, try searching repositories logger.info('Searching for public key in repositories...') try: repos = getRepositories() distributors = list() for repo, records in repos.items(): if pluginname in records: logger.debug( 'Found %s in repository %s for plugin %s.' % (records[pluginname], repo, pluginname)) distributors.append(records[pluginname]) if len(distributors) != 0: distributor = None if len(distributors) == 1: logger.info('Found distributor: %s' % distributors[0]) distributor = distributors[0] else: distributors_message = '' index = 1 for dist in distributors: distributors_message += ' ' + logger.colors.bold + str( index) + ') ' + logger.colors.reset + str( dist) + '\n' index += 1 logger.info( (logger.colors.bold + 'Found distributors (%s):' + logger.colors.reset + '\n' + distributors_message) % len(distributors)) valid = False while not valid: choice = logger.readline( 'Select the number of the key to use, from 1 to %s, or press Ctrl+C to cancel:' % (index - 1)) try: if int(choice) < index and int(choice) >= 1: distributor = distributors[int(choice)] valid = True except KeyboardInterrupt: logger.info('Installation cancelled.') return True except: pass if not distributor is None: pkobh = distributor except Exception as e: logger.warn('Failed to lookup plugin in repositories.', timestamp=False) logger.error('asdf', error=e, timestamp=False) if pkobh is None: logger.error( 'No key for this plugin found in keystore or repositories, please specify.' ) help() return True valid_hash = pluginapi.get_utils().validateHash(pkobh) real_block = False valid_key = pluginapi.get_utils().validatePubKey(pkobh) real_key = False if valid_hash: real_block = Block.exists(pkobh) elif valid_key: real_key = pluginapi.get_utils().hasKey(pkobh) blockhash = None if valid_hash and not real_block: logger.error( 'Block hash not found. Perhaps it has not been synced yet?') logger.debug( 'Is valid hash, but does not belong to a known block.') return True elif valid_hash and real_block: blockhash = str(pkobh) logger.debug('Using block %s...' % blockhash) installBlock(blockhash) elif valid_key and not real_key: logger.error( 'Public key not found. Try adding the node by address manually, if possible.' ) logger.debug('Is valid key, but the key is not a known one.') elif valid_key and real_key: publickey = str(pkobh) logger.debug('Using public key %s...' % publickey) saveKey(pluginname, pkobh) signedBlocks = Block.getBlocks(type='plugin', signed=True, signer=publickey) mostRecentTimestamp = None mostRecentVersionBlock = None for block in signedBlocks: try: blockContent = json.loads(block.getContent()) if not (('author' in blockContent) and ('info' in blockContent) and ('date' in blockContent) and ('name' in blockContent)): raise ValueError( 'Missing required parameter `date` in block %s.' % block.getHash()) blockDatetime = datetime.datetime.strptime( blockContent['date'], '%Y-%m-%d %H:%M:%S') if blockContent['name'] == pluginname: if ('version' in blockContent['info']) and ( blockContent['info']['version'] == version) and (not version is None): mostRecentTimestamp = blockDatetime mostRecentVersionBlock = block.getHash() break elif mostRecentTimestamp is None: mostRecentTimestamp = blockDatetime mostRecentVersionBlock = block.getHash() elif blockDatetime > mostRecentTimestamp: mostRecentTimestamp = blockDatetime mostRecentVersionBlock = block.getHash() except Exception as e: pass logger.warn( 'Only continue the installation is you are absolutely certain that you trust the plugin distributor. Public key of plugin distributor: %s' % publickey, timestamp=False) installBlock(mostRecentVersionBlock) else: logger.error( 'Unknown data "%s"; must be public key or block hash.' % str(pkobh)) return else: logger.info(sys.argv[0] + ' ' + sys.argv[1] + ' <plugin> [public key/block hash]') return True
def inbox(self): blockCount = 0 pmBlockMap = {} pmBlocks = {} logger.info('Decrypting messages...') choice = '' displayList = [] subject = '' # this could use a lot of memory if someone has received a lot of messages for blockHash in self.myCore.getBlocksByType('pm'): pmBlocks[blockHash] = Block(blockHash, core=self.myCore) pmBlocks[blockHash].decrypt() blockCount = 0 for blockHash in pmBlocks: if not pmBlocks[blockHash].decrypted: continue blockCount += 1 pmBlockMap[blockCount] = blockHash block = pmBlocks[blockHash] senderKey = block.signer try: senderKey = senderKey.decode() except AttributeError: pass senderDisplay = onionrusers.OnionrUser(self.myCore, senderKey).getName() if senderDisplay == 'anonymous': senderDisplay = senderKey blockDate = pmBlocks[blockHash].getDate().strftime("%m/%d %H:%M") try: subject = pmBlocks[blockHash].bmetadata['subject'] except KeyError: subject = '' displayList.append('%s. %s - %s - <%s>: %s' % (blockCount, blockDate, senderDisplay[:12], subject[:10], blockHash)) while choice not in ('-q', 'q', 'quit'): for i in displayList: logger.info(i) try: choice = logger.readline( 'Enter a block number, -r to refresh, or -q to stop: ' ).strip().lower() except (EOFError, KeyboardInterrupt): choice = '-q' if choice in ('-q', 'q', 'quit'): continue if choice in ('-r', 'r', 'refresh'): # dirty hack self.inbox() return try: choice = int(choice) except ValueError: pass else: try: pmBlockMap[choice] readBlock = pmBlocks[pmBlockMap[choice]] except KeyError: pass else: cancel = '' readBlock.verifySig() senderDisplay = self.myCore._utils.bytesToStr( readBlock.signer) if len(senderDisplay.strip()) == 0: senderDisplay = 'Anonymous' logger.info('Message received from %s' % (senderDisplay, )) logger.info('Valid signature: %s' % readBlock.validSig) if not readBlock.validSig: logger.warn( 'This message has an INVALID/NO signature. ANYONE could have sent this message.' ) cancel = logger.readline( 'Press enter to continue to message, or -q to not open the message (recommended).' ) print('') if cancel != '-q': try: print( draw_border( self.myCore._utils.escapeAnsi( readBlock.bcontent.decode().strip()))) except ValueError: logger.warn( 'Error presenting message. This is usually due to a malformed or blank message.' ) pass if readBlock.validSig: reply = logger.readline( "Press enter to continue, or enter %s to reply" % ("-r", )) print('') if reply == "-r": self.draft_message( self.myCore._utils.bytesToStr( readBlock.signer, )) else: logger.readline("Press enter to continue") print('') return