def test_signed_key(self): try: bpio.rmdir_recursive('/tmp/.bitdust_test_signed_key') except Exception: pass lg.set_debug_level(30) settings.init(base_dir='/tmp/.bitdust_test_signed_key') self.my_current_key = None try: os.makedirs('/tmp/.bitdust_test_signed_key/metadata/') except: pass fout = open('/tmp/_some_priv_key', 'w') fout.write(_some_priv_key) fout.close() fout = open(settings.LocalIdentityFilename(), 'w') fout.write(_some_identity_xml) fout.close() self.assertTrue(key.LoadMyKey(keyfilename='/tmp/_some_priv_key')) self.assertTrue(my_id.loadLocalIdentity()) key_id = '[email protected]_8084' my_keys.erase_key(key_id, keys_folder='/tmp/') my_keys.register_key(key_id, _sample_private_key, keys_folder='/tmp/') is_valid = my_keys.validate_key(my_keys.key_obj(key_id)) self.assertTrue(is_valid) my_keys.sign_key(key_id) signed_key_info = my_keys.get_key_info(key_id, include_private=True, include_signature=True) self.assertTrue(my_keys.verify_key_info_signature(signed_key_info)) key.ForgetMyKey() my_id.forgetLocalIdentity() settings.shutdown() os.remove('/tmp/_some_priv_key') bpio.rmdir_recursive('/tmp/.bitdust_test_signed_key')
def on_key_received(newpacket, info, status, error_message): """ Callback will be executed when I receive a new key from one remote user. """ block = encrypted.Unserialize(newpacket.Payload) if block is None: lg.err('failed reading key info from %s' % newpacket.RemoteID) return False try: key_data = block.Data() key_json = serialization.BytesToDict(key_data, keys_to_text=True, values_to_text=True) key_id = key_json['key_id'] key_label = key_json.get('label', '') key_id, key_object = my_keys.read_key_info(key_json) if key_object.isSigned(): if not my_keys.verify_key_info_signature(key_json): raise Exception('key signature verification failed') if key_object.isPublic(): # received key is a public key if my_keys.is_key_registered(key_id): # but we already have a key with that ID if my_keys.is_key_private(key_id): # we should not overwrite existing private key raise Exception('private key already registered') if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): # and we should not overwrite existing public key as well raise Exception('another public key already registered with that ID and it is not matching') p2p_service.SendAck(newpacket) lg.warn('received existing public key: %s, skip' % key_id) return True if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') else: lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) if _Debug: lg.info('received and stored locally a new key %s, include_private=%s' % (key_id, key_json.get('include_private'))) return True # received key is a private key if my_keys.is_key_registered(key_id): # check if we already have that key if my_keys.is_key_private(key_id): # we have already private key with same ID!!! if my_keys.get_private_key_raw(key_id) != key_object.toPrivateString(): # and this is a new private key : we should not overwrite! raise Exception('private key already registered and it is not matching') # this is the same private key p2p_service.SendAck(newpacket) lg.warn('received existing private key: %s, skip' % key_id) return True # but we have a public key with same ID already if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): # and we should not overwrite existing public key as well raise Exception('another public key already registered with that ID and it is not matching with private key') lg.info('erasing public key %s' % key_id) my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True # no private key with given ID was registered if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True except Exception as exc: lg.exc() p2p_service.SendFail(newpacket, strng.to_text(exc)) return False
def on_key_received(newpacket, info, status, error_message): """ Callback will be executed when I receive a new key from one remote user. """ block = encrypted.Unserialize(newpacket.Payload) if block is None: lg.err('failed reading key info from %s' % newpacket.RemoteID) return False try: key_data = block.Data() key_json = serialization.BytesToDict(key_data, keys_to_text=True, values_to_text=True) # key_id = strng.to_text(key_json['key_id']) key_label = strng.to_text(key_json.get('label', '')) key_id, key_object = my_keys.read_key_info(key_json) if key_object.isSigned(): if not my_keys.verify_key_info_signature(key_json): raise Exception('received key signature verification failed: %r' % key_json) # TODO: must also compare "signature_pubkey" with pub key of the creator of the key! if key_object.isPublic(): # received key is a public key if my_keys.is_key_registered(key_id): # but we already have a key with that ID if my_keys.is_key_private(key_id): # we should not overwrite existing private key # TODO: check other scenarios raise Exception('private key already registered with %r' % key_id) if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') else: lg.info('replaced existing key %s, is_public=%s' % (key_id, key_object.isPublic())) # normally should not overwrite existing public key # TODO: look more if need to add some extra checks # for example need to be able to overwrite or erase remotely some keys to cleanup # raise Exception('another public key already registered with %r and new key is not matching' % key_id) p2p_service.SendAck(newpacket) lg.warn('received existing public key: %s, skip' % key_id) return True if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') else: lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) if _Debug: lg.info('received and stored locally a new key %s, include_private=%s' % (key_id, key_json.get('include_private'))) return True # received key is a private key if my_keys.is_key_registered(key_id): # check if we already have that key if my_keys.is_key_private(key_id): # we have already private key with same ID!!! if my_keys.get_private_key_raw(key_id) != key_object.toPrivateString(): # and this is a new private key : we should not overwrite! raise Exception('private key already registered and it is not matching with received copy') # this is the same private key p2p_service.SendAck(newpacket) lg.warn('received again an exact copy of already existing private key: %s, skip' % key_id) return True # but we have a public key with same ID already # if my_keys.get_public_key_raw(key_id) != key_object.toPublicString(): # # and we should not overwrite existing public key as well # raise Exception('another public key already registered with that ID and it is not matching with private key') lg.info('erasing public key %s' % key_id) my_keys.erase_key(key_id) if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True # no private key with given ID was registered if not my_keys.register_key(key_id, key_object, label=key_label): raise Exception('key register failed') lg.info('added new key %s, is_public=%s' % (key_id, key_object.isPublic())) p2p_service.SendAck(newpacket) return True except Exception as exc: lg.exc() p2p_service.SendFail(newpacket, strng.to_text(exc)) return False
def transfer_key(key_id, trusted_idurl, include_private=False, include_signature=False, timeout=10, result=None): """ Actually sending given key to remote user. """ if _Debug: lg.out(_DebugLevel, 'key_ring.transfer_key %s -> %s' % (key_id, trusted_idurl)) key_id = my_keys.latest_key_id(key_id) if not result: result = Deferred() recipient_id_obj = identitycache.FromCache(trusted_idurl) if not recipient_id_obj: lg.warn('not found "%s" in identity cache' % trusted_idurl) result.errback(Exception('not found "%s" in identity cache' % trusted_idurl)) return result key_alias, creator_idurl = my_keys.split_key_id(key_id) if not key_alias or not creator_idurl: lg.warn('wrong key_id') result.errback(Exception('wrong key_id')) return result if not my_keys.is_key_registered(key_id): lg.warn('unknown key: "%s"' % key_id) result.errback(Exception('unknown key: "%s"' % key_id)) return result key_object = my_keys.key_obj(key_id) try: key_json = my_keys.make_key_info( key_object, key_id=key_id, include_private=include_private, generate_signature=include_signature, ) except Exception as exc: lg.exc() result.errback(exc) return result if include_signature and not my_keys.verify_key_info_signature(key_json): lg.err('signature verification failed after making key info: %r' % key_json) result.errback(Exception('signature verification failed after making key info: "%s"' % key_id)) return result if _Debug: lg.args(_DebugLevel, key_json=key_json) key_data = serialization.DictToBytes(key_json, values_to_text=True) block = encrypted.Block( BackupID=key_id, Data=key_data, SessionKey=key.NewSessionKey(session_key_type=key.SessionKeyType()), SessionKeyType=key.SessionKeyType(), # encrypt data using public key of recipient EncryptKey=lambda inp: recipient_id_obj.encrypt(inp), ) encrypted_key_data = block.Serialize() p2p_service.SendKey( remote_idurl=recipient_id_obj.getIDURL(), encrypted_key_data=encrypted_key_data, packet_id=key_id, callbacks={ commands.Ack(): lambda response, info: _on_transfer_key_response(response, info, key_id, result), commands.Fail(): lambda response, info: _on_transfer_key_response(response, info, key_id, result), None: lambda pkt_out: _on_transfer_key_response(None, None, key_id, result), }, timeout=timeout, ) return result