def _set_tag(self, tag, value): assert isinstance(tag, unicode) assert tag in [u"store", u"ignore", u"drop"] assert isinstance(value, bool) if __debug__: dprint(tag, " -> ", value) if value: if tag in self._tags: # the tag is already set return False self._tags.append(tag) else: if not tag in self._tags: # the tag isn't there to begin with return False self._tags.remove(tag) # todo: at some point we may want to optimize this. for now this is a feature that will # probably not be used often hence we leave it like this. with DispersyDatabase.get_instance() as database: tags = list(database.execute(u"SELECT key, value FROM tag")) int_tags = [0, 0] + [key for key, value in tags if value in self._tags] reduced = reduce(lambda a, b: a | b, int_tags) database.execute(u"UPDATE user SET tags = ? WHERE public_key = ?", (reduced, buffer(self._public_key),)) return True
def __init__(self, public_key, private_key=None, sync_with_database=True): assert isinstance(public_key, str) assert not public_key.startswith("-----BEGIN") assert isinstance(private_key, (type(None), str)) assert private_key is None or not private_key.startswith("-----BEGIN") assert isinstance(sync_with_database, bool) if sync_with_database: if private_key is None: # get private key database = DispersyDatabase.get_instance() try: private_key = str(database.execute(u"SELECT private_key FROM key WHERE public_key == ? LIMIT 1", (buffer(public_key),)).next()[0]) except StopIteration: pass else: # set private key database = DispersyDatabase.get_instance() database.execute(u"INSERT OR IGNORE INTO key(public_key, private_key) VALUES(?, ?)", (buffer(public_key), buffer(private_key))) if private_key is None: raise ValueError("The private key is unavailable") super(PrivateMember, self).__init__(public_key, ec_from_private_bin(private_key), sync_with_database) self._private_key = private_key
def __init__(self, mid): assert isinstance(mid, str) assert len(mid) == 20 self._mid = mid assert DispersyDatabase.has_instance(), "DispersyDatabase has not yet been created" database = DispersyDatabase.get_instance() if __debug__: # may only create a DummyMember when the public key is not available try: public_key, = database.execute( u"SELECT public_key FROM member WHERE mid = ? LIMIT 1", (buffer(mid),) ).next() assert public_key is None except StopIteration: pass try: database_id, tags = database.execute( u"SELECT id, tags FROM member WHERE mid = ? LIMIT 1", (buffer(mid),) ).next() except StopIteration: database.execute(u"INSERT INTO member (mid) VALUES (?)", (buffer(mid),)) database_id = database.last_insert_rowid tags = u"" self._database_id = database_id self._mid = mid
def update(self): """ Update tags from the database. """ execute = DispersyDatabase.get_instance().execute # set tags try: tags, = execute(u"SELECT tags FROM member WHERE id = ?", (self._database_id,)).next() except StopIteration: assert False, "should never occur" else: self._tags = [tag for tag in tags.split(",") if tag] if __debug__: assert len(set(self._tags)) == len(self._tags), ("there are duplicate tags", self._tags) for tag in self._tags: assert tag in (u"store", u"ignore", u"blacklist"), tag for community_database_id, in execute(u""" SELECT DISTINCT sync.community FROM sync JOIN meta_message ON meta_message.id = sync.meta_message WHERE meta_message.name = \"dispersy-identity\" AND sync.member = ? """, (self._database_id, )): self._communities.add(community_database_id)
def members(self): # TODO we should not just trust this information, a member can put any address in their # dispersy-identity message. The database should contain a column with a 'verified' flag. # This flag is only set when a handshake was successfull. return [Member.get_instance(str(public_key)) for public_key, in list(DispersyDatabase.get_instance().execute(u"SELECT public_key FROM user WHERE host = ? AND port = ? -- AND verified = 1", (unicode(self._address[0]), self._address[1])))]
def __init__(self, public_key, private_key = None, sync_with_database = True): if sync_with_database: if private_key is None: database = DispersyDatabase.get_instance() try: private_key = str(database.execute(u'SELECT private_key FROM key WHERE public_key == ? LIMIT 1', (buffer(public_key),)).next()[0]) except StopIteration: pass else: database = DispersyDatabase.get_instance() database.execute(u'INSERT OR IGNORE INTO key(public_key, private_key) VALUES(?, ?)', (buffer(public_key), buffer(private_key))) if private_key is None: raise ValueError('The private key is unavailable') super(PrivateMember, self).__init__(public_key, ec_from_private_bin(private_key), sync_with_database) self._private_key = private_key
def __init__(self, community, dispersy_version, community_version): """ COMMUNITY instance that this conversion belongs to. DISPERSY_VERSION is the dispersy conversion identifier (on the wire version; must be one byte). COMMUNIY_VERSION is the community conversion identifier (on the wire version; must be one byte). COMMUNIY_VERSION may not be '\x00' or '\xff'. '\x00' is used by the DefaultConversion until a proper conversion instance can be made for the Community. '\xff' is reserved for when more than one byte is needed as a version indicator. """ if __debug__: from community import Community assert isinstance(community, Community), type(community) assert isinstance(dispersy_version, str), type(dispersy_version) assert len(dispersy_version) == 1, dispersy_version assert isinstance(community_version, str), type(community_version) assert len(community_version) == 1, community_version # the dispersy database self._dispersy_database = DispersyDatabase.get_instance() # the community that this conversion belongs to. self._community = community # the messages that this instance can handle, and that this instance produces, is identified # by _prefix. self._prefix = dispersy_version + community_version + community.cid assert len(self._prefix) == 22 # when this assumption changes, we need to ensure the
def __init__(self, mid): assert isinstance(mid, str) assert len(mid) == 20 self._mid = mid assert DispersyDatabase.has_instance(), "DispersyDatabase has not yet been created" database = DispersyDatabase.get_instance() try: database_id, = database.execute(u"SELECT id FROM member WHERE mid = ? LIMIT 1", (buffer(mid),)).next() except StopIteration: database.execute(u"INSERT INTO member (mid) VALUES (?)", (buffer(mid),)) database_id = database.last_insert_rowid self._database_id = database_id self._mid = mid
def __init__(self, public_key, ec=None, sync_with_database=True): """ Create a new Member instance. Member instances must be reated or retrieved using has_instance or get_instance. PUBLIC_KEY must be a string giving the public EC key in DER format. EC is an optional EC object (given when created from private key). """ assert isinstance(public_key, str) assert not public_key.startswith("-----BEGIN") assert isinstance(sync_with_database, bool) self._public_key = public_key if ec is None: self._ec = ec_from_public_bin(public_key) else: self._ec = ec self._signature_length = ec_signature_length(self._ec) self._mid = sha1(public_key).digest() self._database_id = -1 self._address = ("", -1) self._tags = [] # sync with database if sync_with_database: if not self.update(): database = DispersyDatabase.get_instance() database.execute(u"INSERT INTO user(mid, public_key) VALUES(?, ?)", (buffer(self._mid), buffer(self._public_key))) self._database_id = database.last_insert_rowid
def __init__(self, mid): assert isinstance(mid, str) assert len(mid) == 20 self._mid = mid assert DispersyDatabase.has_instance( ), "DispersyDatabase has not yet been created" database = DispersyDatabase.get_instance() try: database_id, = database.execute( u"SELECT id FROM member WHERE mid = ? LIMIT 1", (buffer(mid), )).next() except StopIteration: database.execute(u"INSERT INTO member (mid) VALUES (?)", (buffer(mid), )) database_id = database.last_insert_rowid self._database_id = database_id self._mid = mid
def update(self): try: execute = DispersyDatabase.get_instance().execute self._database_id, host, port, tags = execute(u'SELECT id, host, port, tags FROM user WHERE public_key = ? LIMIT 1', (buffer(self._public_key),)).next() self._address = (str(host), port) self._tags = [] if tags: self._tags = list(execute(u'SELECT key FROM tag WHERE value & ?', (tags,))) return True except StopIteration: return False
def _set_tag(self, tag, value): if value: if tag in self._tags: return False self._tags.append(tag) else: if tag not in self._tags: return False self._tags.remove(tag) with DispersyDatabase.get_instance() as execute: tags = list(execute(u'SELECT key, value FROM tag')) int_tags = [0, 0] + [ key for key, value in tags if value in self._tags ] reduced = reduce(lambda a, b: a | b, int_tags) execute(u'UPDATE user SET tags = ? WHERE public_key = ?', (reduced, buffer(self._public_key))) return True
def __init__(self, public_key, ec = None, sync_with_database = True): self._public_key = public_key if ec is None: self._ec = ec_from_public_bin(public_key) else: self._ec = ec self._signature_length = ec_signature_length(self._ec) self._mid = sha1(public_key).digest() self._database_id = -1 self._address = ('', -1) self._tags = [] if sync_with_database: if not self.update(): database = DispersyDatabase.get_instance() database.execute(u'INSERT INTO user(mid, public_key) VALUES(?, ?)', (buffer(self._mid), buffer(self._public_key))) self._database_id = database.last_insert_rowid
def _set_tag(self, tag, value): assert isinstance(tag, unicode) assert tag in [u"store", u"ignore", u"blacklist"] assert isinstance(value, bool) if __debug__: dprint(tag, " -> ", value) if value: if tag in self._tags: # the tag is already set return False self._tags.append(tag) else: if not tag in self._tags: # the tag isn't there to begin with return False self._tags.remove(tag) execute = DispersyDatabase.get_instance().execute execute(u"UPDATE member SET tags = ? WHERE id = ?", (u",".join(sorted(self._tags)), self._database_id)) return True
def __init__(self, public_key, private_key=""): """ Create a new Member instance. """ assert isinstance(public_key, str) assert isinstance(private_key, str) assert ec_check_public_bin(public_key), public_key.encode("HEX") assert private_key == "" or ec_check_private_bin(private_key), private_key.encode("HEX") if not hasattr(self, "_public_key"): assert DispersyDatabase.has_instance(), "DispersyDatabase has not yet been created" database = DispersyDatabase.get_instance() try: database_id, mid, tags, private_key_from_db = database.execute( u"SELECT m.id, m.mid, m.tags, p.private_key FROM member AS m LEFT OUTER JOIN private_key AS p ON p.member = m.id WHERE m.public_key = ? LIMIT 1", (buffer(public_key),), ).next() except StopIteration: mid = sha1(public_key).digest() private_key_from_db = None try: database_id, tags = database.execute( u"SELECT id, tags FROM member WHERE mid = ? LIMIT 1", (buffer(mid),) ).next() except StopIteration: database.execute( u"INSERT INTO member (mid, public_key) VALUES (?, ?)", (buffer(mid), buffer(public_key)) ) database_id = database.last_insert_rowid tags = u"" else: database.execute( u"UPDATE member SET public_key = ? WHERE id = ?", (buffer(public_key), database_id) ) else: mid = str(mid) private_key_from_db = str(private_key_from_db) if private_key_from_db else "" assert private_key_from_db == "" or ec_check_private_bin( private_key_from_db ), private_key_from_db.encode("HEX") if private_key_from_db: private_key = private_key_from_db elif private_key: database.execute( u"INSERT INTO private_key (member, private_key) VALUES (?, ?)", (database_id, buffer(private_key)) ) self._database = database self._database_id = database_id self._mid = mid self._public_key = public_key self._private_key = private_key self._ec = ec_from_private_bin(private_key) if private_key else ec_from_public_bin(public_key) self._signature_length = ec_signature_length(self._ec) self._tags = [tag for tag in tags.split(",") if tag] self._has_identity = set() if __debug__: assert len(set(self._tags)) == len(self._tags), ("there are duplicate tags", self._tags) for tag in self._tags: assert tag in (u"store", u"ignore", u"blacklist"), tag if __debug__: dprint( "mid:", self._mid.encode("HEX"), " db:", self._database_id, " public:", bool(self._public_key), " private:", bool(self._private_key), )
def __init__(self, public_key, private_key=""): """ Create a new Member instance. """ assert isinstance(public_key, str) assert isinstance(private_key, str) assert ec_check_public_bin(public_key), public_key.encode("HEX") assert private_key == "" or ec_check_private_bin( private_key), private_key.encode("HEX") if not hasattr(self, "_public_key"): assert DispersyDatabase.has_instance( ), "DispersyDatabase has not yet been created" database = DispersyDatabase.get_instance() try: database_id, mid, tags, private_key_from_db = database.execute( u"SELECT m.id, m.mid, m.tags, p.private_key FROM member AS m LEFT OUTER JOIN private_key AS p ON p.member = m.id WHERE m.public_key = ? LIMIT 1", (buffer(public_key), )).next() except StopIteration: mid = sha1(public_key).digest() private_key_from_db = None try: database_id, tags = database.execute( u"SELECT id, tags FROM member WHERE mid = ? LIMIT 1", (buffer(mid), )).next() except StopIteration: database.execute( u"INSERT INTO member (mid, public_key) VALUES (?, ?)", (buffer(mid), buffer(public_key))) database_id = database.last_insert_rowid tags = u"" else: database.execute( u"UPDATE member SET public_key = ? WHERE id = ?", (buffer(public_key), database_id)) else: mid = str(mid) private_key_from_db = str( private_key_from_db) if private_key_from_db else "" assert private_key_from_db == "" or ec_check_private_bin( private_key_from_db), private_key_from_db.encode("HEX") if private_key_from_db: private_key = private_key_from_db elif private_key: database.execute( u"INSERT INTO private_key (member, private_key) VALUES (?, ?)", (database_id, buffer(private_key))) self._database = database self._database_id = database_id self._mid = mid self._public_key = public_key self._private_key = private_key self._ec = ec_from_private_bin( private_key) if private_key else ec_from_public_bin(public_key) self._signature_length = ec_signature_length(self._ec) self._tags = [tag for tag in tags.split(",") if tag] self._has_identity = set() if __debug__: assert len(set(self._tags)) == len( self._tags), ("there are duplicate tags", self._tags) for tag in self._tags: assert tag in (u"store", u"ignore", u"blacklist"), tag if __debug__: dprint("mid:", self._mid.encode("HEX"), " db:", self._database_id, " public:", bool(self._public_key), " private:", bool(self._private_key))
def __init__(self, public_key, private_key="", sync_with_database=True, public_key_available=True): """ Create a new Member instance. Member instances must be reated or retrieved using has_instance or get_instance. To create a Member instance we either need a public_key or a mid. If only the mid is available it must be given as the public_key parameter and public_key_available must be False. In this case the member will be unable to verify or sign data. Also not that it is possible, however unlikely, that someone is able to find another member with the same mid. This will cause conflicts until the public_key is available. """ assert isinstance(public_key, str) assert isinstance(private_key, str) assert isinstance(sync_with_database, bool) assert isinstance(public_key_available, bool) assert (public_key_available and len(public_key) > 0 and not public_key.startswith("-----BEGIN")) or \ (not public_key_available and len(public_key) == 20), (len(public_key), public_key_available, public_key.encode("HEX")) assert (public_key_available and len(private_key) > 0 and not private_key.startswith("-----BEGIN")) or len(private_key) == 0 assert DispersyDatabase.has_instance(), "DispersyDatabase has not yet been created" database = DispersyDatabase.get_instance() if hasattr(self, "_database_id"): # # singleton already exists. we may have received a public or private key now, so update # those in the database is needed # if __debug__: dprint("continue with existing singleton", force=1) if public_key_available: assert self._public_key == "" or self._public_key == public_key assert self._private_key == "" or self._private_key == private_key if not self._public_key: assert public_key assert ec_check_public_bin(public_key), public_key.encode("HEX") self._public_key = public_key if sync_with_database: database.execute(u"UPDATE member SET public_key = ? WHERE id = ?", (buffer(public_key), self._database_id)) if not self._private_key and private_key: assert private_key assert ec_check_private_bin(private_key), private_key.encode("HEX") self._private_key = private_key if sync_with_database: database.execute(u"UPDATE private_key SET private_key = ? WHERE member = ?", (buffer(private_key), self._database_id)) self._ec = ec_from_private_bin(self._private_key) if self._private_key else ec_from_public_bin(self._public_key) self._signature_length = ec_signature_length(self._ec) else: # we have nothing new pass else: # # singleton did not exist. we make a new one # if public_key_available: assert public_key assert ec_check_public_bin(public_key), public_key.encode("HEX") assert not private_key or ec_check_private_bin(private_key), private_key.encode("HEX") self._public_key = public_key self._private_key = private_key self._mid = sha1(public_key).digest() self._database_id = -1 self._communities = set() self._tags = [] if sync_with_database: try: self._database_id, private_key = database.execute(u"SELECT m.id, p.private_key FROM member AS m LEFT OUTER JOIN private_key AS p ON p.member = m.id WHERE m.public_key = ? LIMIT 1", (buffer(self._public_key),)).next() except StopIteration: # TODO check if there is a member already in the database where we only had # the MID database.execute(u"INSERT INTO member(mid, public_key) VALUES(?, ?)", (buffer(self._mid), buffer(self._public_key))) self._database_id = database.last_insert_rowid if self._private_key: database.execute(u"INSERT INTO private_key(member, private_key) VALUES(?, ?)", (self._database_id, buffer(self._private_key))) else: if not self._private_key and private_key: self._private_key = str(private_key) self._ec = ec_from_private_bin(self._private_key) if self._private_key else ec_from_public_bin(self._public_key) self._signature_length = ec_signature_length(self._ec) else: assert len(public_key) == 20, public_key.encode("HEX") self._public_key = "" self._private_key = "" self._mid = public_key self._database_id = -1 self._communities = set() self._tags = [] if sync_with_database: try: # # TODO do something smart to select the right mid (multiple can exist...) self._database_id, = database.execute(u"SELECT id FROM member WHERE mid = ? LIMIT 1", (buffer(self._mid),)).next() except StopIteration: database.execute(u"INSERT INTO member(mid) VALUES(?)", (buffer(self._mid),)) self._database_id = database.last_insert_rowid self._ec = None self._signature_length = 0 if sync_with_database: self.update() if __debug__: dprint("mid:", self._mid.encode("HEX"), " db:", self._database_id, " public:", bool(self._public_key), " private:", bool(self._private_key), " from-public:", public_key_available)