Skip to content

Commit

Permalink
Merge pull request #2232 from pimveldhuisen/tunnel-perm-id
Browse files Browse the repository at this point in the history
Use a permanent identity for the multichain
  • Loading branch information
whirm committed Jun 7, 2016
2 parents f8b5725 + af82fb9 commit 07d1acd
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 24 deletions.
22 changes: 12 additions & 10 deletions Tribler/Core/APIImplementation/LaunchManyCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,19 +238,21 @@ def load_communities():
self.dispersy.define_auto_load(PreviewChannelCommunity,
self.session.dispersy_member, kargs=default_kwargs)

# Define settings for the Tunnel and Multichain community
keypair = self.dispersy.crypto.generate_key(u"curve25519")
dispersy_member = self.dispersy.get_member(private_key=self.dispersy.crypto.key_to_bin(keypair),)
if self.session.get_tunnel_community_enabled():

if self.session.get_enable_multichain():
from Tribler.community.multichain.community import MultiChainCommunity
# Start the multichain community and hook in the multichain scheduler.
self.dispersy.define_auto_load(MultiChainCommunity, dispersy_member, load=True)
if self.session.get_enable_multichain():
# If the multichain is enabled, we use the permanent multichain keypair
# for both the multichain and the tunnel community
keypair = self.session.multichain_keypair
dispersy_member = self.dispersy.get_member(private_key=keypair.key_to_bin())

from Tribler.community.multichain.community import MultiChainCommunity
self.dispersy.define_auto_load(MultiChainCommunity, dispersy_member, load=True)
else:
keypair = self.dispersy.crypto.generate_key(u"curve25519")
dispersy_member = self.dispersy.get_member(private_key=self.dispersy.crypto.key_to_bin(keypair))

if self.session.get_tunnel_community_enabled():
from Tribler.community.tunnel.hidden_community import HiddenTunnelCommunity
# The multichain community MUST be auto_loaded before the tunnel community,
# because it must be unloaded after the tunnel, so that the tunnel closures can be signed
tunnel_settings = TunnelSettings(tribler_session=self.session)
tunnel_kwargs = {'tribler_session': self.session, 'settings': tunnel_settings}
self.tunnel_community = self.dispersy.define_auto_load(
Expand Down
15 changes: 13 additions & 2 deletions Tribler/Core/Session.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ def set_and_create_dir(dirname, setter, default_dir):
#
pairfilename = scfg.get_permid_keypair_filename()

if os.access(pairfilename, os.F_OK):
# May throw exceptions
if os.path.exists(pairfilename):
self.keypair = permidmod.read_keypair(pairfilename)
else:
self.keypair = permidmod.generate_keypair()
Expand All @@ -123,6 +122,18 @@ def set_and_create_dir(dirname, setter, default_dir):
permidmod.save_keypair(self.keypair, pairfilename)
permidmod.save_pub_key(self.keypair, pubfilename)

multichain_pairfilename = scfg.get_multichain_permid_keypair_filename()

if os.path.exists(multichain_pairfilename):
self.multichain_keypair = permidmod.read_keypair_multichain(multichain_pairfilename)
else:
self.multichain_keypair = permidmod.generate_keypair_multichain()

# Save keypair
multichain_pubfilename = os.path.join(scfg.get_state_dir(), 'ecpub_multichain.pem')
permidmod.save_keypair_multichain(self.multichain_keypair, multichain_pairfilename)
permidmod.save_pub_key_multichain(self.multichain_keypair, multichain_pubfilename)

if not scfg.get_megacache():
scfg.set_torrent_checking(0)

Expand Down
21 changes: 21 additions & 0 deletions Tribler/Core/SessionConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,27 @@ def get_permid_keypair_filename(self):
self.set_permid_keypair_filename(file_name)
return file_name

def set_multichain_permid_keypair_filename(self, keypairfilename):
""" Set the filename containing the Elliptic Curve keypair to use for
PermID-based authentication for multichain in this Session.
Note: if a Session is started with a SessionStartupConfig that
points to an existing state dir and that state dir contains a saved
keypair, that keypair will be used unless a different keypair is
explicitly configured via this method.
"""
self.sessconfig.set(u'general', u'ec_keypair_filename_multichain', keypairfilename)

def get_multichain_permid_keypair_filename(self):
""" Returns the filename of the Session's multichain keypair.
@return An absolute path name. """
file_name = self.sessconfig.get(u'general', u'ec_keypair_filename_multichain')
if not file_name:
file_name = os.path.join(self.get_state_dir(), 'ec_multichain.pem')
self.set_multichain_permid_keypair_filename(file_name)
return file_name


def set_listen_port(self, port):
""" Set the UDP and TCP listen port for this Session.
@param port A port number.
Expand Down
22 changes: 22 additions & 0 deletions Tribler/Core/permid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import logging
from M2Crypto import Rand, EC, BIO
from Tribler.dispersy.crypto import LibNaCLSK

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -47,3 +48,24 @@ def save_pub_key(keypair, pubkeyfilename):
with open(pubkeyfilename, 'w') as file:
file.write(membuf.read())
membuf.close()


def generate_keypair_multichain():
return LibNaCLSK()


def read_keypair_multichain(keypairfilename):
with open(keypairfilename, 'rb') as keyfile:
binarykey = keyfile.read()
return LibNaCLSK(binarykey=binarykey)


def save_keypair_multichain(keypair, keypairfilename):
with open(keypairfilename, 'wb') as keyfile:
keyfile.write(keypair.key.sk)
keyfile.write(keypair.key.seed)

def save_pub_key_multichain(keypair, pubkeyfilename):
with open(pubkeyfilename, 'wb') as keyfile:
keyfile.write(keypair.key.pk)

38 changes: 28 additions & 10 deletions Tribler/Test/Core/test_permid.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,44 @@
from M2Crypto.EC import EC

from Tribler.Core import permid
from Tribler.dispersy.crypto import LibNaCLSK
from Tribler.Test.Core.base_test import TriblerCoreTest


class TriblerCoreTestPermid(TriblerCoreTest):

def setUp(self):
super(TriblerCoreTestPermid, self).setUp()
# All the files are in self.session_base_dir, so they will automatically be cleaned on tearDown()
self.pub_key_path = os.path.join(self.session_base_dir, 'pub_key.pem')
self.key_pair_path = os.path.join(self.session_base_dir, 'pair.pem')
self.pub_key_path_multichain = os.path.join(self.session_base_dir, 'pub_key_multichain.pem')
self.key_pair_path_multichain = os.path.join(self.session_base_dir, 'pair_multichain.pem')

def test_save_load_keypair_pubkey(self):
permid.init()
key = permid.generate_keypair()

test_base_dir = mkdtemp(suffix="_tribler_test_session")
pub_key_path = os.path.join(test_base_dir, 'pub_key.pem')
key_pair_path = os.path.join(test_base_dir, 'pair.pem')

permid.save_keypair(key, key_pair_path)
permid.save_pub_key(key, pub_key_path)
permid.save_keypair(key, self.key_pair_path)
permid.save_pub_key(key, self.pub_key_path)

self.assertTrue(os.path.isfile(pub_key_path))
self.assertTrue(os.path.isfile(key_pair_path))
self.assertTrue(os.path.isfile(self.pub_key_path))
self.assertTrue(os.path.isfile(self.key_pair_path))

loaded_key = permid.read_keypair(key_pair_path)
loaded_key = permid.read_keypair(self.key_pair_path)
self.assertIsInstance(loaded_key, EC)

shutil.rmtree(unicode(test_base_dir), ignore_errors=True)
def test_save_load_keypair_pubkey_multichain(self):
permid.init()
key = permid.generate_keypair_multichain()

permid.save_keypair_multichain(key, self.key_pair_path_multichain)
permid.save_pub_key_multichain(key, self.pub_key_path_multichain)

self.assertTrue(os.path.isfile(self.pub_key_path_multichain))
self.assertTrue(os.path.isfile(self.key_pair_path_multichain))

loaded_key = permid.read_keypair_multichain(self.key_pair_path_multichain)
self.assertIsInstance(loaded_key, LibNaCLSK)
self.assertEquals(key.key_to_bin(), loaded_key.key_to_bin())

1 change: 1 addition & 0 deletions Tribler/community/multichain/community.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(self, *args, **kwargs):
self._private_key = self.my_member.private_key
self._public_key = self.my_member.public_key
self.persistence = MultiChainDB(self.dispersy, self.dispersy.working_directory)
self.logger.debug("The multichain community started with Public Key: %s", base64.encodestring(self._public_key))

# No response is expected yet.
self.expected_response = None
Expand Down
2 changes: 2 additions & 0 deletions Tribler/community/tunnel/tunnel_community.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,10 @@ def __init__(self, tribler_session=None):

if tribler_session:
self.become_exitnode = tribler_session.get_tunnel_community_exitnode_enabled()
self.enable_multichain = tribler_session.get_enable_multichain()
else:
self.become_exitnode = False
self.enable_multichain = False


class ExitCandidate(object):
Expand Down
17 changes: 15 additions & 2 deletions twisted/plugins/tunnel_helper_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ def check_yappi_args(profile):

class Options(usage.Options):
optFlags = [
["exit", "x", "Allow being an exit-node"]
["exit", "x", "Allow being an exit-node"],
["multichain", "M", "Enable the multichain community"]
]

optParameters = [
Expand Down Expand Up @@ -201,6 +202,7 @@ def start_tribler(self):
config.set_dispersy_port(self.dispersy_port)
config.set_enable_torrent_search(False)
config.set_enable_channel_search(False)
config.set_enable_multichain(self.settings.enable_multichain)

# We do not want to load the TunnelCommunity in the session but instead our own community
config.set_tunnel_community_enabled(False)
Expand All @@ -222,7 +224,12 @@ def start_community():
member = self.dispersy.get_member(private_key=self.dispersy.crypto.key_to_bin(keypair))
cls = TunnelCommunityCrawler
else:
member = self.dispersy.get_new_member(u"curve25519")
if self.settings.enable_multichain:
from Tribler.community.multichain.community import MultiChainCommunity
member = self.dispersy.get_member(private_key=self.session.multichain_keypair.key_to_bin())
self.dispersy.define_auto_load(MultiChainCommunity, member, load=True)
else:
member = self.dispersy.get_new_member(u"curve25519")
cls = HiddenTunnelCommunity
self.community = self.dispersy.define_auto_load(cls, member, (self.session, self.settings), load=True)[0]

Expand Down Expand Up @@ -459,6 +466,12 @@ def start_tunnel(self, options):
else:
logger.info("Exit-node disabled")

settings.enable_multichain = bool(options["multichain"])
if settings.enable_multichain:
logger.info("Multichain enabled")
else:
logger.info("Multichain disabled")

tunnel = Tunnel(settings, crawl_keypair_filename, dispersy_port)
StandardIO(LineHandler(tunnel, profile))

Expand Down

0 comments on commit 07d1acd

Please sign in to comment.