def test_build_rebuild_modify(self): # generate shards for testing bucket = Builder(addresses["epsilon"], my_shard_size, my_max_size, debug=True) bucket.build(self.store_path) # modify one of the files o = 'baf428097fa601fac185750483fd532abb0e43f9f049398290fac2c049cc2a60' path = os.path.join(self.store_path, o) sha256_org_file = partialhash.compute(path) # write some data with open(path, "a") as f: f.write("bad data is bad\n") # check their hashes sha256_mod_file = partialhash.compute(path) self.assertNotEqual(sha256_org_file, sha256_mod_file) # build without a rebuild should fail bucket.build(self.store_path) sha256_mod_file = partialhash.compute(path) self.assertNotEqual(sha256_org_file, sha256_mod_file) # build with a rebuild should pass bucket.build(self.store_path, rebuild=True) sha256_mod_file = partialhash.compute(path) self.assertEqual(sha256_org_file, sha256_mod_file)
def audit(self, store_path, btc_index, btc_hash, block_size=common.DEFAULT_BLOCK_SIZE, full_audit=common.DEFAULT_FULL_AUDIT, min_confirmations=DEFAULT_MIN_CONFIRMATIONS): """audit one block""" audit_begin = (btc_index % full_audit) * block_size audit_end = audit_begin + block_size logger.info("Audit block {0} - {1}.".format(audit_begin, audit_end)) seeds = self.build_seeds(audit_end)[audit_begin:] # check if the block is complete for seed in seeds: path = self._get_shard_path(store_path, seed) if not (os.path.exists(path) and os.path.getsize(path) == self.shard_size): logger.info("Shard missing or corrupt {0}".format(path)) return 0 # generate audit response audit_hash = "" for seed in seeds: path = self._get_shard_path(store_path, seed) digest = partialhash.compute(path, seed=btc_hash.encode('utf8')) audit_hash += str(binascii.hexlify(digest)) return str(hashlib.sha256(audit_hash.encode('utf-8')).hexdigest())
def test_partial(self): path = fixtures["partial"]["path"] length = fixtures["partial"]["length"] offset = fixtures["partial"]["offset"] expected = h2b(fixtures["partial"]["sha256"]) digest = partialhash.compute(path, length=length, offset=offset) self.assertEqual(digest, expected)
def test_seed(self): seed_path = fixtures["seed"]["seed_path"] file_path = fixtures["seed"]["file_path"] expected = h2b(fixtures["seed"]["sha256"]) with open(seed_path, 'rb') as seed_file: seed_data = seed_file.read() digest = partialhash.compute(file_path, seed=seed_data) self.assertEqual(digest, expected)
def get_hash_bin(shard, salt=b"", size=0, offset=0): """Get the hash of the shard. Args: shard: A file like object representing the shard. salt: Optional salt to add as a prefix before hashing. Returns: Hex digetst of ripemd160(sha256(salt + shard)). """ shard.seek(0) digest = partialhash.compute(shard, offset=offset, length=size, seed=salt, hash_algorithm=hashlib.sha256) shard.seek(0) return ripemd160(digest).digest()
def verify_response(data, challenge, response): """ Generates the response for a requested audit. Arguments: data: File path or file like object. challenge: challenge bytes response: The audit response to verify. Returns: True if response is correct. """ # TODO validate input # get reward secret sha256sum(challenge + data) reward_secret = partialhash.compute(data, seed=challenge) # get response sha256sum(reward secret) generated_response = hashlib.sha256(reward_secret).digest() return response == generate_response
def generate_response(btctxstore, data, challenge): """ Generates the response for a requested audit. Arguments: btctxstore: BtcTxStore instance used generate the reward wif. data: File path or file like object. challenge: challenge bytes Returns: { "response": sha256sum, "reward_wif": bitcoin_wif } """ # TODO validate input # get reward secret sha256sum(challenge + data) reward_secret = partialhash.compute(data, seed=challenge) # generate reward wif from reward secret reward_wif = btctxstore.create_key(master_secret=reward_secret) # get response (second hash to prevent infering of the reward secret) response = hashlib.sha256(reward_secret).digest() return {"response": response, "reward_wif": reward_wif}
# coding: utf-8 # Copyright (c) 2015 Fabian Barkhau <*****@*****.**> # License: MIT (see LICENSE file) from __future__ import print_function from __future__ import unicode_literals import binascii import partialhash path = "examples/random.data" # sha256 hash of full file digest = partialhash.compute(path) # file path or file like object print(binascii.hexlify(digest)) # sha256 hash of first 1024 bytes digest = partialhash.compute(path, length=1024) print(binascii.hexlify(digest)) # sha256 hash, skipping the first 512 bytes digest = partialhash.compute(path, offset=512) print(binascii.hexlify(digest)) # sha256 hash of seed + file data digest = partialhash.compute(path, seed=b'seeddata')
def callback(): path = fixtures["bounds"]["path"] length = fixtures["bounds"]["length"] partialhash.compute(path, length=length)
def callback(): path = fixtures["negative_length"]["path"] length = fixtures["negative_length"]["length"] partialhash.compute(path, length=length)
def callback(): path = fixtures["negative_offset"]["path"] offset = fixtures["negative_offset"]["offset"] partialhash.compute(path, offset=offset)
def test_full(self): path = fixtures["full"]["path"] expected = h2b(fixtures["full"]["sha256"]) digest = partialhash.compute(path) self.assertEqual(digest, expected)