Skip to main content

Python library to access Notepad++ Secrets Manager encrypted secrets

Project description

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 incorrect
  • SecretsFileNotFoundError: 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 name
  • value (str): Secret value
  • category (str): Category (optional)

Exceptions

  • SecretsManagerError: Base exception
  • InvalidPasswordError: Wrong password
  • SecretsFileNotFoundError: 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

  1. Lock after use: Always call manager.lock() when done
  2. Don't hardcode passwords: Use environment variables or getpass
  3. Limit scope: Only unlock when needed
  4. Use strong passwords: For your master password
  5. 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:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. 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:

Related Projects


Made with ❤️ for secure secret management in Notepad++

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

npp_secrets-1.0.0.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

npp_secrets-1.0.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file npp_secrets-1.0.0.tar.gz.

File metadata

  • Download URL: npp_secrets-1.0.0.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for npp_secrets-1.0.0.tar.gz
Algorithm Hash digest
SHA256 342f33f8badd05bf56e9da2946ca2a560779f07d8a47337be45d5159073b6478
MD5 189b4688c3208257008bc47e47d6cd36
BLAKE2b-256 23febe2473c6d6fd16c537bcf9e4a8044c2816d79eaafab7969a9c12cac5c427

See more details on using hashes here.

File details

Details for the file npp_secrets-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: npp_secrets-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for npp_secrets-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6b6af045e7819a2c852b5d1f1e46ab49447a3173496b0f0df7de80508b804d63
MD5 988845bbc351ab68ddf5163beab67b87
BLAKE2b-256 46210d0568474e06acf68245b5aa8edd1db64f12e6a0513318d5afcb6be43f24

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page