def site_file(name: str, file: str)->Response: """Accept a site 'name', if pubkey then show multi-page site, if hash show single page site""" resp: str = 'Not Found' mime_type = mimetypes.MimeTypes().guess_type(file)[0] # If necessary convert the name to base32 from mnemonic if mnemonickeys.DELIMITER in name: name = mnemonickeys.get_base32(name) # Now make sure the key is regardless a valid base32 format ed25519 key (readding padding if necessary) if stringvalidators.validate_pub_key(name): name = unpaddedbase32.repad(name) resp = sitefiles.get_file(name, file) elif stringvalidators.validate_hash(name): try: resp = onionrblockapi.Block(name).bcontent except onionrexceptions.NoDataAvailable: abort(404) except TypeError: pass try: resp = base64.b64decode(resp) except binascii.Error: pass if resp == 'Not Found' or not resp: abort(404) return Response(resp, mimetype=mime_type)
def addForwardKey(self, newKey, expire=DEFAULT_KEY_EXPIRE): newKey = bytesconverter.bytes_to_str( unpaddedbase32.repad(bytesconverter.str_to_bytes(newKey))) if not stringvalidators.validate_pub_key(newKey): # Do not add if something went wrong with the key raise onionrexceptions.InvalidPubkey(newKey) conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=DATABASE_LOCK_TIMEOUT) c = conn.cursor() # Get the time we're inserting the key at timeInsert = epoch.get_epoch() # Look at our current keys for duplicate key data or time for entry in self._getForwardKeys(): if entry[0] == newKey: return False if entry[1] == timeInsert: timeInsert += 1 # Sleep if our time is the same to prevent dupe time records time.sleep(1) # Add a forward secrecy key for the peer # Prepare the insert command = (self.publicKey, newKey, timeInsert, timeInsert + expire) c.execute("INSERT INTO forwardKeys VALUES(?, ?, ?, ?);", command) conn.commit() conn.close() return True
def get_motd()->Response: motds = blockmetadb.get_blocks_by_type("motd") newest_time = 0 message = "No MOTD currently present." for x in motds: bl = onionrblocks.onionrblockapi.Block(x) if not bl.verifySig() or bl.signer != bytesconverter.bytes_to_str(unpaddedbase32.repad(bytesconverter.str_to_bytes(signer))): continue if not bl.isSigner(signer): continue if bl.claimedTime > newest_time: newest_time = bl.claimedTime message = bl.bcontent return Response(message, headers={"Content-Type": "text/plain"})
def find_site_gzip(user_id: str) -> tarfile.TarFile: """Return verified site tar object""" sites = blockmetadb.get_blocks_by_type('osite') user_site = None user_id = unpaddedbase32.repad(user_id) for site in sites: block = onionrblockapi.Block(site) if block.isSigner(user_id): user_site = block if not user_site is None: return tarfile.open(fileobj=io.BytesIO(user_site.bcontent), mode='r') return None
def ed_sign(data, key, encodeResult=False): '''Ed25519 sign data''' key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key)) try: data = data.encode() except AttributeError: pass key = nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder) retData = '' if encodeResult: retData = key.sign( data, encoder=nacl.encoding.Base64Encoder).signature.decode( ) # .encode() is not the same as nacl.encoding else: retData = key.sign(data).signature return retData
def change_ID(): key_manager = keymanager.KeyManager() try: key = sys.argv[2] key = unpaddedbase32.repad(key.encode()).decode() except IndexError: logger.warn('Specify pubkey to use', terminal=True) else: if stringvalidators.validate_pub_key(key): key_list = key_manager.getPubkeyList() if key in key_list or key.replace('=', '') in key_list: config.set('general.public_key', key) config.save() logger.info('Set active key to: %s' % (key, ), terminal=True) logger.info('Restart Onionr if it is running.', terminal=True) else: logger.warn('That key does not exist', terminal=True) else: logger.warn('Invalid key %s' % (key, ), terminal=True)
def validate_pub_key(key): ''' Validate if a string is a valid base32 encoded Ed25519 key ''' if type(key) is type(None): return False # Accept keys that have no = padding key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key)) retVal = False try: nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder) except nacl.exceptions.ValueError: pass except base64.binascii.Error as err: pass else: retVal = True return retVal
def __init__(self, publicKey, saveUser=False, recordExpireSeconds=5): try: if mnemonickeys.DELIMITER in publicKey: publicKey = mnemonickeys.get_base32(publicKey) #publicKey = unpaddedbase32.b32encode(bytesconverter.str_to_bytes(publicKey)) except ValueError: pass publicKey = bytesconverter.bytes_to_str( unpaddedbase32.repad(bytesconverter.str_to_bytes(publicKey))) super(ContactManager, self).__init__(publicKey, saveUser=saveUser) home = identifyhome.identify_home() self.dataDir = home + '/contacts/' self.dataFile = '%s/contacts/%s.json' % (home, publicKey) self.lastRead = 0 self.recordExpire = recordExpireSeconds self.data = self._loadData() self.deleted = False if not os.path.exists(self.dataDir): os.mkdir(self.dataDir)
def pub_key_encrypt(data, pubkey, encodedData=False): '''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)''' pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey)) retVal = '' box = None data = bytesconverter.str_to_bytes(data) pubkey = nacl.signing.VerifyKey( pubkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_public_key() if encodedData: encoding = nacl.encoding.Base64Encoder else: encoding = nacl.encoding.RawEncoder box = nacl.public.SealedBox(pubkey) retVal = box.encrypt(data, encoder=encoding) return retVal
def __init__(self, publicKey, saveUser=False): """ OnionrUser is an abstraction for "users" of the network. Takes a base32 encoded ed25519 public key, and a bool saveUser saveUser determines if we should add a user to our peer database or not. """ publicKey = unpaddedbase32.repad( bytesconverter.str_to_bytes(publicKey)).decode() self.trust = 0 self.publicKey = publicKey if saveUser and not publicKey == getourkeypair.get_keypair(): try: keydb.addkeys.add_peer(publicKey) except (AssertionError, ValueError) as _: pass self.trust = keydb.userinfo.get_user_info(self.publicKey, 'trust') return
def ed_verify(data, key, sig, encodedData=True): '''Verify signed data (combined in nacl) to an ed25519 key''' key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key)) try: key = nacl.signing.VerifyKey(key=key, encoder=nacl.encoding.Base32Encoder) except nacl.exceptions.ValueError: return False except binascii.Error: logger.warn('Could not load key for verification, invalid padding') return False retData = False sig = base64.b64decode(sig) try: data = data.encode() except AttributeError: pass try: retData = key.verify(data, sig) # .encode() is not the same as nacl.encoding except nacl.exceptions.BadSignatureError: pass return retData
def isSigner(self, signer, encodedData=True): """ Checks if the block was signed by the signer inputted Inputs: - signer (str): the public key of the signer to check against - encodedData (bool): whether or not the `signer` argument is base64 encoded Outputs: - (bool): whether or not the signer of the block is the signer inputted """ signer = unpaddedbase32.repad(bytesconverter.str_to_bytes(signer)) try: if (not self.isSigned()) or ( not stringvalidators.validate_pub_key(signer)): return False return bool( signing.ed_verify(self.getSignedData(), signer, self.getSignature(), encodedData=encodedData)) except: return False
def pub_key_decrypt(data, pubkey='', privkey='', encodedData=False): '''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)''' if pubkey != '': pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey)) decrypted = False if encodedData: encoding = nacl.encoding.Base64Encoder else: encoding = nacl.encoding.RawEncoder if privkey == '': privkey = our_priv_key ownKey = nacl.signing.SigningKey( seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key() if stringvalidators.validate_pub_key(privkey): privkey = nacl.signing.SigningKey( seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key() anonBox = nacl.public.SealedBox(privkey) else: anonBox = nacl.public.SealedBox(ownKey) decrypted = anonBox.decrypt(data, encoder=encoding) return decrypted
def getHumanReadable(name): name = unpaddedbase32.repad(bytesconverter.str_to_bytes(name)) return Response(mnemonickeys.get_human_readable_ID(name))
import nacl.encoding, nacl.public, nacl.signing from .. import getourkeypair import unpaddedbase32 from onionrutils import bytesconverter, stringvalidators pair = getourkeypair.get_keypair() our_pub_key = unpaddedbase32.repad(pair[0].encode()) our_priv_key = unpaddedbase32.repad(pair[1].encode()) def pub_key_encrypt(data, pubkey, encodedData=False): '''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)''' pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey)) retVal = '' box = None data = bytesconverter.str_to_bytes(data) pubkey = nacl.signing.VerifyKey( pubkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_public_key() if encodedData: encoding = nacl.encoding.Base64Encoder else: encoding = nacl.encoding.RawEncoder box = nacl.public.SealedBox(pubkey) retVal = box.encrypt(data, encoder=encoding) return retVal