def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password_encrypted = self.encrypt(password.encode("utf-8")) # encode with base64 password_base64 = base64.encodestring(password_encrypted).decode() # ensure the file exists self._ensure_file_path() # load the keyring from the disk config = configparser.RawConfigParser() config.read(self.file_path) # update the keyring with the password if not config.has_section(service): config.add_section(service) config.set(service, username, password_base64) # save the keyring back to the file config_file = open(self.file_path, "w") try: config.write(config_file) finally: config_file.close()
def set_password(self, service, username, password): """Write the password in the file. """ self._relocate_file() service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password_encrypted = self.encrypt(password.encode('utf-8')) # load the password from the disk config = ConfigParser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # encode with base64 password_base64 = base64.encodestring(password_encrypted).decode() # write the modification if not config.has_section(service): config.add_section(service) config.set(service, username, password_base64) # ensure the storage path exists if not os.path.isdir(os.path.dirname(self.file_path)): os.makedirs(os.path.dirname(self.file_path)) config_file = open(self.file_path,'w') config.write(config_file)
def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password_encrypted = self.encrypt(password.encode('utf-8')) # encode with base64 password_base64 = base64.encodestring(password_encrypted).decode() # ensure the file exists self._ensure_file_path() # load the keyring from the disk config = configparser.RawConfigParser() config.read(self.file_path) # update the keyring with the password if not config.has_section(service): config.add_section(service) config.set(service, username, password_base64) # save the keyring back to the file with open(self.file_path, 'w') as config_file: config.write(config_file)
def get_password(self, service, username): """ Read the password from the file. """ assoc = self._generate_assoc(service, username) service = escape_for_ini(service) username = escape_for_ini(username) # load the passwords from the file config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # fetch the password try: password_base64 = config.get(service, username).encode() # decode with base64 password_encrypted = decodebytes(password_base64) # decrypt the password with associated data try: password = self.decrypt(password_encrypted, assoc).decode('utf-8') except ValueError: # decrypt the password without associated data password = self.decrypt(password_encrypted).decode('utf-8') except (configparser.NoOptionError, configparser.NoSectionError): password = None return password
def test_scheme(self): self.assertTrue(self.keyring.scheme is not None) # generate keyring self.keyring.set_password('system', 'user', 'password') config = self.get_config() krsetting = escape_for_ini('keyring-setting') scheme = escape_for_ini('scheme') defscheme = '[Argon2] AES128.GCM' # default scheme match if self.keyring.aesmode == 'GCM': self.assertTrue(config.get(krsetting, scheme) == defscheme) # invalid AES mode config.set(krsetting, scheme, defscheme.replace('GCM', 'XXX')) with pytest.raises(ValueError): self.keyring._check_scheme(config) # compatibility with former scheme format config.set(krsetting, scheme, 'PyCryptodome ' + defscheme) self.assertTrue(self.keyring._check_scheme(config) == None) # test with invalid KDF config.set(krsetting, scheme, defscheme.replace('Argon2', 'PBKDF2')) with pytest.raises(ValueError): self.keyring._check_scheme(config) # a missing scheme is valid config.remove_option(krsetting, scheme) self.save_config(config) self.assertTrue(self.keyring._check_file() == True) with pytest.raises(AttributeError): self.keyring._check_scheme(config)
def _check_scheme(self, config): """ check for a valid scheme raise AttributeError if missing raise ValueError if not valid """ try: scheme = config.get( escape_for_ini('keyring-setting'), escape_for_ini('scheme'), ) except (configparser.NoSectionError, configparser.NoOptionError): raise AttributeError("Encryption scheme missing") # extract AES mode aesmode = scheme[-3:] if aesmode not in self._get_mode(): raise ValueError("Encryption scheme invalid: %s" % (aesmode)) # setup AES mode self.aesmode = aesmode # remove pointless crypto module name if scheme.startswith('PyCryptodome '): scheme = scheme[13:] # check other scheme properties if scheme != self.scheme: raise ValueError("Encryption scheme mismatch " "(exp.: %s, found: %s)" % (self.scheme, scheme))
def delete_password(self, service, username): service = escape_for_ini(service) username = escape_for_ini(username) try: self.config.remove_option(service, username) except configparser.NoSectionError: raise errors.PasswordDeleteError('Password not found') config_file = UnicodeWriterAdapter(self._open('w')) self.config.write(config_file) config_file.close()
def set_password(self, service, username, password): """Write the password in the file. """ assoc = (escape_for_ini(service) + '\0' + escape_for_ini(username)).encode() # encrypt the password password_encrypted = self.encrypt(password.encode('utf-8'), assoc) # encode with base64 and add line break to untangle config file password_base64 = '\n' + encodebytes(password_encrypted).decode() self._write_config_value(service, username, password_base64)
def _check_file(self): """ Check if the file exists and has the expected password reference. """ if not os.path.exists(self.file_path): return False self._migrate() config = configparser.RawConfigParser() config.read(self.file_path) try: config.get(escape_for_ini("keyring-setting"), escape_for_ini("password reference")) except (configparser.NoSectionError, configparser.NoOptionError): return False return True
def _check_version(self, config): """ check for a valid version an existing scheme implies an existing version as well return True, if version is valid, and False otherwise """ try: self.file_version = config.get( escape_for_ini('keyring-setting'), escape_for_ini('version'), ) except (configparser.NoSectionError, configparser.NoOptionError): return False return True
def delete_password(self, service, username): """Delete the password for the username of the service. """ service = escape_for_ini(service) username = escape_for_ini(username) config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) try: if not config.remove_option(service, username): raise PasswordDeleteError("Password not found") except configparser.NoSectionError: raise PasswordDeleteError("Password not found") # update the file with open(self.file_path, 'w') as config_file: config.write(config_file)
def get_password(self, service, username): """Read the password from the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # fetch the password try: password_base64 = self.config.get(service, username).encode() # decode with base64 password_encrypted = base64.decodestring(password_base64) # decrypted the password password = self.decrypt(password_encrypted).decode('utf-8') except (configparser.NoOptionError, configparser.NoSectionError): password = None return password
def _check_file(self): """ Check if the file exists and has the expected password reference. """ if not os.path.exists(self.file_path): return False self._migrate() config = configparser.RawConfigParser() config.read(self.file_path) try: config.get( escape_for_ini('keyring-setting'), escape_for_ini('password reference'), ) except (configparser.NoSectionError, configparser.NoOptionError): return False return True
def get_password(self, service, username): """Read the password from the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # load the passwords from the file config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path, encoding='utf-8') # fetch the password try: password = config.get(service, username) except (configparser.NoOptionError, configparser.NoSectionError): password = None return password
def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password = password or '' password_encrypted = self.encrypt(password.encode('utf-8')) # encode with base64 password_base64 = base64.encodestring(password_encrypted).decode() # write the modification if not self.config.has_section(service): self.config.add_section(service) self.config.set(service, username, password_base64) config_file = UnicodeWriterAdapter(self._open('w')) self.config.write(config_file) config_file.close()
def _write_config_value(self, service, key, value): # ensure the file exists self._ensure_file_path() # load the keyring from the disk config = configparser.RawConfigParser() config.read(self.file_path) service = escape_for_ini(service) key = escape_for_ini(key) # update the keyring with the password if not config.has_section(service): config.add_section(service) config.set(service, key, value) # save the keyring back to the file with open(self.file_path, 'w') as config_file: config.write(config_file)
def test_version(self): # version exists self.assertTrue(self.keyring.version is not None) if not hasattr(self.keyring, '_check_version'): return # generate keyring self.keyring.set_password('system', 'user', 'password') config = self.get_config() # default version valid self.assertTrue(self.keyring._check_version(config) == True) krsetting = escape_for_ini('keyring-setting') version = escape_for_ini('version') # invalid, if version is missing config.remove_option(krsetting, version) self.save_config(config) self.assertTrue(self.keyring._check_version(config) == False)
def delete_password(self, service, username): """Delete the password for the username of the service. """ service = escape_for_ini(service) config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) if not config.remove_section(service): raise PasswordDeleteError("Password not found") # update the file config_file = open(self.file_path, "w") config.write(config_file)
def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password_encrypted = self.encrypt(password) # load the password from the disk config = ConfigParser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # encode with base64 password_base64 = password_encrypted.encode("base64") # write the modification if not config.has_section(service): config.add_section(service) config.set(service, username, password_base64) config_file = open(self.file_path,'w') config.write(config_file)
def get_password(self, service, username): """Read the password from the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # load the passwords from the file config = ConfigParser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # fetch the password try: password_base64 = config.get(service, username) # decode with base64 password_encrypted = password_base64.decode("base64") # decrypted the password password = self.decrypt(password_encrypted) except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): password = None return password
def test_file(self): if not hasattr(self.keyring, '_check_file'): return # keyring file doesn't exist yet self.assertTrue(self.keyring._check_file() == False) # generate keyring self.keyring.set_password('system', 'user', 'password') # valid keyring file exist now self.assertTrue(self.keyring._check_file() == True) # lock keyring self.keyring._lock() # fetch password from keyring self.assertTrue(self.keyring.get_password('system', 'user') == 'password') # test missing password reference config = self.get_config() krsetting = escape_for_ini('keyring-setting') pwref = escape_for_ini('password reference') #pwrefval = config.get(krsetting, pwref) config.remove_option(krsetting, pwref) self.save_config(config) self.assertTrue(self.keyring._check_file() == False)
def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password_encrypted = self.encrypt(password) # load the password from the disk config = ConfigParser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # encode with base64 password_base64 = password_encrypted.encode("base64") # write the modification if not config.has_section(service): config.add_section(service) config.set(service, username, password_base64) config_file = open(self.file_path, 'w') config.write(config_file)
def test_scheme(self): # scheme exists self.assertTrue(self.keyring.scheme is not None) if not hasattr(self.keyring, '_check_file'): return # keyring file doesn't exist yet self.assertTrue(self.keyring._check_file() == False) # generate keyring self.keyring.set_password('system', 'user', 'password') config = self.get_config() krsetting = escape_for_ini('keyring-setting') scheme = escape_for_ini('scheme') defscheme = '[PBKDF2] AES256.CFB' # default scheme match self.assertTrue(config.get(krsetting, scheme) == defscheme) # invalid AES mode config.set(krsetting, scheme, defscheme.replace('CFB', 'XXX')) with pytest.raises(ValueError): self.keyring._check_scheme(config) # compatibility with former scheme format config.set(krsetting, scheme, 'PyCrypto ' + defscheme) self.assertTrue(self.keyring._check_scheme(config) == None) # test with invalid KDF config.set(krsetting, scheme, defscheme.replace('PBKDF2', 'scrypt')) with pytest.raises(ValueError): self.keyring._check_scheme(config) # a missing scheme is valid config.remove_option(krsetting, scheme) self.save_config(config) self.assertTrue(self.keyring._check_file() == True) with pytest.raises(AttributeError): self.keyring._check_scheme(config)
def _check_scheme(self, config): """ check for a valid scheme raise ValueError otherwise raise AttributeError if missing """ try: scheme = config.get( escape_for_ini('keyring-setting'), escape_for_ini('scheme'), ) except (configparser.NoSectionError, configparser.NoOptionError): raise AttributeError("Encryption scheme missing") # remove pointless crypto module name if scheme.startswith('PyCrypto '): scheme = scheme[9:] if scheme != self.scheme: raise ValueError("Encryption scheme mismatch " "(exp.: %s, found: %s)" % (self.scheme, scheme))
def _check_file(self): """ Check if the file exists and has the expected password reference. """ if not os.path.exists(self.file_path): return False self._migrate() config = configparser.RawConfigParser() config.read(self.file_path) try: config.get( escape_for_ini('keyring-setting'), escape_for_ini('password reference'), ) except (configparser.NoSectionError, configparser.NoOptionError): return False try: self._check_scheme(config) except AttributeError: # accept a missing scheme return True return self._check_version(config)
def test_file(self): if not hasattr(self.keyring, '_check_file'): return # keyring file doesn't exist yet self.assertTrue(self.keyring._check_file() == False) # generate keyring self.keyring.set_password('system', 'user', 'password') # valid keyring file exist now self.assertTrue(self.keyring._check_file() == True) # lock keyring self.keyring._lock() # fetch password from keyring self.assertTrue( self.keyring.get_password('system', 'user') == 'password') # test missing password reference config = self.get_config() krsetting = escape_for_ini('keyring-setting') pwref = escape_for_ini('password reference') #pwrefval = config.get(krsetting, pwref) config.remove_option(krsetting, pwref) self.save_config(config) self.assertTrue(self.keyring._check_file() == False)
def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # ensure the file exists self._ensure_file_path() # load the keyring from the disk config = configparser.RawConfigParser() config.read(self.file_path) # update the keyring with the password if not config.has_section(service): config.add_section(service) config.set(service, username, password) # save the keyring back to the file config_file = codecs.open(self.file_path, 'w', 'utf-8') try: config.write(config_file) finally: config_file.close()
def _generate_assoc(self, service, username): """Generate tamper resistant bytestring of associated data """ return (escape_for_ini(service) + '\0' + escape_for_ini(username)).encode()