def validate_descriptor(stream_info): try: hex_stream_name = stream_info['stream_name'] key = stream_info['key'] hex_suggested_file_name = stream_info['suggested_file_name'] stream_hash = stream_info['stream_hash'] blobs = stream_info['blobs'] except KeyError as e: raise InvalidStreamDescriptorError("Missing '%s'" % (e.args[0])) if stream_info['blobs'][-1]['length'] != 0: raise InvalidStreamDescriptorError( "Does not end with a zero-length blob.") if any([ False if blob_info['length'] > 0 else True for blob_info in stream_info['blobs'][:-1] ]): raise InvalidStreamDescriptorError("Contains zero-length data blob") if 'blob_hash' in stream_info['blobs'][-1]: raise InvalidStreamDescriptorError( "Stream terminator blob should not have a hash") verify_hex(key, "key") verify_hex(hex_suggested_file_name, "suggested file name") verify_hex(stream_hash, "stream_hash") calculated_stream_hash = get_stream_hash(hex_stream_name, key, hex_suggested_file_name, blobs) if calculated_stream_hash != stream_hash: raise InvalidStreamDescriptorError( "Stream hash does not match stream metadata") return True
def validate(self): log.debug("Trying to validate stream descriptor for %s", str(self.raw_info['stream_name'])) try: hex_stream_name = self.raw_info['stream_name'] key = self.raw_info['key'] hex_suggested_file_name = self.raw_info['suggested_file_name'] stream_hash = self.raw_info['stream_hash'] blobs = self.raw_info['blobs'] except KeyError as e: raise InvalidStreamDescriptorError("Missing '%s'" % (e.args[0])) for c in hex_suggested_file_name: if c not in '0123456789abcdef': raise InvalidStreamDescriptorError( "Suggested file name is not a hex-encoded string") h = get_lbry_hash_obj() h.update(hex_stream_name) h.update(key) h.update(hex_suggested_file_name) def get_blob_hashsum(b): length = b['length'] if length != 0: blob_hash = b['blob_hash'] else: blob_hash = None blob_num = b['blob_num'] iv = b['iv'] blob_hashsum = get_lbry_hash_obj() if length != 0: blob_hashsum.update(blob_hash) blob_hashsum.update(str(blob_num)) blob_hashsum.update(iv) blob_hashsum.update(str(length)) return blob_hashsum.digest() blobs_hashsum = get_lbry_hash_obj() for blob in blobs: blobs_hashsum.update(get_blob_hashsum(blob)) if blobs[-1]['length'] != 0: raise InvalidStreamDescriptorError( "Does not end with a zero-length blob.") h.update(blobs_hashsum.digest()) if h.hexdigest() != stream_hash: raise InvalidStreamDescriptorError( "Stream hash does not match stream metadata") log.debug("It is validated") return defer.succeed(True)
def get_stream_hash(hex_stream_name, key, hex_suggested_file_name, blob_infos): h = get_lbry_hash_obj() h.update(hex_stream_name) h.update(key) h.update(hex_suggested_file_name) blobs_hashsum = get_lbry_hash_obj() sorted_blob_infos = sorted(blob_infos, key=lambda x: x['blob_num']) for blob in sorted_blob_infos: blobs_hashsum.update(get_blob_hashsum(blob)) if sorted_blob_infos[-1]['length'] != 0: raise InvalidStreamDescriptorError( "Does not end with a zero-length blob.") if 'blob_hash' in sorted_blob_infos[-1]: raise InvalidStreamDescriptorError( "Stream terminator blob should not have a hash") h.update(blobs_hashsum.digest()) return h.hexdigest()
def validate_descriptor(stream_info): try: hex_stream_name = stream_info['stream_name'] key = stream_info['key'] hex_suggested_file_name = stream_info['suggested_file_name'] stream_hash = stream_info['stream_hash'] blobs = stream_info['blobs'] except KeyError as e: raise InvalidStreamDescriptorError("Missing '%s'" % (e.args[0])) verify_hex(key, "key") verify_hex(hex_suggested_file_name, "suggested file name") verify_hex(stream_hash, "stream_hash") calculated_stream_hash = get_stream_hash(hex_stream_name, key, hex_suggested_file_name, blobs) if calculated_stream_hash != stream_hash: raise InvalidStreamDescriptorError( "Stream hash does not match stream metadata") return True
def _return_options_and_validator_and_factories(self, sd_info): if not 'stream_type' in sd_info: raise InvalidStreamDescriptorError('No stream_type parameter in stream descriptor.') stream_type = sd_info['stream_type'] validator = self._get_validator(stream_type)(sd_info) factories = [f for f in self._get_factories(stream_type) if f.can_download(validator)] d = validator.validate() def get_options(): options = self._get_options(stream_type) return validator, options, factories d.addCallback(lambda _: get_options()) return d
def validate(self): log.debug("Trying to validate stream descriptor for %s", str(self.raw_info['stream_name'])) hex_stream_name = self.raw_info['stream_name'] public_key = self.raw_info['public_key'] key = self.raw_info['key'] stream_hash = self.raw_info['stream_hash'] h = get_lbry_hash_obj() h.update(hex_stream_name) h.update(public_key) h.update(key) if h.hexdigest() != stream_hash: raise InvalidStreamDescriptorError( "Stream hash does not match stream metadata") blobs = self.raw_info['blobs'] def check_blob_signatures(): for blob in blobs: length = blob['length'] if length != 0: blob_hash = blob['blob_hash'] else: blob_hash = None blob_num = blob['blob_num'] revision = blob['revision'] iv = blob['iv'] signature = blob['signature'] hashsum = get_lbry_hash_obj() hashsum.update(stream_hash) if length != 0: hashsum.update(blob_hash) hashsum.update(str(blob_num)) hashsum.update(str(revision)) hashsum.update(iv) hashsum.update(str(length)) if not verify_signature(hashsum.digest(), signature, public_key): raise InvalidStreamDescriptorError( "Invalid signature in stream descriptor") return threads.deferToThread(check_blob_signatures)
def check_blob_signatures(): for blob in blobs: length = blob['length'] if length != 0: blob_hash = blob['blob_hash'] else: blob_hash = None blob_num = blob['blob_num'] revision = blob['revision'] iv = blob['iv'] signature = blob['signature'] hashsum = get_lbry_hash_obj() hashsum.update(stream_hash) if length != 0: hashsum.update(blob_hash) hashsum.update(str(blob_num)) hashsum.update(str(revision)) hashsum.update(iv) hashsum.update(str(length)) if not verify_signature(hashsum.digest(), signature, public_key): raise InvalidStreamDescriptorError("Invalid signature in stream descriptor")
def save_sd_info(blob_manager, sd_hash, sd_info): if not blob_manager.blobs.get( sd_hash) or not blob_manager.blobs[sd_hash].get_is_verified(): descriptor_writer = BlobStreamDescriptorWriter(blob_manager) calculated_sd_hash = yield descriptor_writer.create_descriptor(sd_info) if calculated_sd_hash != sd_hash: raise InvalidStreamDescriptorError( "%s does not match calculated %s" % (sd_hash, calculated_sd_hash)) stream_hash = yield blob_manager.storage.get_stream_hash_for_sd_hash( sd_hash) if not stream_hash: log.debug("Saving info for %s", sd_info['stream_name'].decode('hex')) stream_name = sd_info['stream_name'] key = sd_info['key'] stream_hash = sd_info['stream_hash'] stream_blobs = sd_info['blobs'] suggested_file_name = sd_info['suggested_file_name'] yield blob_manager.storage.add_known_blobs(stream_blobs) yield blob_manager.storage.store_stream(stream_hash, sd_hash, stream_name, key, suggested_file_name, stream_blobs) defer.returnValue(stream_hash)
def verify_hex(text, field_name): for c in text: if c not in '0123456789abcdef': raise InvalidStreamDescriptorError( "%s is not a hex-encoded string" % field_name)
def verify_hex(text, field_name): if not set(text).issubset(set(string.hexdigits)): raise InvalidStreamDescriptorError("%s is not a hex-encoded string" % field_name)