class CryptoTransportLayer(TransportLayer): def __init__(self, my_ip, my_port, market_id): self._log = logging.getLogger('[%s] %s' % (market_id, self.__class__.__name__)) # Connect to database MONGODB_URI = 'mongodb://localhost:27017' _dbclient = MongoClient() self._db = _dbclient.openbazaar self._market_id = market_id self.nick_mapping = {} self._uri = "tcp://%s:%s" % (my_ip, my_port) # Set up self._setup_settings() self._dht = DHT(self, market_id, self.settings) self._myself = ec.ECC(pubkey=self.pubkey.decode('hex'), privkey=self.secret.decode('hex'), curve='secp256k1') TransportLayer.__init__(self, market_id, my_ip, my_port, self.guid) # Set up callbacks self.add_callback('hello', self._ping) self.add_callback('findNode', self._findNode) self.add_callback('findNodeResponse', self._findNodeResponse) self.add_callback('store', self._storeValue) def get_guid(self): return self._guid def getDHT(self): return self._dht def getMarketID(self): return self._market_id def getMyself(self): return self._myself def _ping(self, msg): self._log.info('Pinged %s ' % msg) pinger = CryptoPeerConnection(self,msg['uri'], msg['pubkey'], msg['senderGUID']) msg = pinger.send_raw(json.dumps( {"type": "hello_response", "senderGUID": self.guid, "uri": self._uri, "pubkey": self.pubkey, })) print msg def _storeValue(self, msg): self._dht._on_storeValue(msg) def _findNode(self, msg): self._dht.on_find_node(msg) def _findNodeResponse(self, msg): self._dht.on_findNodeResponse(self, msg) def _setup_settings(self): self.settings = self._db.settings.find_one({'id':"%s" % self._market_id}) if self.settings: self.nickname = self.settings['nickname'] if self.settings.has_key("nickname") else "" self.secret = self.settings['secret'] self.pubkey = self.settings['pubkey'] self.guid = self.settings['guid'] else: self.nickname = 'Default' self._generate_new_keypair() self.settings = self._db.settings.find_one({'id':"%s" % self._market_id}) self._log.debug('Retrieved Settings: %s', self.settings) def _generate_new_keypair(self): # Generate new keypair key = ec.ECC(curve='secp256k1') self.secret = key.get_privkey().encode('hex') pubkey = key.get_pubkey() signedPubkey = key.sign(pubkey) self.pubkey = pubkey.encode('hex') self._myself = key # Generate a node ID by ripemd160 hashing the signed pubkey guid = hashlib.new('ripemd160') guid.update(signedPubkey) self.guid = guid.digest().encode('hex') self._db.settings.update({"id":'%s' % self._market_id}, {"$set": {"secret":self.secret, "pubkey":self.pubkey, "guid":self.guid}}, True) def join_network(self, seed_uri): self.listen(self.pubkey) # Turn on zmq socket if seed_uri: self._log.info('Initializing Seed Peer(s): [%s]' % seed_uri) seed_peer = CryptoPeerConnection(self, seed_uri) self._dht.start(seed_peer) def get_crypto_peer(self, guid, uri, pubkey=None): if guid == self.guid: self._log.info('Trying to get cryptopeer for yourself') return peer = CryptoPeerConnection(self, uri, pubkey, guid=guid) return peer def addCryptoPeer(self, peer): peerExists = False for idx, aPeer in enumerate(self._activePeers): if aPeer._guid == peer._guid or aPeer._pub == peer._pub or aPeer._address == peer._address: self._log.info('guids or pubkey match') peerExists = True if peer._pub and aPeer._pub == '': self._log.info('no pubkey') aPeer._pub = peer._pub self._activePeers[idx] = aPeer if not peerExists and peer._guid != self._guid: self._log.info('Adding crypto peer %s' % peer._pub) self._routingTable.addContact(peer) print peer self._dht.add_active_peer(self, (peer._pub, peer._address, peer._guid)) # Return data array with details from the crypto file # TODO: This needs to be protected better; potentially encrypted file or DB @staticmethod def load_crypto_details(store_file): with open(store_file) as f: data = json.loads(f.read()) assert "nickname" in data assert "secret" in data assert "pubkey" in data assert len(data["secret"]) == 2 * 32 assert len(data["pubkey"]) == 2 * 33 return data["nickname"], data["secret"].decode("hex"), \ data["pubkey"].decode("hex") def get_profile(self): peers = {} self.settings = self._db.settings.find_one({'id':"%s" % self._market_id}) for uri, peer in self._peers.iteritems(): if peer._pub: peers[uri] = peer._pub.encode('hex') return {'uri': self._uri, 'pub': self._myself.get_pubkey().encode('hex'),'nickname': self.nickname, 'peers': peers} def respond_pubkey_if_mine(self, nickname, ident_pubkey): if ident_pubkey != self.pubkey: self._log.info("Public key does not match your identity") return # Return signed pubkey pubkey = self._myself.pubkey ec_key = obelisk.EllipticCurveKey() ec_key.set_secret(self.secret) digest = obelisk.Hash(pubkey) signature = ec_key.sign(digest) # Send array of nickname, pubkey, signature to transport layer self.send(proto_response_pubkey(nickname, pubkey, signature)) def pubkey_exists(self, pub): for uri, peer in self._peers.iteritems(): self._log.info('PEER: %s Pub: %s' % (peer._pub.encode('hex'), pub.encode('hex'))) if peer._pub.encode('hex') == pub.encode('hex'): return True return False def create_peer(self, uri, pub, node_guid): if pub: pub = pub.decode('hex') # Create the peer if public key is not already in the peer list # if not self.pubkey_exists(pub): self._peers[uri] = CryptoPeerConnection(self, uri, pub, node_guid) # Call 'peer' callbacks on listeners self.trigger_callbacks('peer', self._peers[uri]) # else: # print 'Pub Key is already in peer list' def send_enc(self, uri, msg): peer = self._peers[uri] pub = peer._pub # Now send a hello message to the peer if pub: self._log.info("Sending encrypted [%s] message to %s" % (msg['type'], uri)) peer.send(msg) else: # Will send clear profile on initial if no pub self._log.info("Sending unencrypted [%s] message to %s" % (msg['type'], uri)) self._peers[uri].send_raw(json.dumps(msg)) def init_peer(self, msg): uri = msg['uri'] pub = msg.get('pub') nickname = msg.get('nickname') msg_type = msg.get('type') guid = msg['guid'] if not self.valid_peer_uri(uri): self._log.error("Invalid Peer: %s " % uri) return if uri not in self._peers: # Unknown peer self._log.info('Add New Peer: %s' % uri) self.create_peer(uri, pub, guid) if not msg_type: self.send_enc(uri, hello_request(self.get_profile())) elif msg_type == 'hello_request': self.send_enc(uri, hello_response(self.get_profile())) else: # Known peer if pub: # test if we have to update the pubkey if not self._peers[uri]._pub: self._log.info("Setting public key for seed node") self._peers[uri]._pub = pub.decode('hex') self.trigger_callbacks('peer', self._peers[uri]) if self._peers[uri]._pub != pub.decode('hex'): self._log.info("Updating public key for node") self._peers[uri]._nickname = nickname self._peers[uri]._pub = pub.decode('hex') self.trigger_callbacks('peer', self._peers[uri]) if msg_type == 'hello_request': # reply only if necessary self.send_enc(uri, hello_response(self.get_profile())) def on_message(self, msg): # here goes the application callbacks # we get a "clean" msg which is a dict holding whatever self._log.info("[On Message] Data received: %s" % msg) pubkey = msg.get('pubkey') uri = msg.get('uri') ip = urlparse(uri).hostname port = urlparse(uri).port guid = msg.get('senderGUID') self._dht.add_active_peer(self, (pubkey, uri, guid)) self._dht.add_known_node((ip, port, guid)) self.trigger_callbacks(msg['type'], msg) def on_raw_message(self, serialized): try: # Try to deserialize cleartext message msg = json.loads(serialized) self._log.info("Message Received [%s]" % msg.get('type', 'unknown')) except ValueError: try: # Encrypted? try: msg = self._myself.decrypt(serialized) msg = json.loads(msg) self._log.info("Decrypted Message [%s]" % msg.get('type', 'unknown')) except: self._log.error("Could not decrypt message: %s" % msg) return except: self._log.info("Bad Message: %s..." % self._myself.decrypt(serialized)) traceback.print_exc() return if msg.get('type') != '': msg_type = msg.get('type') msg_uri = msg.get('uri') msg_guid = msg.get('guid') self._log.info(msg.get('type')) # # if msg_type.startswith('hello') and msg_uri: # self.init_peer(msg) # for uri, pub in msg.get('peers', {}).iteritems(): # # Do not add yourself as a peer # if uri != self._uri: # self.init_peer({'uri': uri, 'pub': pub}) # self._log.info("Update peer table [%s peers]" % len(self._peers)) # # elif msg_type == 'goodbye' and msg_uri: # self._log.info("Received goodbye from %s" % msg_uri) # self.remove_peer(msg_uri) # # else: self.on_message(msg) else: self._log.error('Received a message with no type')
def signal_handler(sig, frame): logger.warning("Ctrl-C pressed, quitting") quit_event.set() sys.exit(0) def mount_disk(): if not os.path.ismount(DISK): os.system("mount %s" % dist) if __name__ == "__main__": #Start all acquisition threads gps.start() sds.start() dht.start() mount_disk() while gps.date is None: logger.warning("Waiting for GPS for date") time.sleep(1.0) today = gps.date.strftime("%Y-%m-%d") existing = len([1 for i in os.listdir(DISK) if i.startswith(today)]) base = os.path.join(DISK, today + "_%s.log" % existing) logger.info("Saving in %s" % base) cnt = 0 now = datetime.datetime(gps.date.year, gps.date.month, gps.date.day, gps.time.hour, gps.time.minute, gps.time.second) header = [ "#started on %s UTC" % now.strftime("%c"), "#%8s %21s %13s %20s" %
class CryptoTransportLayer(TransportLayer): def __init__(self, my_ip, my_port, market_id): self._log = logging.getLogger('[%s] %s' % (market_id, self.__class__.__name__)) # Connect to database MONGODB_URI = 'mongodb://localhost:27017' _dbclient = MongoClient() self._db = _dbclient.openbazaar self._market_id = market_id self.nick_mapping = {} self._uri = "tcp://%s:%s" % (my_ip, my_port) # Set up self._setup_settings() self._dht = DHT(market_id, self.settings) self._myself = ec.ECC(pubkey=self.pubkey.decode('hex'), privkey=self.secret.decode('hex'), curve='secp256k1') TransportLayer.__init__(self, market_id, my_ip, my_port, self.guid) # Set up callbacks self.add_callback('ping', self._dht._on_ping) self.add_callback('findNode', self._dht._on_findNode) self.add_callback('findNodeResponse', self._dht._on_findNodeResponse) def _setup_settings(self): self.settings = self._db.settings.find_one( {'id': "%s" % self._market_id}) if self.settings: self.nickname = self.settings['nickname'] if self.settings.has_key( "nickname") else "" self.secret = self.settings['secret'] self.pubkey = self.settings['pubkey'] self.guid = self.settings['guid'] else: self.nickname = 'Default' self._generate_new_keypair() self.settings = self._db.settings.find_one( {'id': "%s" % self._market_id}) self._log.debug('Retrieved Settings: %s', self.settings) def _generate_new_keypair(self): # Generate new keypair key = ec.ECC(curve='secp256k1') self.secret = key.get_privkey().encode('hex') pubkey = key.get_pubkey() signedPubkey = key.sign(pubkey) self.pubkey = pubkey.encode('hex') self._myself = key # Generate a node ID by ripemd160 hashing the signed pubkey guid = hashlib.new('ripemd160') guid.update(signedPubkey) self.guid = guid.digest().encode('hex') self._db.settings.update({"id": '%s' % self._market_id}, { "$set": { "secret": self.secret, "pubkey": self.pubkey, "guid": self.guid } }, True) def join_network(self, seed_uri): self.listen(self.pubkey) # Turn on zmq socket if seed_uri: self._log.info('Initializing Seed Peer(s): [%s]' % (seed_uri)) seed_peer = CryptoPeerConnection(self, seed_uri) self._dht.start(seed_peer) def _addCryptoPeer(self, uri, guid, pubkey): peer = CryptoPeerConnection(self, uri, pubkey) self.addCryptoPeer(peer) def addCryptoPeer(self, peer): peerExists = False for idx, aPeer in enumerate(self._activePeers): if aPeer._guid == peer._guid or aPeer._pub == peer._pub or aPeer._address == peer._address: self._log.info('guids or pubkey match') peerExists = True if peer._pub and aPeer._pub == '': self._log.info('no pubkey') aPeer._pub = peer._pub self._activePeers[idx] = aPeer if not peerExists: self._log.info('Adding crypto peer %s' % peer._pub) self._routingTable.addContact(peer) self._activePeers.append(peer) # Return data array with details from the crypto file # TODO: This needs to be protected better; potentially encrypted file or DB def load_crypto_details(self, store_file): with open(store_file) as f: data = json.loads(f.read()) assert "nickname" in data assert "secret" in data assert "pubkey" in data assert len(data["secret"]) == 2 * 32 assert len(data["pubkey"]) == 2 * 33 return data["nickname"], data["secret"].decode("hex"), \ data["pubkey"].decode("hex") def get_profile(self): peers = {} self.settings = self._db.settings.find_one( {'id': "%s" % self._market_id}) for uri, peer in self._peers.iteritems(): if peer._pub: peers[uri] = peer._pub.encode('hex') return { 'uri': self._uri, 'pub': self._myself.get_pubkey().encode('hex'), 'nickname': self.nickname, 'peers': peers } def respond_pubkey_if_mine(self, nickname, ident_pubkey): if ident_pubkey != self.pubkey: self._log.info("Public key does not match your identity") return # Return signed pubkey pubkey = self._myself.pubkey ec_key = obelisk.EllipticCurveKey() ec_key.set_secret(self.secret) digest = obelisk.Hash(pubkey) signature = ec_key.sign(digest) # Send array of nickname, pubkey, signature to transport layer self.send(proto_response_pubkey(nickname, pubkey, signature)) def pubkey_exists(self, pub): for uri, peer in self._peers.iteritems(): self._log.info('PEER: %s Pub: %s' % (peer._pub.encode('hex'), pub.encode('hex'))) if peer._pub.encode('hex') == pub.encode('hex'): return True return False def create_peer(self, uri, pub, node_guid): if pub: pub = pub.decode('hex') # Create the peer if public key is not already in the peer list # if not self.pubkey_exists(pub): self._peers[uri] = CryptoPeerConnection(self, uri, pub, node_guid) # Call 'peer' callbacks on listeners self.trigger_callbacks('peer', self._peers[uri]) # else: # print 'Pub Key is already in peer list' def send_enc(self, uri, msg): peer = self._peers[uri] pub = peer._pub # Now send a hello message to the peer if pub: self._log.info("Sending encrypted [%s] message to %s" % (msg['type'], uri)) peer.send(msg) else: # Will send clear profile on initial if no pub self._log.info("Sending unencrypted [%s] message to %s" % (msg['type'], uri)) self._peers[uri].send_raw(json.dumps(msg)) def init_peer(self, msg): uri = msg['uri'] pub = msg.get('pub') nickname = msg.get('nickname') msg_type = msg.get('type') guid = msg['guid'] if not self.valid_peer_uri(uri): self._log.error("Invalid Peer: %s " % uri) return if uri not in self._peers: # Unknown peer self._log.info('Add New Peer: %s' % uri) self.create_peer(uri, pub, guid) if not msg_type: self.send_enc(uri, hello_request(self.get_profile())) elif msg_type == 'hello_request': self.send_enc(uri, hello_response(self.get_profile())) else: # Known peer if pub: # test if we have to update the pubkey if not self._peers[uri]._pub: self._log.info("Setting public key for seed node") self._peers[uri]._pub = pub.decode('hex') self.trigger_callbacks('peer', self._peers[uri]) if (self._peers[uri]._pub != pub.decode('hex')): self._log.info("Updating public key for node") self._peers[uri]._nickname = nickname self._peers[uri]._pub = pub.decode('hex') self.trigger_callbacks('peer', self._peers[uri]) if msg_type == 'hello_request': # reply only if necessary self.send_enc(uri, hello_response(self.get_profile())) def on_message(self, msg): # here goes the application callbacks # we get a "clean" msg which is a dict holding whatever self._log.info("Data received: %s" % msg) pubkey = msg.get('pubkey') uri = msg.get('uri') ip = urlparse(uri).hostname port = urlparse(uri).port guid = msg.get('senderGUID') new_peer = CryptoPeerConnection(self, uri, pubkey, guid) self._dht.add_active_peer(new_peer) self._dht.add_known_node((ip, port, guid)) self.trigger_callbacks(msg['type'], msg) def on_raw_message(self, serialized): try: # Try to deserialize cleartext message msg = json.loads(serialized) self._log.info("Message Received [%s]" % msg.get('type', 'unknown')) except ValueError: try: # Encrypted? try: msg = self._myself.decrypt(serialized) msg = json.loads(msg) self._log.info("Decrypted Message [%s]" % msg.get('type', 'unknown')) except: self._log.error("Could not decrypt message: %s" % msg) return except: self._log.info("Bad Message: %s..." % self._myself.decrypt(serialized)) traceback.print_exc() return if msg.get('type') != '': msg_type = msg.get('type') msg_uri = msg.get('uri') msg_guid = msg.get('guid') # # if msg_type.startswith('hello') and msg_uri: # self.init_peer(msg) # for uri, pub in msg.get('peers', {}).iteritems(): # # Do not add yourself as a peer # if uri != self._uri: # self.init_peer({'uri': uri, 'pub': pub}) # self._log.info("Update peer table [%s peers]" % len(self._peers)) # # elif msg_type == 'goodbye' and msg_uri: # self._log.info("Received goodbye from %s" % msg_uri) # self.remove_peer(msg_uri) # # else: self.on_message(msg)