### Verify Installation Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Initialize a new project and verify the package can be imported. ```bash uv init uv add SecretsManager uv run python -c "from secrets_manager import SecretsManager; print('OK')" ``` -------------------------------- ### Clone and Setup Repository Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md Commands to clone the repository and initialize the development environment. ```bash git clone https://github.com/your-user/SecretsManager.git cd SecretsManager ``` ```bash git checkout -b feature/my-feature ``` ```bash uv sync --extra dev ``` -------------------------------- ### Install Dependencies with uv Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Install core or development dependencies using the uv package manager. ```bash # Core install uv sync # Development (pytest, mypy, etc) uv sync --extra dev ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Install additional dependencies required for development using uv sync. ```bash uv sync --extra dev ``` -------------------------------- ### Initialize SecretsManager Locally Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Example script to verify encryption and decryption functionality. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "k", "salt": "s"}}, active_version="v1", ) manager = SecretsManager(config) version, ciphertext = manager.encrypt(b"data") print(version, manager.decrypt(ciphertext)) ``` -------------------------------- ### Example Configuration with Salt Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Illustrates the structure of a SecretsConfig object with a key and salt, where the salt is provided as bytes. ```python config = SecretsConfig(keys={"v1": {"key": "k", "salt": b"my-salt"}}, active_version="v1") ``` -------------------------------- ### Commit Message Example Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md An example of a standard commit message format. ```text Add audit event metadata Include version and size in audit events for easier monitoring. ``` -------------------------------- ### Conventional Commit Examples Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md Various examples of valid conventional commit messages. ```bash feat(core): add key rotation strategy fix(config): validate salt hash length docs: update README with usage instructions refactor: simplify encryption flow chore: update project dependencies feat!: require explicit version on encrypt BREAKING CHANGE: version is now required for encrypt ``` -------------------------------- ### Quick Start: Encrypt and Decrypt Data Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Initialize SecretsManager with a configuration and perform basic encryption and decryption operations. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={ "v1": { "key": "my-secret-password", "salt": b"random-salt-value", } }, active_version="v1", ) manager = SecretsManager(config) version, ciphertext = manager.encrypt(b"sensitive data") version, plaintext = manager.decrypt(ciphertext) ``` -------------------------------- ### Install SecretsManager with uv Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Use this command to add the SecretsManager package to your project. ```bash uv add SecretsManager ``` -------------------------------- ### Key Rotation Example Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Demonstrates how to rotate encryption keys to a new version and decrypt data encrypted with older versions. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "old-password", "salt": b"old-salt"}}, active_version="v1", ) manager = SecretsManager(config) _, ciphertext_v1 = manager.encrypt(b"important data") manager.rotate_to_new_version( new_version="v2", new_key="new-password", new_salt=b"new-salt", ) _, ciphertext_v2 = manager.encrypt(b"new data") manager.decrypt(ciphertext_v1) manager.decrypt(ciphertext_v2) ``` -------------------------------- ### Audit Logging Setup Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Implement an audit callback function to log events and metadata during secrets management operations. ```python def audit_callback(event: str, metadata: dict): print(f"[AUDIT] {event}: {metadata}") config = SecretsConfig( keys={"v1": {"key": "pass", "salt": b"salt"}}, active_version="v1", audit_callback=audit_callback, ) ``` -------------------------------- ### Makefile Targets for Windows Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Commands to install development dependencies and run tests on Windows using Makefile.windows. ```bash make -f Makefile.windows install-dev ``` ```bash make -f Makefile.windows test ``` ```bash make -f Makefile.windows check ``` -------------------------------- ### Get Statistics Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Retrieve basic metrics and statistics tracked by the SecretsManager instance. ```python stats = manager.get_statistics() ``` -------------------------------- ### Get Usage Statistics Source: https://context7.com/dclobato/secrets-manager/llms.txt Retrieves thread-safe statistics on encryption, decryption, cache performance, and integrity checks. Individual metrics can be accessed directly from the returned dictionary. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "key", "salt": b"salt"}}, active_version="v1", ) manager = SecretsManager(config) # Perform some operations for i in range(5): _, ct = manager.encrypt(f"data {i}".encode()) manager.decrypt(ct) # Get statistics stats = manager.get_statistics() print(stats) # Output: # { # 'encryptions': 5, # 'decryptions': 5, # 'cache_hits': 9, # 'cache_misses': 1, # 'integrity_checks': 0 # } # Access individual metrics print(f"Total encryptions: {stats['encryptions']}") print(f"Cache hit ratio: {stats['cache_hits'] / (stats['cache_hits'] + stats['cache_misses']):.2%}") ``` -------------------------------- ### Build and Publish to PyPI Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Build the package and upload it to the registry. ```bash uv build uv publish ``` -------------------------------- ### Navigate to Project Directory Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Change the current working directory to the project root. ```bash cd SecretsManager ``` -------------------------------- ### Execute Test Suite Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Run unit tests and coverage reports using uv or the provided Makefile. ```bash # Basic tests uv run pytest # Coverage uv run pytest --cov=secrets_manager --cov-report=html # Or use the Makefile uv run make test uv run make test-cov ``` -------------------------------- ### Initialize Secrets Manager Source: https://context7.com/dclobato/secrets-manager/llms.txt Set up logging, configuration, and the SecretsManager instance. The configuration includes key versions, the active version, and an optional logger. ```python import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "my-secret-password", "salt": b"random-salt"}}, active_version="v1", logger=logger, ) manager = SecretsManager(config) # Get active version print(manager.get_active_version()) # Output: v1 # Get all available versions print(manager.get_all_versions()) # Output: ['v1'] # Get Fernet instance for specific version fernet = manager.get_fernet("v1") ``` -------------------------------- ### Load and Save Configuration from/to File Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Serialize SecretsConfig to an environment file and deserialize it back, normalizing salts to bytes. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "my-key", "salt": b"my-salt"}}, active_version="v1", ) config.to_file(".env.secrets") loaded = SecretsConfig.from_file(".env.secrets") manager = SecretsManager(loaded) ``` -------------------------------- ### Run Local Test Script Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Execute the local test script using the uv environment. ```bash uv run python test_local.py ``` -------------------------------- ### Load SecretsConfig from Environment Variables Source: https://context7.com/dclobato/secrets-manager/llms.txt Create configuration from environment variables using standard prefixes or custom overrides. ```python import os from secrets_manager import SecretsConfig, SecretsManager # Set environment variables (typically done outside Python) os.environ["ENCRYPTION_KEYS__v1"] = "my-secret-key" os.environ["ENCRYPTION_SALT__v1"] = "bXktc2FsdA==" # base64 encoded salt os.environ["ENCRYPTION_SALT_HASH__v1"] = "abc123..." # optional os.environ["ACTIVE_ENCRYPTION_VERSION"] = "v1" # Load configuration from environment config = SecretsConfig.from_environment() # Custom prefixes if needed config = SecretsConfig.from_environment( keys_prefix="MY_APP_KEYS", salt_prefix="MY_APP_SALT", salt_hash_prefix="MY_APP_HASH", active_version_key="MY_APP_ACTIVE_VERSION", ) manager = SecretsManager(config) version, ciphertext = manager.encrypt(b"sensitive data") ``` -------------------------------- ### Configure SecretsManager with SecretsConfig Source: https://context7.com/dclobato/secrets-manager/llms.txt Initialize SecretsConfig with encryption keys, salt integrity validation, and optional audit callbacks. ```python from secrets_manager import SecretsConfig, SecretsManager import hashlib # Basic configuration with single key version config = SecretsConfig( keys={ "v1": { "key": "my-secret-password", "salt": b"random-salt-value", # Must be bytes } }, active_version="v1", kdf_iterations=100_000, # PBKDF2 iterations (default) verify_salt_integrity=True, # Validate salt hash if provided ) # Configuration with salt integrity validation salt = b"my-secure-salt" salt_hash = hashlib.sha256(salt).hexdigest() config_with_integrity = SecretsConfig( keys={ "v1": { "key": "password", "salt": salt, "salt_hash": salt_hash, # Optional SHA256 hash for validation } }, active_version="v1", verify_salt_integrity=True, ) # Configuration with audit callback def audit_callback(event: str, metadata: dict): print(f"[AUDIT] {event}: {metadata}") config_with_audit = SecretsConfig( keys={"v1": {"key": "pass", "salt": b"salt"}}, active_version="v1", audit_callback=audit_callback, ) manager = SecretsManager(config_with_audit) # Output on encrypt: [AUDIT] encryption: {'version': 'v1', 'size': 12} ``` -------------------------------- ### Run Development Checks Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md Commands to execute tests, coverage reports, and code quality tools. ```bash uv run pytest uv run pytest --cov=secrets_manager --cov-report=html uv run black src/ tests/ uv run isort src/ tests/ uv run mypy src/ ``` -------------------------------- ### Tag and Push Release Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Commit changes and create a git tag for the release. ```bash git add . git commit -m "Release v0.1.1" git tag v0.1.1 git push origin main --tags ``` -------------------------------- ### Persist Keys to Environment File Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Rotate to a new key version and persist the changes to a specified environment file. ```python manager.rotate_to_new_version( new_version="v2", new_key="new-key", new_salt=b"new-salt", persist_to_file=".env.secrets", ) ``` -------------------------------- ### Load SecretsConfig from .env File Source: https://context7.com/dclobato/secrets-manager/llms.txt Load configuration from a .env file, automatically handling base64-encoded salts and checksum validation. ```python from secrets_manager import SecretsConfig, SecretsManager # Load configuration from .env file config = SecretsConfig.from_file(".env.secrets") # Initialize manager with loaded config manager = SecretsManager(config) # Encrypt and decrypt data version, ciphertext = manager.encrypt(b"confidential payload") _, plaintext = manager.decrypt(ciphertext) print(f"Decrypted: {plaintext.decode()}") # Output: Decrypted: confidential payload ``` -------------------------------- ### Initialize SecretsManager Source: https://context7.com/dclobato/secrets-manager/llms.txt Core class initialization for handling encryption operations. ```python from secrets_manager import SecretsConfig, SecretsManager import logging ``` -------------------------------- ### Update Package Version Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Set the version string in the package initialization file. ```python __version__ = "0.1.1" ``` -------------------------------- ### Project Directory Structure Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md The standard file layout for the SecretsManager project. ```text SecretsManager/ ├── src/ │ └── secrets_manager/ │ ├── __init__.py │ ├── config.py │ ├── manager.py │ └── utils.py ├── tests/ ├── examples/ ``` -------------------------------- ### Commit Changes Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md Commands to stage and commit changes to the repository. ```bash git add . git commit -m "Clear change description" ``` ```bash git push origin feature/my-feature ``` -------------------------------- ### Perform Code Quality Checks Source: https://github.com/dclobato/secrets-manager/blob/main/INSTALLATION_GUIDE.md Run formatting, linting, and type checking tasks. ```bash # Formatting uv run make format # Linting uv run make lint # Type checking uv run make type-check # All checks uv run make check ``` -------------------------------- ### Normalize Version Strings Source: https://context7.com/dclobato/secrets-manager/llms.txt Converts version strings to lowercase to ensure consistent cross-platform behavior. ```python from secrets_manager import normalize_version # Normalize to lowercase print(normalize_version("V1")) # Output: v1 print(normalize_version("v1")) # Output: v1 print(normalize_version("VERSION2")) # Output: version2 ``` -------------------------------- ### Configure Validated Keys Source: https://context7.com/dclobato/secrets-manager/llms.txt Creates an immutable KeyConfiguration object that supports automatic salt hash validation and secure memory cleanup. ```python from secrets_manager.config import KeyConfiguration import hashlib salt = b"secure-salt" salt_hash = hashlib.sha256(salt).hexdigest() # Create key configuration (validates salt hash automatically) key_config = KeyConfiguration( version="v1", key="my-encryption-key", # Converted to bytearray internally salt=salt, salt_hash=salt_hash, # Optional: validates on creation ) print(f"Version: {key_config.version}") print(f"Salt: {key_config.salt}") # Secure cleanup - zeros key material in memory key_config.cleanup() # After cleanup, key_config.key is all zeros ``` -------------------------------- ### Key Rotation Source: https://context7.com/dclobato/secrets-manager/llms.txt Adds a new key version and sets it as active. Old versions remain available for decrypting existing data. Optionally persists configuration to a .env file. ```APIDOC ## POST /rotate_to_new_version ### Description Adds a new key version and sets it as active. Old versions remain available for decrypting existing data. Optionally persists configuration to a .env file. ### Method POST ### Endpoint /rotate_to_new_version ### Parameters #### Request Body - **new_version** (string) - Required - The name for the new key version. - **new_key** (string) - Required - The new secret key. - **new_salt** (bytes) - Required - The salt for the new key version. - **persist_to_file** (string) - Optional - Path to a file to persist the configuration. ### Request Example ```json { "new_version": "v2", "new_key": "new-stronger-password", "new_salt": "random_salt_bytes", "persist_to_file": ".env.secrets" } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Key version v2 added and set as active." } ``` ``` -------------------------------- ### Persist SecretsConfig to .env File Source: https://context7.com/dclobato/secrets-manager/llms.txt Save configuration to a .env file with automatic checksum generation, supporting append mode. ```python from secrets_manager import SecretsConfig, SecretsManager # Create configuration config = SecretsConfig( keys={"v1": {"key": "example-key", "salt": b"example-salt"}}, active_version="v1", ) # Save to file (overwrites existing) config.to_file(".env.secrets") # Save preserving existing variables config.to_file(".env.secrets", append=True) # Generated .env file contents: # ACTIVE_ENCRYPTION_VERSION="v1" # ENCRYPTION_ENV_CHECKSUM="abc123..." # ENCRYPTION_KEYS__v1="example-key" # ENCRYPTION_SALT__v1="ZXhhbXBsZS1zYWx0" (base64) # ENCRYPTION_SALT_HASH__v1="..." ``` -------------------------------- ### Perform Secure Memory Cleanup Source: https://context7.com/dclobato/secrets-manager/llms.txt Zeros encryption key material and clears caches. Call this method before application shutdown to prevent sensitive data exposure. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "sensitive-key", "salt": b"salt"}}, active_version="v1", ) manager = SecretsManager(config) # Use manager for encryption/decryption _, ciphertext = manager.encrypt(b"data") manager.decrypt(ciphertext) # Before shutdown: cleanup sensitive material manager.cleanup() # Output log: Limpeza de segurança concluída: todas as chaves em cache zeradas e caches limpos # After cleanup, create new manager instance if needed # Do NOT reuse the cleaned-up manager ``` -------------------------------- ### Normalize Salt Formats Source: https://context7.com/dclobato/secrets-manager/llms.txt Converts various salt input formats including hex, base64, and UTF-8 strings into bytes. ```python from secrets_manager import normalize_salt # From bytes (passthrough) salt1 = normalize_salt(b"my-salt") print(salt1) # Output: b'my-salt' # From hex string salt2 = normalize_salt("6d792d73616c74") # hex for "my-salt" print(salt2) # Output: b'my-salt' # From base64 string salt3 = normalize_salt("bXktc2FsdA==") # base64 for "my-salt" print(salt3) # Output: b'my-salt' # From UTF-8 string (fallback) salt4 = normalize_salt("plain-text-salt") print(salt4) # Output: b'plain-text-salt' ``` -------------------------------- ### Encrypt Data with Secrets Manager Source: https://context7.com/dclobato/secrets-manager/llms.txt Encrypts plaintext bytes using the active key version. Ensure the SecretsConfig is properly initialized with keys and an active version. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "my-password", "salt": b"my-salt"}}, active_version="v1", ) manager = SecretsManager(config) # Encrypt sensitive data plaintext = b"Confidential information" version, ciphertext = manager.encrypt(plaintext) print(f"Encrypted with version: {version}") # Output: Encrypted with version: v1 print(f"Ciphertext length: {len(ciphertext)}") # Output: Ciphertext length: ~100+ bytes # Encrypt multiple items data_items = [ b"user@example.com", b"password123", b"api-key-secret", ] encrypted_items = [] for data in data_items: ver, ct = manager.encrypt(data) encrypted_items.append(ct) print(f"Encrypted: {data[:20]}...") ``` -------------------------------- ### Conventional Commit Format Source: https://github.com/dclobato/secrets-manager/blob/main/CONTRIBUTING.md The required structure for all commit messages in the project. ```text (): [optional longer description] [optional BREAKING CHANGE: describe the breaking change] ``` -------------------------------- ### Rotate Encryption Keys Source: https://context7.com/dclobato/secrets-manager/llms.txt Adds a new key version and sets it as active, allowing old versions to decrypt existing data. Optionally persists configuration to a file. Ensure a secure random salt is generated for new keys. ```python from secrets_manager import SecretsConfig, SecretsManager import os config = SecretsConfig( keys={"v1": {"key": "old-password", "salt": b"old-salt"}}, active_version="v1", ) manager = SecretsManager(config) # Encrypt data with v1 _, ciphertext_v1 = manager.encrypt(b"important data") # Rotate to new version manager.rotate_to_new_version( new_version="v2", new_key="new-stronger-password", new_salt=os.urandom(16), # Generate secure random salt ) print(f"Active version: {manager.get_active_version()}") # Output: v2 print(f"All versions: {manager.get_all_versions()}") # Output: ['v1', 'v2'] # New encryptions use v2 version, ciphertext_v2 = manager.encrypt(b"new data") print(f"New data encrypted with: {version}") # Output: v2 # Old data (v1) still decrypts successfully version_used, plaintext = manager.decrypt(ciphertext_v1) print(f"Old data decrypted with: {version_used}") # Output: v1 # Rotate and persist to file manager.rotate_to_new_version( new_version="v3", new_key="even-newer-key", new_salt=os.urandom(16), persist_to_file=".env.secrets", # Saves all versions to file ) ``` -------------------------------- ### Usage Statistics Source: https://context7.com/dclobato/secrets-manager/llms.txt Returns thread-safe statistics about encryption operations, cache performance, and integrity checks. ```APIDOC ## GET /get_statistics ### Description Returns thread-safe statistics about encryption operations, cache performance, and integrity checks. ### Method GET ### Endpoint /get_statistics ### Response #### Success Response (200) - **encryptions** (integer) - Number of encryption operations performed. - **decryptions** (integer) - Number of decryption operations performed. - **cache_hits** (integer) - Number of times data was found in the cache. - **cache_misses** (integer) - Number of times data was not found in the cache. - **integrity_checks** (integer) - Number of integrity checks performed. #### Response Example ```json { "encryptions": 5, "decryptions": 5, "cache_hits": 9, "cache_misses": 1, "integrity_checks": 0 } ``` ``` -------------------------------- ### Salt Integrity Validation Configuration Source: https://github.com/dclobato/secrets-manager/blob/main/README.md Configure SecretsManager to verify salt integrity using SHA256 hashing. Ensure the salt is provided as bytes. ```python import hashlib salt = b"my-salt" salt_hash = hashlib.sha256(salt).hexdigest() config = SecretsConfig( keys={"v1": {"key": "password", "salt": salt, "salt_hash": salt_hash}}, active_version="v1", verify_salt_integrity=True, ) ``` -------------------------------- ### Clear Internal Caches Source: https://context7.com/dclobato/secrets-manager/llms.txt Clears Fernet and configuration caches without affecting the underlying key material. Useful for testing or forcing key re-derivation. ```python from secrets_manager import SecretsConfig, SecretsManager config = SecretsConfig( keys={"v1": {"key": "key", "salt": b"salt"}}, active_version="v1", ) manager = SecretsManager(config) # Perform operations (populates cache) manager.encrypt(b"data") # Clear caches (keys will be re-derived on next use) manager.clear_cache() # Next operation will re-derive Fernet key manager.encrypt(b"more data") ``` -------------------------------- ### Encrypt Data Source: https://context7.com/dclobato/secrets-manager/llms.txt Encrypts plaintext bytes using the active key version. Returns a tuple of (version_used, ciphertext). ```APIDOC ## POST /encrypt ### Description Encrypts plaintext bytes using the active key version. Returns a tuple of (version_used, ciphertext). ### Method POST ### Endpoint /encrypt ### Parameters #### Request Body - **plaintext** (bytes) - Required - The data to encrypt. ### Request Example ```json { "plaintext": "Confidential information" } ``` ### Response #### Success Response (200) - **version_used** (string) - The version of the key used for encryption. - **ciphertext** (bytes) - The encrypted data. #### Response Example ```json { "version_used": "v1", "ciphertext": "gAAAAABl..." } ``` ``` -------------------------------- ### Decrypt Data Source: https://context7.com/dclobato/secrets-manager/llms.txt Decrypts ciphertext, automatically trying multiple key versions if needed. Returns (version_used, plaintext). ```APIDOC ## POST /decrypt ### Description Decrypts ciphertext, automatically trying multiple key versions if needed. Returns (version_used, plaintext). ### Method POST ### Endpoint /decrypt ### Parameters #### Request Body - **ciphertext** (bytes) - Required - The data to decrypt. - **version_hint** (string) - Optional - A hint for which version to try first. ### Request Example ```json { "ciphertext": "gAAAAABl...", "version_hint": "v2" } ``` ### Response #### Success Response (200) - **version_used** (string) - The version of the key used for decryption. - **plaintext** (bytes) - The decrypted data. #### Response Example ```json { "version_used": "v2", "plaintext": "secret data" } ``` #### Error Response (400) - **error** (string) - Description of the decryption error. #### Error Response Example ```json { "error": "Decryption failed: Invalid ciphertext" } ``` ``` -------------------------------- ### Decrypt Data with Secrets Manager Source: https://context7.com/dclobato/secrets-manager/llms.txt Decrypts ciphertext, automatically trying multiple key versions if needed. Handles potential decryption errors by raising SecretsManagerError. A version hint can be provided for optimization. ```python from secrets_manager import SecretsConfig, SecretsManager, SecretsManagerError config = SecretsConfig( keys={ "v1": {"key": "old-key", "salt": b"old-salt"}, "v2": {"key": "new-key", "salt": b"new-salt"}, }, active_version="v2", ) manager = SecretsManager(config) # Encrypt with v2 (active) _, ciphertext = manager.encrypt(b"secret data") # Decrypt - automatically uses correct version version_used, plaintext = manager.decrypt(ciphertext) print(f"Decrypted with {version_used}: {plaintext}") # Output: Decrypted with v2: b'secret data' # Decrypt with version hint (optimization for known version) version_used, plaintext = manager.decrypt(ciphertext, version_hint="v2") # Handle decryption errors try: _, plaintext = manager.decrypt(b"invalid-ciphertext") except SecretsManagerError as e: print(f"Decryption failed: {e}") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.