def mine(self): # Create hash of transactions with a Merkle Tree tree = MerkleTree() for t in self.transactions: tree.encryptRecord(t.id.encode()) # make bytestring merkle_hash = tree.rootHash # 32-bit sized nonce for nonce in range(2 << 32): # header consists ofev_hash, nonce, merkle of transactions # and the block timestamps. # see: https://en.bitcoin.it/wiki/Block_hashing_algorithm nonce = hex(nonce).encode() timestamp = str(time()).encode() header = self.previous_hash + nonce + merkle_hash + timestamp h = SHA256.new() # apply hashing 2 times hash_value = h.new(h.new(header).digest()).hexdigest() hash_value = str(hash_value[::-1]) # reverse, little endian if int(hash_value[0:config.DIFFICULTY], 16) == 0: solved = True break if solved: self.hash = hash_value.encode() self.nonce = nonce self.timestamp = timestamp else: self.mine()
def importarDicionario(self, dicionario): _tArvore = dicionario["arvoreDeMerkle"] _tTransacoesDict = OrderedDict() _tTransacoesDict = dicionario["transacoes"] _tTransacoes = blocosDeTransacoesFinal() _tTransacoes.importarDicionarios(_tTransacoesDict["transacoes"]) _tArvoreJson = open("tmp.json", "w") json.dump(_tArvore, _tArvoreJson) _tArvoreJson.close() _tArvoreMerkle = MerkleTree.loadFromFile("tmp.json") if _tArvoreMerkle != MerkleTree(*_tTransacoes.dados()): raise arvoreDeMerkleInvalida self.transacoes = _tTransacoes self.arvoreDeMerkle = _tArvoreMerkle _tArvoreJson = open("tmp.json", "w") Utilitarios.remover_seguramente("tmp.json", 5) _tArvoreJson.close() return self
def test_UndecodableRecordError_with_encryptRecord(_byte, _encoding, _security): _tree = MerkleTree('a', 'b', 'c', encoding=_encoding, security=_security) _output = _tree.encryptRecord(_byte) assert _output == 1 and _tree.length == 3
def test_deserialization_error(): """ Tests JSONDecodeError upon trying to encrypt a non-deserializable .json file """ tree = MerkleTree() with pytest.raises(json.JSONDecodeError): tree.encryptJSONFromFile( os.path.join(parent_dir, 'json_files/bad.json'))
def test_UndecodableRecord_with_encryptRecord(byte, encoding, security): tree = MerkleTree('a', 'b', 'c', encoding=encoding, raw_bytes=False, security=security) with pytest.raises(UndecodableRecord): tree.encryptRecord(byte)
def test_deserialization_error(): """Tests that the .encryptObjectFromFile() method raises JSONDecodeError when the provided .json file cannot be deserialized """ tree = MerkleTree() with pytest.raises(json.JSONDecodeError): tree.encryptObjectFromFile( os.path.join(os.path.dirname(__file__), 'objects/bad.json'))
def test_WronJSONFormat(): """Tests that the .encryptFilePerObject() method raises WrongJSONFormat when the deserialized object loaded from the provided file is not a list """ tree = MerkleTree() with pytest.raises(WrongJSONFormat): tree.encryptFilePerObject( os.path.join(os.path.dirname(__file__), 'objects/sample.json'))
def test_encryptFilePerObject(tree, hash_machine): tree.clear() tree.encryptFilePerObject(objects_file_path, sort_keys=False, indent=0) clone_tree = MerkleTree(hash_type=tree.hash_type, encoding=tree.encoding, security=tree.security) for object in list_of_objects: clone_tree.update(record=json.dumps(object, sort_keys=False, indent=0)) assert tree.rootHash() == clone_tree.rootHash()
def test_encryptFilePerObject(_tree, _hash_machine): _tree.clear() _tree.encryptFilePerObject(objects_list_file, sort_keys=False, indent=0) _clone = MerkleTree(hash_type=_tree.hash_type, encoding=_tree.encoding, security=_tree.security) for _object in objects_list: _clone.update(record=json.dumps(_object, sort_keys=False, indent=0)) assert _tree.rootHash == _clone.rootHash
def test_encryptFilePerLog(tree): tree.clear() # Update original tree directly from file tree.encryptFilePerLog(short_APACHE_log_path) clone_tree = MerkleTree(hash_type=tree.hash_type, encoding=tree.encoding, security=tree.security) for record in records: clone_tree.update(record) assert tree.rootHash() == clone_tree.rootHash()
def validate_hash(self): # validate block hash value tree = MerkleTree() for t in self.transactions: tree.encryptRecord(t.id.encode()) # make bytestring merkle_hash = tree.rootHash header = self.previous_hash + self.nonce+\ merkle_hash + self.timestamp h = SHA256.new() hash_value = str(h.new(h.new(header).digest()).hexdigest()[::-1]) return (int(hash_value[0:config.DIFFICULTY], 16) == 0)
def test_tree_constructor_with_records(): tree_1 = MerkleTree(*(bytes('{}-th record'.format(i), 'utf-8') for i in range(0, 1000))) tree_2 = MerkleTree() for i in range(1000): tree_2.update('{}-th record'.format(i)) assert tree_1.rootHash() == tree_2.rootHash()
def test_validationReceipt(): _tree = MerkleTree(*['%d-th record' % i for i in range(5)]) _audit_proof = _tree.auditProof(3) _receipt = validationReceipt(target=_tree.rootHash, proof=_audit_proof, dirpath=os.path.join( os.path.dirname(__file__), 'receipts')) _receipt_path = os.path.join(os.path.dirname(__file__), 'receipts', '%s.json' % _receipt.header['uuid']) with open(_receipt_path) as _file: _clone = json.load(_file) assert _receipt.serialize() == _clone
def test_defense_against_second_preimage_attack(original_tree): # Construct forged record leaves = original_tree.leaves encoding = original_tree.encoding if original_tree.raw_bytes: F = leaves[2].digest G = leaves[3].digest else: F = leaves[2].digest.decode(encoding) G = leaves[3].digest.decode(encoding) forged_record = F + G # Attacker's tree attacker_tree = MerkleTree( 'a', 'b', forged_record, # forged records hash_type=original_tree.hash_type, encoding=original_tree.encoding, raw_bytes=original_tree.raw_bytes, security=original_tree.security) # Check if the attacker has replicated the original root-hash if original_tree.security: assert original_tree.rootHash != attacker_tree.rootHash else: assert original_tree.rootHash == attacker_tree.rootHash
def __init__(self, eleicao, abrangencia, endereco, zona, secao, blocoTF=None, arvore=None): if blocoTF != None: if len(blocoTF.dados()) == 0: raise quantidadeMenorQueUm elif isinstance(blocoTF, blocosDeTransacoesFinal): for transacao in blocoTF: if isinstance(transacao, Transacoes): pass else: raise tipoDeTransacaoDesconhecido if blocoTF.validaSequencia(): _tArvore = MerkleTree(*blocoTF.dados()) if arvore: if arvore != _tArvore: raise arvoreDeMerkleInvalida self.votos = blocoTF self.arvoreDeMerkle = _tArvore self.abrangencia = abrangencia self.endereco = endereco self.zona = zona self.secao = secao self.eleicao = eleicao else: raise sequenciaDeHashesInvalida else: raise deveSerBlocoDeTransacaoFinal
def test_validation_get_receipt(): tree = MerkleTree(*['%d-th record' % _ for _ in range(5)]) audit_proof = tree.auditProof(b'2-th record') receipt = validateProof(target=tree.rootHash, proof=audit_proof, get_receipt=True, dirpath=os.path.join(os.path.dirname(__file__), 'receipts')) receipt_path = os.path.join(os.path.dirname(__file__), 'receipts', '%s.json' % receipt.header['uuid']) with open(receipt_path) as __file: clone = json.load(__file) assert receipt.serialize() == clone
def create_tree(self): """Create the tree Args: output_folder (str): The folder where the parts will be written. """ self.tree = MerkleTree(hash_type=self.hash_type, security=False, raw_bytes=True) # Creating tree for i, f in enumerate(self.get_parts()): x = self.tree.update(f) # Creating proofs for i, f in enumerate(self._parts): self.proofs.append(self.tree.auditProof(i).serialize())
def arvoreDeMerkle(self, arvore): if not self.votos: raise registroSemTransacoes _tArvore = MerkleTree(*self.transacoes.dados()) if arvore != _tArvore: raise arvoreDeMerkleInvalida else: self._arvoreDeMerkle = arvore
def test_defense_against_second_preimage_attack(original_tree): # Construct forged record F = original_tree.leaves[2].stored_hash.decode( encoding=original_tree.encoding) G = original_tree.leaves[3].stored_hash.decode( encoding=original_tree.encoding) forged_record = '%s%s' % (F, G) # Construct attacker's tree attacker_tree = MerkleTree('a', 'b', forged_record, hash_type=original_tree.hash_type, encoding=original_tree.encoding, security=original_tree.security) # Check if the attacker has found the original root-hash if original_tree.security: assert original_tree.rootHash() != attacker_tree.rootHash() else: assert original_tree.rootHash() == attacker_tree.rootHash()
def __init__(self, file=None): """sets up the underlying merkle tree Parameters: file (str): Optional recovery of tree state dumped by export(). """ if file is None: self.merkle = MerkleTree( b"hello world", b"Hello world", b"hello World", b"Hello World", b"hello world!", b"Hello World!", # include enough hello worlds to construct a path raw_bytes=False, ) else: self.merkle = MerkleTree.loadFromFile(file)
def merkle_root(self): tree = MerkleTree() tree = MerkleTree(hash_type='sha256', encoding='utf-8', raw_bytes=True, security=True) tree.update(str(self.pending_transactions)) #tree.export('tree-without-root-hash.json') return str(tree.rootHash.decode())
def test_encryptFilePerLog(_tree): _tree.clear() _output = _tree.encryptFilePerLog(short_APACHE_log) if _tree.encoding not in EXTENDED: _clone = MerkleTree(*records, hash_type=_tree.hash_type, encoding=_tree.encoding, security=_tree.security) assert _output == 0 and _tree.rootHash == _clone.rootHash else: assert _output == 1 and not _tree
def test_encryptFilePerLog(tree): if tree.raw_bytes: tree.clear() encrypted = tree.encryptFilePerLog(short_APACHE_log) clone = MerkleTree(*records, hash_type=tree.hash_type, encoding=tree.encoding, raw_bytes=tree.raw_bytes, security=tree.security) assert tree.rootHash == clone.rootHash elif tree.encoding in ('iso8859_8', 'iso2022_kr', 'iso8859_3', 'ascii', 'utf_7', 'utf_32_be', 'iso2022_jp_1', 'utf_32_le', 'utf_32', 'iso2022_jp_3', 'iso2022_jp_2004', 'hz', 'iso8859_7', 'iso8859_6', 'iso2022_jp_ext', 'utf_16', 'cp424', 'iso2022_jp_2', 'utf_16_le', 'utf_16_be', 'iso2022_jp'): with pytest.raises(UndecodableRecord): tree.encryptFilePerLog(short_APACHE_log)
import pytest import os import json from pymerkle import MerkleTree # Clean exports dir before running the test for file in os.listdir(os.path.join(os.path.dirname(__file__), 'exports')): os.remove(os.path.join(os.path.dirname(__file__), 'exports', file)) tree = MerkleTree() for i in range(12): tree.update(record='{}-th record'.format(i)) export_path = os.path.join(os.path.dirname(__file__), 'exports', '{}.json'.format(tree.uuid)) tree.export(file_path=export_path) with open(export_path, 'r') as f: exported_version = json.load(f) def test_export(): assert exported_version == { "header": { "encoding": "utf_8", "hash_type": "sha256", "security": True }, "hashes": [ "a08665f5138f40a07987234ec9821e5be05ecbf5d7792cd4155c4222618029b6", "3dbbc4898d7e909de7fc7bb1c0af36feba78abc802102556e4ea52c28ccb517f", "45c44059cf0f5a447933f57d851a6024ac78b44a41603738f563bcbf83f35d20", "b5db666b0b34e92c2e6c1d55ba83e98ff37d6a98dda532b125f049b43d67f802",
import pytest from pymerkle import MerkleTree, hashing, encodings # Generate trees for all combinations of hash and encoding types # (including both security modes for each) HASH_TYPES = hashing.HASH_TYPES ENCODINGS = encodings.ENCODINGS trees = [] for security in (True, False): for hash_type in HASH_TYPES: for encoding in ENCODINGS: trees.append( MerkleTree( 'a', 'b', 'c', 'd', # original records hash_type=hash_type, encoding=encoding, security=security)) @pytest.mark.parametrize("original_tree", trees) def test_defense_against_second_preimage_attack(original_tree): # Construct forged record F = original_tree.leaves[2].stored_hash.decode( encoding=original_tree.encoding) G = original_tree.leaves[3].stored_hash.decode( encoding=original_tree.encoding) forged_record = '%s%s' % (F, G) # Construct attacker's tree attacker_tree = MerkleTree('a',
def test_loadFromFile(): assert tree.rootHash() == MerkleTree.loadFromFile( file_path=export_path).rootHash()
import json from pymerkle import MerkleTree, hashing, encodings HASH_TYPES = hashing.HASH_TYPES ENCODINGS = encodings.ENCODINGS # Generate trees and corresoponding hash machines for all combinations of # hash and encoding types (including both security modes for each) trees = [] hash_machines = [] for security in (True, False): for hash_type in HASH_TYPES: for encoding in ENCODINGS: trees.append( MerkleTree(hash_type=hash_type, encoding=encoding, security=security)) hash_machines.append( hashing.hash_machine(hash_type=hash_type, encoding=encoding, security=security)) @pytest.mark.parametrize("tree, hash_machine", [(trees[i], hash_machines[i]) for i in range(len(trees))]) def test_encryptRecord(tree, hash_machine): tree.encryptRecord('some kind of record...') assert tree.rootHash() == hash_machine.hash('some kind of record...') large_APACHE_log_path = os.path.join(os.path.dirname(__file__),
"""pymerkle demo""" from pymerkle import MerkleTree, validateProof if __name__ == '__main__': tree = MerkleTree(hash_type='sha256', encoding='utf-8', raw_bytes=True, security=True) for i in range(7): tree.encryptRecord('%d-th record' % i) print(repr(tree)) challenge = { 'checksum': '45c44059cf0f5a447933f57d851a6024ac78b44a41603738f563bcbf83f35d20' } proof = tree.merkleProof(challenge) print(proof) assert validateProof(proof) receipt = validateProof(proof, get_receipt=True) print(receipt)
import json from pymerkle import MerkleTree from pymerkle.hashing import HashMachine, HASH_TYPES from pymerkle.exceptions import UndecodableRecord from tests.conftest import ENCODINGS trees__hash_machines = [] for raw_bytes in (True, False): for security in (True, False): for hash_type in HASH_TYPES: for encoding in ENCODINGS: trees__hash_machines.append((MerkleTree(hash_type=hash_type, encoding=encoding, raw_bytes=raw_bytes, security=security), HashMachine(hash_type=hash_type, encoding=encoding, raw_bytes=raw_bytes, security=security))) single_records = [] for (tree, hash_machine) in trees__hash_machines: single_records.extend([(tree, hash_machine, 'string record'), (tree, hash_machine, bytes('bytes record', tree.encoding))]) @pytest.mark.parametrize("tree, hash_machine, record", single_records)
class GeradorDeUrna: auxCriptografia = Criptografia() util = Utilitarios() eleicao = None idSecao = None zona = None secao = None saldoInicial = None nonce = None timestamp = None endereco = None chavePublica = None arvoreDeMerkle = MerkleTree() candidatos = [] eleitores = [] cedulas = Cedulas() def __init__(self, eleicao, zona, secao): self.eleicao = eleicao self.zona = zona self.secao = secao self.timestamp = datetime.utcnow().timestamp() self.saldoInicial = 0 def incluirEleitor(self, eleitor_): if isinstance(eleitor_, tEleitor): _tEleitor = regEleitor(eleitor_.endereco, eleitor_.titulo) self.eleitores.append(_tEleitor) self.saldoInicial += 1 def serializarEleitores(self): _dicionarios = [] for _eleitor in self.eleitores: _dicionario = { "endereco": _eleitor.endereco, "titulo": _eleitor.titulo } _dicionarios.append(_dicionario) return _dicionarios def importarEleitor(self, dEleitor_): if dEleitor_["tipo"] == "eleitor": _e = tEleitor(dEleitor_["nome"], dEleitor_["titulo"], dEleitor_["endereco"], dEleitor_["chavePublica"], dEleitor_["aleatorio"], dEleitor_["timestamp"], dEleitor_["assinatura"]) self.incluirEleitor(_e) def incluirCandidato(self, candidato_): if isinstance(candidato_, tCandidato): _tCandidato = regCandidato(candidato_.numero, candidato_.abrangencia, candidato_.endereco, candidato_.nome) self.candidatos.append(_tCandidato) def importarCandidato(self, candidato_): if candidato_["tipo"] == "candidato": _c = tCandidato(candidato_["abrangencia"], candidato_["nome"], candidato_["titulo"], candidato_["cargo"], candidato_["numero"], candidato_["processo"], candidato_["endereco"], candidato_["timestamp"]) self.incluirCandidato(_c) def serializarCandidatos(self): _dicionarios = [] for _candidato in self.candidatos: _dicionario = { "numero": _candidato.numero, "abrangencia": _candidato.abrangencia, "endereco": _candidato.endereco, "nome": _candidato.nome, "saldo": _candidato.saldo } _dicionarios.append(_dicionario) return _dicionarios def gerarCedulas(self): if len(self.candidatos) > 0 and len(self.eleitores) > 0: self.cedulas.criarCedulas(self.saldoInicial) else: raise saldoInconsistente def gerarChaves(self): _sk = self.auxCriptografia.gerarChavePrivada() self.auxCriptografia.exportarChavePrivada( _sk, "tmp/PrivUrnaZona{}Secao{}.pem".format(self.zona, self.secao)) self.chavePublica = _sk.verifying_key def gerarEndereco(self): if self.chavePublica: self.endereco = self.util.gerarEndereco( "tmp/PrivUrnaZona{}Secao{}.pem".format(self.zona, self.secao)) def dados(self): return "{}{}{}{}{}{}{}".format(self.eleicao, self.zona, self.secao, self.endereco, self.saldoInicial, self.nonce, self.arvoreDeMerkle.rootHash) def calcularArvoreDeMerkle(self): for _c in self.cedulas: self.arvoreDeMerkle.update(_c.retornaIdCedula()) for _e in self.eleitores: self.arvoreDeMerkle.update(_e.dados()) for _cD in self.candidatos: self.arvoreDeMerkle.update(_cD.dados()) def importarCedulas(self, dicCedulas_): if isinstance(dicCedulas_, Cedulas): self.cedulas.importarDicionario(dicCedulas_["cedulas"]) def calcularHash(self): self.nonce = 0 gerador = hashing.HashMachine() _hash = '' while not _hash.startswith('00000'): _hash = gerador.hash(self.dados()) self.nonce += 1 return _hash def serializar(self): return { "eleicao": self.eleicao, "zona": self.zona, "secao": self.secao, "endereco": self.endereco, "saldoInicial": self.saldoInicial, "timestamp": self.timestamp, "nonce": self.nonce, "hashRaiz": self.arvoreDeMerkle.rootHash, "hash": self.calcularHash(), "arvoreDeMerkle": self.arvoreDeMerkle.serialize(), "cedulas": self.cedulas.serializar(), "eleitores": self.serializarEleitores(), "candidatos": self.serializarCandidatos() }