Notepad++ Secrets Manager - Python Library
A Python library to access secrets stored by the Notepad++ Secrets Manager plugin. Read encrypted secrets directly from Python scripts without opening Notepad++.
Features
- ✅ Read encrypted secrets - Access secrets stored by Notepad++ plugin
- ✅ Password protected - Verifies master password using SHA-256
- ✅ Strong encryption - Uses PBKDF2 + Windows DPAPI (same as C++ plugin)
- ✅ Simple API - Easy-to-use Python interface
- ✅ Type hints - Full type annotations for better IDE support
- ✅ Search & filter - Find secrets by name or category
- ✅ Environment variables - Export secrets as env vars
Installation
From PyPI
pip install npp-secrets
From source
cd python_library
pip install .
Development install
cd python_library
pip install -e ".[dev]"
Requirements
- Python 3.7+
- Windows (uses Windows DPAPI)
- pywin32 - For Windows Cryptography API access
Quick Start
Basic Usage
from npp_secrets import SecretsManager
# Initialize manager
manager = SecretsManager()
# Check if password is set
if manager.has_password():
# Unlock with your master password
manager.unlock("your_master_password")
# Get a specific secret
api_key = manager.get_secret("GitHub API Key")
print(f"API Key: {api_key}")
# List all secrets
for secret in manager.list_secrets():
print(f"{secret.name}: {secret.value}")
# Lock when done
manager.lock()
Using as Environment Variables
from npp_secrets import SecretsManager
import os
manager = SecretsManager()
manager.unlock("your_password")
# Get secrets as environment variables
env_vars = manager.get_as_env_dict()
os.environ.update(env_vars)
# Now use them
github_token = os.environ["GITHUB_API_KEY"] # From "GitHub API Key"
Search and Filter
from npp_secrets import SecretsManager
manager = SecretsManager()
manager.unlock("your_password")
# Search by name
results = manager.search_secrets("github")
for secret in results:
print(f"Found: {secret.name}")
# Get secrets by category
api_keys = manager.get_secret_by_category("API Keys")
for secret in api_keys:
print(f"{secret.name} = {secret.value}")
Error Handling
from npp_secrets import (
SecretsManager,
InvalidPasswordError,
SecretsFileNotFoundError,
SecretsManagerError
)
manager = SecretsManager()
try:
manager.unlock("wrong_password")
except InvalidPasswordError:
print("Incorrect password!")
except SecretsFileNotFoundError:
print("Secrets file not found. Create secrets in Notepad++ first.")
except SecretsManagerError as e:
print(f"Error: {e}")
Context Manager (Future)
from npp_secrets import SecretsManager
# Automatically locks when exiting context
with SecretsManager() as manager:
manager.unlock("your_password")
api_key = manager.get_secret("My API Key")
# Use the API key...
# Automatically locked here
API Reference
SecretsManager
Methods
__init__(config_dir: Optional[str] = None)
Initialize the secrets manager.
Parameters:
config_dir(optional): Custom config directory. Defaults to%APPDATA%\Notepad++\plugins\config
has_password() -> bool
Check if a master password has been set.
Returns: True if password exists, False otherwise
verify_password(password: str) -> bool
Verify if the provided password is correct.
Parameters:
password: Password to verify
Returns: True if correct, False otherwise
unlock(password: str) -> None
Unlock the secrets manager.
Parameters:
password: Master password
Raises:
InvalidPasswordError: If password is incorrectSecretsFileNotFoundError: If secrets file doesn't exist
lock() -> None
Lock the secrets manager and clear secrets from memory.
get_secret(name: str) -> Optional[str]
Get a secret by name.
Parameters:
name: Secret name
Returns: Secret value or None if not found
Raises:
SecretsManagerError: If not unlocked
get_secret_by_category(category: str) -> List[Secret]
Get all secrets in a category.
Parameters:
category: Category name
Returns: List of secrets
list_secrets() -> List[Secret]
Get all secrets.
Returns: List of all secrets
search_secrets(query: str) -> List[Secret]
Search secrets by name (case-insensitive).
Parameters:
query: Search query
Returns: List of matching secrets
get_as_dict() -> Dict[str, str]
Get all secrets as a dictionary.
Returns: Dictionary mapping secret names to values
get_as_env_dict() -> Dict[str, str]
Get secrets as environment variable dictionary.
Returns: Dictionary with UPPER_SNAKE_CASE names
Properties
is_unlocked: bool
Check if currently unlocked.
secret_count: int
Get the number of loaded secrets.
Secret (dataclass)
Attributes:
name(str): Secret namevalue(str): Secret valuecategory(str): Category (optional)
Exceptions
SecretsManagerError: Base exceptionInvalidPasswordError: Wrong passwordSecretsFileNotFoundError: Missing secrets file
Command-Line Usage
The library includes a CLI tool:
# Run interactive demo
npp-secrets
# Or use Python
python -m npp_secrets.secrets_manager
Output:
Enter master password: ********
✓ Unlocked! Found 5 secrets.
Available secrets:
• GitHub API Key [API Keys]
• AWS Access Key [API Keys]
• Database Password [Credentials]
Environment variable mapping:
GITHUB_API_KEY=***
AWS_ACCESS_KEY=***
DATABASE_PASSWORD=***
Use Cases
1. CI/CD Scripts
from npp_secrets import SecretsManager
manager = SecretsManager()
manager.unlock(os.environ["NPP_MASTER_PASSWORD"])
# Deploy using secrets
deploy_api_key = manager.get_secret("Deploy Key")
deploy_to_server(api_key=deploy_api_key)
2. Database Connections
from npp_secrets import SecretsManager
import psycopg2
manager = SecretsManager()
manager.unlock("master_pass")
db_password = manager.get_secret("Database Password")
conn = psycopg2.connect(
host="localhost",
user="admin",
password=db_password
)
3. API Testing
from npp_secrets import SecretsManager
import requests
manager = SecretsManager()
manager.unlock("master_pass")
api_key = manager.get_secret("Test API Key")
response = requests.get(
"https://api.example.com/data",
headers={"Authorization": f"Bearer {api_key}"}
)
4. Configuration Files
from npp_secrets import SecretsManager
import json
manager = SecretsManager()
manager.unlock("master_pass")
config = {
"api_key": manager.get_secret("API Key"),
"secret": manager.get_secret("App Secret"),
"token": manager.get_secret("Auth Token")
}
with open("config.json", "w") as f:
json.dump(config, f)
Security Considerations
✅ What This Library Does
- Encrypts secrets using Windows DPAPI (tied to your user account)
- Uses PBKDF2 with 10,000 iterations for key derivation
- Requires master password to decrypt
- Clears secrets from memory when locked
⚠️ Important Notes
- Secrets are tied to your Windows user account - Can't be decrypted on another machine or by another user
- Master password is required - Store it securely
- Auto-lock after 60 minutes - Plugin auto-locks, but Python library doesn't (call
lock()when done) - No recovery - If you forget the master password, secrets are lost
- Windows only - Uses Windows DPAPI
🔒 Best Practices
- Lock after use: Always call
manager.lock()when done - Don't hardcode passwords: Use environment variables or getpass
- Limit scope: Only unlock when needed
- Use strong passwords: For your master password
- Secure your scripts: Don't commit scripts with passwords
File Format
The library reads two binary files:
secrets_hash.dat
[4 bytes: hash_size]
[hash_size bytes: SHA-256 hash of password]
secrets.dat
[4 bytes: count]
For each secret:
[4 bytes: name_size]
[name_size bytes: encrypted name (salt + size + dpapi_data)]
[4 bytes: value_size]
[value_size bytes: encrypted value]
[4 bytes: category_size]
[category_size bytes: encrypted category]
Encrypted Field Format
[16 bytes: salt]
[4 bytes: data_size]
[data_size bytes: DPAPI encrypted data]
Development
Running Tests
pytest tests/
Type Checking
mypy npp_secrets/
Code Formatting
black npp_secrets/
Compatibility
| Component | Version |
|---|---|
| Python | 3.7+ |
| Windows | 7+ |
| Notepad++ Plugin | v1.0+ |
| pywin32 | 300+ |
License
This library is licensed under the GNU General Public License v2.0 or later, matching the Notepad++ plugin license.
See LICENSE for details.
Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new features
- Submit a pull request
Changelog
1.0.0 (2024)
- Initial release
- Read encrypted secrets from Notepad++ plugin
- Password verification
- Search and filtering
- Environment variable export
- CLI tool
Support
For issues or questions:
- Open an issue on GitHub
- Check the main plugin README
Related Projects
- Notepad++ Secrets Manager Plugin - The C++ plugin for Notepad++
Made with ❤️ for secure secret management in Notepad++
Metadata
Release files for npp-secrets 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| npp_secrets-1.0.0.tar.gz | 11.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| npp_secrets-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.9 kB
Release files / npp_secrets-1.0.0.tar.gz
| Download URL | npp_secrets-1.0.0.tar.gz |
|---|---|
| Size | 11.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
342f33f8badd05bf56e9da2946ca2a560779f07d8a47337be45d5159073b6478
|
|
BLAKE2b-256 checksum How to use checksums |
23febe2473c6d6fd16c537bcf9e4a8044c2816d79eaafab7969a9c12cac5c427
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Release files / npp_secrets-1.0.0-py3-none-any.whl
| Download URL | npp_secrets-1.0.0-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6b6af045e7819a2c852b5d1f1e46ab49447a3173496b0f0df7de80508b804d63
|
|
BLAKE2b-256 checksum How to use checksums |
46210d0568474e06acf68245b5aa8edd1db64f12e6a0513318d5afcb6be43f24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|