def open_safe(given_pw: str, dir): # 0: read password file expected_pw = HashedPassword.read_from_file( join(dir, consts.SAFE_PASSWORD_FILE)) # 1: verify password if not hash_utils.verify_password(given_pw, expected_pw): raise Exception("incorrect password") # 2: get key_hash mkey_hashed = hash_utils.hash_for_key(given_pw, expected_pw.kdf_params) mkey = Key(conversions.string_to_bytes(mkey_hashed.hash)) given_pw = "" # 4: open encyrpted key file with open(join(dir, consts.SAFE_KEY_FILE)) as key_file: encrypted_key = key_file.read() # 5: decyrpt derived key dkey_string = cipher_utils.decrypt_string(encrypted_key, mkey) dkey = Key(conversions.string_to_bytes(dkey_string)) mkey_hashed.destroy() mkey.destroy() # 6: decrpyt file names to get note names notes = Note.load_from_dir(dir, dkey) # 7: return new safe with info return Safe(dir, notes, dkey)
def generate_and_encrypt(password: str, safe_dir): mkey = conversions.string_to_bytes(password) dkey_bytes = urandom(consts.MASTER_KEY_LENGTH) dkey = conversions.bytes_to_b64string(dkey_bytes) enc_dkey = cipher_utils.encrypt_string(dkey, Key(mkey)) with open(join(safe_dir, consts.SAFE_KEY_FILE), 'w') as key_file: key_file.write(enc_dkey) return Key(conversions.string_to_bytes(dkey))
def _get_kdf_instance(kdf_params): salt = conversions.string_to_bytes(kdf_params.salt) kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=kdf_params.output_length, salt=salt, iterations=kdf_params.iterations, backend=default_backend()) return kdf
def verify_password(password: str, expected: HashedPassword): given_bytes = conversions.string_to_bytes(password) expected_bytes = conversions.encoded_string_to_bytes(expected.hash) kdf_params = expected.kdf_params first_iteration = _hash_bytes(given_bytes, kdf_params) # will raise exception if bytes don't match _verify_bytes(first_iteration, expected_bytes, kdf_params) return True
def create_verification_hash(password): kdf_params = KDFParams.default() # double hash because verification hash = _hash_bytes( _hash_bytes(conversions.string_to_bytes(password), kdf_params), kdf_params) password = "" hash = conversions.bytes_to_b64string(hash) return HashedPassword(hash, kdf_params)
def encrypt_string(plaintext: str, key): fernet_key = key.fernet_key() plaintext_bytes = conversions.string_to_bytes(plaintext) return fernet_key.encrypt(plaintext_bytes).decode()
def decrypt_string(ciphertext: str, key): fernet_key = key.fernet_key() ciphertext_bytes = conversions.string_to_bytes(ciphertext) return fernet_key.decrypt(ciphertext_bytes).decode()
def hash_for_key(password, kdf_params): hash = _hash_bytes(conversions.string_to_bytes(password), kdf_params) password = "" hash = conversions.bytes_to_b64string(hash) return HashedPassword(hash, kdf_params)