diff --git a/ipv8/attestation/trustchain/block.py b/ipv8/attestation/trustchain/block.py index 9ea612f7c..fbdd08096 100644 --- a/ipv8/attestation/trustchain/block.py +++ b/ipv8/attestation/trustchain/block.py @@ -291,7 +291,7 @@ def err(reason, double_spend=False): if linklinked is not None and linklinked.hash != self.hash: err("Double countersign fraud") if 'double_sig' in self.transaction and self.transaction['double_sig'] \ - and 'double_sig' in linklinked.transaction and linklinked.transactino['double_sig']: + and 'double_sig' in linklinked.transaction and linklinked.transaction['double_sig']: (sign_secret, private_key) = crypto.recover_double_signature( self.transaction['double_sig'], linklinked.transaction['double_sig'], @@ -319,7 +319,7 @@ def err(reason, double_spend=False): return result[0], errors, result[1] - def sign(self, key): + def sign(self, key, double_sign=True): """ Signs this block with the given key :param key: the key to sign this block with @@ -330,8 +330,9 @@ def sign(self, key): # Attach custom double signature to the transaction itself sign_secret = doublesign.sha256("%s%s" % (key, self.block_id)) - if self.transaction and isinstance(self.transaction, dict): - self.transaction['double_sig'] = crypto.create_custom_signature(key.key.hex_sk(), data, sign_secret) + if double_sign and self.transaction and isinstance(self.transaction, dict): + signing_secret_key_hex = key.key.signer.sk[:32].encode('hex') + self.transaction['double_sig'] = crypto.create_custom_signature(signing_secret_key_hex, data, sign_secret) @classmethod def create(cls, transaction, database, public_key, link=None, link_pk=None): diff --git a/ipv8/attestation/trustchain/community.py b/ipv8/attestation/trustchain/community.py index c1e53e8b1..90515d004 100644 --- a/ipv8/attestation/trustchain/community.py +++ b/ipv8/attestation/trustchain/community.py @@ -50,11 +50,13 @@ class TrustChainCommunity(Community): def __init__(self, *args, **kwargs): working_directory = kwargs.pop('working_directory', '') db_name = kwargs.pop('db_name', self.DB_NAME) + double_sign = kwargs.pop('double_sign', True) super(TrustChainCommunity, self).__init__(*args, **kwargs) self.request_cache = RequestCache() self.logger = logging.getLogger(self.__class__.__name__) self.persistence = self.DB_CLASS(working_directory, db_name) self.relayed_broadcasts = [] + self.double_sign = double_sign self.logger.debug("The trustchain community started with Public Key: %s", self.my_peer.public_key.key_to_bin().encode("hex")) @@ -135,7 +137,7 @@ def sign_block(self, peer, public_key=EMPTY_PK, transaction=None, linked=None): block = self.BLOCK_CLASS.create(transaction, self.persistence, self.my_peer.public_key.key_to_bin(), link=linked, link_pk=public_key) - block.sign(self.my_peer.key) + block.sign(self.my_peer.key, double_sign=self.double_sign) validation = block.validate(self.persistence) self.logger.info("Signed block to %s (%s) validation result %s", block.link_public_key.encode("hex")[-8:], block, validation) diff --git a/ipv8/keyvault/doublesign.py b/ipv8/keyvault/doublesign.py index 486851d27..e96842846 100644 --- a/ipv8/keyvault/doublesign.py +++ b/ipv8/keyvault/doublesign.py @@ -5,12 +5,21 @@ """ import logging from binascii import unhexlify, hexlify + from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric.rsa import _modinv logger = logging.getLogger(__name__) +try: + from gmpy2 import mpz + gmpy_present = True +except ImportError: + gmpy_present = False + +def fastint(int_value): + return mpz(int_value) if gmpy_present else int_value def sha256(msg): msg_hash = hashes.Hash(hashes.SHA256(), backend=default_backend()) @@ -163,7 +172,8 @@ def integer(self, x): """ Returns a plain integer """ - return x.value if isinstance(x, FieldElement) else x + int_value = x.value if isinstance(x, FieldElement) else x + return fastint(int_value) def zero(self): """ diff --git a/test/attestation/identity/test_identity.py b/test/attestation/identity/test_identity.py index 13eaf4d8a..da8462e01 100644 --- a/test/attestation/identity/test_identity.py +++ b/test/attestation/identity/test_identity.py @@ -14,7 +14,7 @@ def setUp(self): def create_node(self): return MockIPv8(u"curve25519", IdentityCommunity, working_directory=u":memory:") - @twisted_wrapper + @twisted_wrapper(4) def test_advertise(self): """ Check if a node can construct an advertisement for his attestest attribute. diff --git a/test/attestation/trustchain/test_block.py b/test/attestation/trustchain/test_block.py index 5bdaf3d93..a9035e46d 100644 --- a/test/attestation/trustchain/test_block.py +++ b/test/attestation/trustchain/test_block.py @@ -15,7 +15,7 @@ class TestBlock(TrustChainBlock): Also used in other test files for TrustChain. """ - def __init__(self, transaction=None, previous=None, key=None): + def __init__(self, transaction=None, previous=None, key=None, double_sign=False): crypto = ECCrypto() other = crypto.generate_key(u"curve25519").pub().key_to_bin() @@ -34,7 +34,7 @@ def __init__(self, transaction=None, previous=None, key=None): TrustChainBlock.__init__(self, ( encode(transaction), self.key.pub().key_to_bin(), random.randint(50, 100), other, 0, sha256(str(random.randint(0, 100000))).digest(), 0, 0)) - self.sign(self.key) + self.sign(self.key, double_sign=double_sign) class MockDatabase(object): @@ -167,21 +167,21 @@ def test_double_spending(self): db = MockDatabase() # Adding 4 test blocks - block0 = TestBlock(key=key) + block0 = TestBlock(key=key, double_sign=True) block0.sequence_number = GENESIS_SEQ db.add_block(block0) - block1 = TestBlock(previous=block0) + block1 = TestBlock(previous=block0, double_sign=True) db.add_block(block1) - block2 = TestBlock(previous=block1) + block2 = TestBlock(previous=block1, double_sign=True) db.add_block(block2) - block3 = TestBlock(previous=block2) + block3 = TestBlock(previous=block2, double_sign=True) db.add_block(block3) # Double signed block; Previous block is same as for block3 - new_block = TestBlock(previous=block2) + new_block = TestBlock(previous=block2, double_sign=True) # Validation should detect double spend and recover the private key of the signer. validation = new_block.validate(db) @@ -190,5 +190,6 @@ def test_double_spending(self): # Check equality of the private keys recovered_private_key = validation[2][1] - self.assertEqual(key.key.sk, recovered_private_key, "Recovered private key did not match.") + original_signing_secret_key = key.key.signer.sk[:32] + self.assertEqual(original_signing_secret_key, recovered_private_key, "Recovered private key did not match.") diff --git a/test/attestation/trustchain/test_community.py b/test/attestation/trustchain/test_community.py index 9f4d3fce0..012e5a481 100644 --- a/test/attestation/trustchain/test_community.py +++ b/test/attestation/trustchain/test_community.py @@ -12,7 +12,7 @@ def setUp(self): self.initialize(TrustChainCommunity, 2) def create_node(self): - return MockIPv8(u"curve25519", TrustChainCommunity, working_directory=u":memory:") + return MockIPv8(u"curve25519", TrustChainCommunity, working_directory=u":memory:", double_sign=False) @twisted_wrapper def test_sign_half_block(self): diff --git a/test/util.py b/test/util.py index d6aab9090..a57d6d545 100644 --- a/test/util.py +++ b/test/util.py @@ -166,4 +166,4 @@ def twisted_wrapper(arg): """ if isinstance(arg, (int, long)): return lambda x: deferred(arg)(inlineCallbacks(x)) - return deferred(timeout=10)(inlineCallbacks(arg)) + return deferred(timeout=1)(inlineCallbacks(arg))