wauth package

Subpackages

Submodules

Module contents

WAuth - Local encrypted secret management library.

Provides a simple interface to store and retrieve secrets encrypted with Fernet (AES-256), backed by a SQLite database via wsqlite.

Example

>>> from wauth import WAuth
>>> auth = WAuth()
>>> auth.set("API_KEY", "secret-value")
>>> auth.get("API_KEY")
'secret-value'
class wauth.WAuth(db_path='~/.wisrovi/wauth.db', custom_key=None, config_path=None, verbose=False)[source]

Bases: object

Main interface for managing encrypted secrets.

Provides methods for storing, retrieving, deleting, rotating, backing up, and restoring encrypted secrets.

Parameters:
  • db_path (str) – Path to the SQLite database file. Defaults to ~/.wisrovi/wauth.db.

  • custom_key (str | None) – Optional custom encryption key string.

  • config_path (str | None) – Optional path to a TOML configuration file.

  • verbose (bool) – When True, emit debug/info/warning logs via loguru. Defaults to False.

Example

>>> auth = WAuth()
>>> auth.set("MY_KEY", "my-secret")
>>> value = auth.get("MY_KEY")
__init__(db_path='~/.wisrovi/wauth.db', custom_key=None, config_path=None, verbose=False)[source]
set(key, value, ttl=None)[source]

Store an encrypted text secret.

Parameters:
  • key (str) – Unique identifier for the secret.

  • value (str) – Plaintext value to encrypt and store.

  • ttl (float | None) – Optional time-to-live in seconds. None means no expiration.

set_file(key, path, ttl=None)[source]

Store an encrypted file (e.g., .pem, .key).

Parameters:
  • key (str) – Unique identifier for the file secret.

  • path (str) – Filesystem path to the file to encrypt and store.

  • ttl (float | None) – Optional time-to-live in seconds.

get(key)[source]

Retrieve a decrypted secret.

Parameters:

key (str) – Unique identifier for the secret.

Returns:

Decrypted secret as str for text type or bytes for file type. Returns None if the key does not exist.

Return type:

str | bytes | None

encrypt(data)[source]

Encrypt data without storing it in the vault.

Parameters:

data (str | bytes | dict | list) – Plaintext string, bytes, dictionary, or list to encrypt. Dictionaries and lists are automatically serialized to JSON.

Returns:

Base64-encoded Fernet token.

Return type:

str

decrypt(token)[source]

Decrypt a Fernet token without retrieving it from the vault.

Parameters:

token (str) – Base64-encoded Fernet token.

Returns:

Decrypted plaintext. Returns a dict or list if it was a JSON string, a str if it can be decoded as UTF-8, otherwise bytes.

Return type:

str | bytes | dict | list

valid(key, value_to_check)[source]

Verify if a stored secret matches the provided value.

This method is more secure than get() when you only need to check a secret’s value, as the secret never leaves the library.

Parameters:
  • key (str) – Unique identifier for the secret.

  • value_to_check (str) – Value to compare against the stored secret.

Returns:

True if the stored secret matches value_to_check.

Return type:

bool

Example

>>> auth = WAuth()
>>> auth.set("API_KEY", "secret123")
>>> auth.valid("API_KEY", "secret123")
True
>>> auth.valid("API_KEY", "wrong")
False
delete(key)[source]

Delete a secret from the vault.

Parameters:

key (str) – Unique identifier for the secret to remove.

Raises:

WAuthError – If the key does not exist.

list_keys()[source]

List all secret keys stored in the vault.

Returns:

A list of all key names.

Return type:

list[str]

rotate_key(new_custom_key)[source]

Rotate the encryption key and re-encrypt all existing secrets.

Decrypts every secret with the current key, then re-encrypts and stores them with the new key. The internal engine is swapped only if all migrations succeed.

Parameters:

new_custom_key (str) – The new custom key to use for encryption.

Returns:

A dict mapping each key to True (success) or False (failure).

Return type:

dict[str, bool]

backup(output_path)[source]

Export all secrets to an encrypted backup file.

Creates a JSON file containing all secret keys and their encrypted values (still encrypted — the backup itself is not decrypted).

Parameters:

output_path (str) – Destination path for the backup file.

Returns:

The absolute path of the created backup file.

Raises:

BackupError – If the export fails.

Return type:

str

restore(backup_path)[source]

Restore secrets from an encrypted backup file.

Reads a backup file created by backup() and re-stores all encrypted secrets into the current vault.

Parameters:

backup_path (str) – Path to the backup file.

Returns:

The number of secrets restored.

Raises:

RestoreError – If the file cannot be read or parsed.

Return type:

int

async async_set(key, value, ttl=None)[source]

Async variant of set().

Runs the synchronous set in a thread pool to avoid blocking the event loop during I/O-bound database writes.

Parameters:
  • key (str) – Unique identifier for the secret.

  • value (str) – Plaintext value to encrypt and store.

  • ttl (float | None) – Optional time-to-live in seconds.

async async_get(key)[source]

Async variant of get().

Parameters:

key (str) – Unique identifier for the secret.

Returns:

Decrypted secret or None.

Return type:

str | bytes | None

async async_valid(key, value_to_check)[source]

Async variant of valid().

Parameters:
  • key (str) – Unique identifier for the secret.

  • value_to_check (str) – Value to compare against stored secret.

Returns:

True if the stored secret matches value_to_check.

Return type:

bool

async async_delete(key)[source]

Async variant of delete().

Parameters:

key (str) – Unique identifier for the secret to remove.

async async_backup(output_path)[source]

Async variant of backup().

Parameters:

output_path (str) – Destination path for the backup file.

Returns:

Absolute path of the created backup file.

Return type:

str

async async_restore(backup_path)[source]

Async variant of restore().

Parameters:

backup_path (str) – Path to the backup file.

Returns:

Number of secrets restored.

Return type:

int

class wauth.CryptoEngine(custom_key=None)[source]

Bases: object

Handles encryption and decryption using Fernet (AES-128-CBC).

The encryption key is derived from a machine-specific identifier, meaning data encrypted on one machine can only be decrypted on that same machine.

Parameters:

custom_key (str | None) – Optional custom encryption key string. If provided, it is hashed with SHA-256 to produce a deterministic 32-byte key. If None, the key is derived from the machine identifier.

__init__(custom_key=None)[source]
encrypt(data)[source]

Encrypt raw bytes into a Fernet token.

Parameters:

data (bytes) – Plaintext data to encrypt.

Returns:

Base64-encoded Fernet token as a string.

Return type:

str

decrypt(token)[source]

Decrypt a Fernet token back to raw bytes.

Parameters:

token (str) – Base64-encoded Fernet token.

Returns:

Decrypted plaintext as bytes.

Raises:

DecryptionError – If the token is invalid, tampered, or encrypted with a different key.

Return type:

bytes

class wauth.LocalDriver(custom_key=None)[source]

Bases: object

Driver that stores secrets locally using Fernet encryption.

Combines the cryptographic engine with the SQLite-backed vault for persistent, machine-locked secret storage.

Parameters:

custom_key (str | None) – Optional custom encryption key string.

__init__(custom_key=None)[source]
set_secret(key, value, ttl=None)[source]

Encrypt and store a text secret.

Parameters:
  • key (str) – Unique identifier for the secret.

  • value (str) – Plaintext value to encrypt.

  • ttl (float | None) – Optional time-to-live in seconds. None means no expiration.

set_file(key, file_path, ttl=None)[source]

Encrypt and store a file’s contents.

Parameters:
  • key (str) – Unique identifier for the file secret.

  • file_path (str) – Path to the file to encrypt and store.

  • ttl (float | None) – Optional time-to-live in seconds.

get_secret(key)[source]

Retrieve and decrypt a secret by its key.

Parameters:

key (str) – Unique identifier for the secret.

Returns:

Decrypted secret as str for text type or bytes for file type. Returns None if the key does not exist.

Return type:

str | bytes | None

delete_secret(key)[source]

Delete a secret from the vault.

Parameters:

key (str) – Unique identifier for the secret to remove.

Raises:

KeyNotFoundError – If the key does not exist.

list_keys()[source]

List all secret keys stored in the vault.

Returns:

A list of all key names.

Return type:

list[str]

rotate_key(new_custom_key, keys_to_migrate=None)[source]

Rotate the encryption key and re-encrypt existing secrets.

Creates a new CryptoEngine with the provided key, decrypts all existing secrets with the current engine, and re-encrypts them with the new engine.

Parameters:
  • new_custom_key (str) – The new custom key to use for encryption.

  • keys_to_migrate (list[str] | None) – Specific keys to migrate. If None, all keys in the vault are migrated.

Returns:

A dictionary mapping each key to a boolean indicating success (True) or failure (False).

Return type:

dict[str, bool]

valid_secret(key, value_to_check)[source]

Verify if stored secret matches provided value without exposing it.

Unlike get_secret(), this method never returns the decrypted secret. Uses constant-time comparison to prevent timing attacks.

Parameters:
  • key (str) – Unique identifier for the secret.

  • value_to_check (str) – Plaintext value to compare against stored secret.

Returns:

True if values match, False otherwise (or if key doesn’t exist).

Return type:

bool

class wauth.SecretModel(*, key, value, type='text', created_at=0.0, updated_at=0.0, ttl=None)[source]

Bases: BaseModel

Pydantic model representing a stored secret.

Variables:
  • key (str) – Primary key — unique name of the secret.

  • value (str) – Encrypted ciphertext of the secret.

  • type (str) – Secret type, either "text" or "file".

  • created_at (float) – Unix timestamp when the secret was first stored.

  • updated_at (float) – Unix timestamp of the last modification.

  • ttl (float | None) – Optional time-to-live in seconds. None means no expiration.

key: str
value: str
type: str
created_at: float
updated_at: float
ttl: float | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class wauth.Vault(db_path='~/.wisrovi/wauth.db')[source]

Bases: object

Encrypted secret storage backed by a SQLite database.

Parameters:

db_path (str) – Path to the SQLite database file. Defaults to ~/.wisrovi/wauth.db.

__init__(db_path='~/.wisrovi/wauth.db')[source]
db_path: str
db: WSQLite
save(key, encrypted_value, val_type='text', ttl=None)[source]

Save or update an encrypted secret in the vault.

Uses INSERT OR REPLACE semantics to upsert the secret by key. Timestamps are automatically managed.

Parameters:
  • key (str) – Unique identifier for the secret.

  • encrypted_value (str) – Fernet-encrypted ciphertext string.

  • val_type (str) – Secret type — "text" or "file".

  • ttl (float | None) – Optional time-to-live in seconds.

get(key)[source]

Retrieve an encrypted secret by its key.

Parameters:

key (str) – Unique identifier for the secret.

Returns:

A tuple of (encrypted_value, type). Returns (None, None) if the key does not exist.

Return type:

Tuple[str | None, str | None]

delete(key)[source]

Delete a secret from the vault.

Parameters:

key (str) – Unique identifier for the secret to remove.

Raises:
list_keys()[source]

List all secret keys stored in the vault.

Returns:

A list of all key names.

Return type:

list[str]

count()[source]

Return the number of secrets stored in the vault.

Returns:

Total number of secrets.

Return type:

int

wauth.set(key, value, ttl=None)[source]

Store an encrypted text secret (functional API).

Parameters:
  • key (str) – Unique identifier for the secret.

  • value (str) – Plaintext value to encrypt and store.

  • ttl (float | None) – Optional time-to-live in seconds.

wauth.set_file(key, path, ttl=None)[source]

Store an encrypted file (functional API).

Parameters:
  • key (str) – Unique identifier for the file secret.

  • path (str) – Filesystem path to the file to encrypt and store.

  • ttl (float | None) – Optional time-to-live in seconds.

wauth.get(key)[source]

Retrieve a decrypted secret (functional API).

Parameters:

key (str) – Unique identifier for the secret.

Returns:

Decrypted secret as str for text type or bytes for file type. Returns None if the key does not exist.

Return type:

str | bytes | None

wauth.delete(key)[source]

Delete a secret (functional API).

Parameters:

key (str) – Unique identifier for the secret to remove.

Raises:

WAuthError – If the key does not exist.

wauth.list_keys()[source]

List all secret keys (functional API).

Returns:

A list of all key names.

Return type:

list[str]

wauth.encrypt(data)[source]

Encrypt data without storing it in the vault (functional API).

Parameters:

data (str | bytes) – Plaintext string or bytes to encrypt.

Returns:

Base64-encoded Fernet token.

Return type:

str

wauth.decrypt(token)[source]

Decrypt a Fernet token (functional API).

Parameters:

token (str) – Base64-encoded Fernet token.

Returns:

Decrypted plaintext.

Return type:

str | bytes

exception wauth.WAuthError[source]

Bases: Exception

Base exception for all WAuth-related errors.

All custom exceptions inherit from this class, allowing callers to catch any WAuth-specific error with a single except clause.

Example

>>> try:
...     auth.get("NONEXISTENT")
... except WAuthError as exc:
...     print(f"WAuth error: {exc}")
wauth.set_verbose(enabled)[source]

Enable or disable loguru output across the entire WAuth library.

When verbose is False (the default), all debug, info, and warning messages are suppressed. Errors are always logged.

Parameters:

enabled (bool) – Whether to enable verbose logging.

wauth.get_verbose()[source]

Return the current verbose state.

Returns:

True if verbose logging is enabled.

Return type:

bool