OpenAI-compatible secure chat client with end-to-end encryption for NOMYO Inference Endpoints
Project description
NOMYO Secure Python Chat Client
OpenAI-compatible secure chat client with end-to-end encryption with NOMYO Inference Endpoints
🔒 All prompts and responses are automatically encrypted and decrypted
🔑 Uses hybrid encryption (AES-256-GCM + RSA-OAEP with 4096-bit keys)
🔄 Drop-in replacement for OpenAI's ChatCompletion API
🚀 Quick Start
0. Try It Now (Demo Credentials)
No account needed — use these public demo credentials to test immediately:
| API key | NOMYO_AI_E2EE_INFERENCE |
| Model | Qwen/Qwen3-0.6B |
Note: The demo endpoint uses a fixed 256-token context window and is intended for evaluation only.
1. Install methods
via pip (recommended):
pip install nomyo
from source:
git clone https://bitfreedom.net/code/nomyo-ai/nomyo.git
cd nomyo
pip install -r requirements.txt
pip install -e .
2. Use the client (same API as OpenAI)
import asyncio
from nomyo import SecureChatCompletion
async def main():
# Initialize client (defaults to https://api.nomyo.ai)
client = SecureChatCompletion(base_url="https://api.nomyo.ai")
# Simple chat completion
response = await client.create(
model="Qwen/Qwen3-0.6B",
messages=[
{"role": "user", "content": "Hello! How are you today?"}
],
security_tier="standard", #optional: standard, high or maximum
temperature=0.7
)
print(response['choices'][0]['message']['content'])
# Run the async function
asyncio.run(main())
🔐 Security Features
Hybrid Encryption
- Payload encryption: AES-256-GCM (authenticated encryption)
- Key exchange: RSA-OAEP with SHA-256
- Key size: 4096-bit RSA keys
- All communication: End-to-end encrypted
Key Management
- Automatic key generation: Keys are automatically generated on first use
- Automatic key loading: Existing keys are loaded automatically from
client_keys/directory - No manual intervention required: The library handles key management automatically
- Keys kept in memory: Active session keys are stored in memory for performance
- Optional persistence: Keys can be saved to
client_keys/directory for reuse across sessions - Password protection: Optional password encryption for private keys (recommended for production)
- Secure permissions: Private keys stored with restricted permissions (600 - owner-only access)
Secure Memory Protection
Ephemeral AES Keys
- Per-request encryption keys: A unique AES-256 key is generated for each request
- Automatic rotation: AES keys are never reused - a fresh key is created for every encryption operation
- Forward secrecy: Compromise of one AES key only affects that single request
- Secure generation: AES keys are generated using cryptographically secure random number generation (
secrets.token_bytes) - Automatic cleanup: AES keys are zeroed from memory immediately after use
- Automatic protection: Plaintext payloads are automatically protected during encryption
- Prevents memory swapping: Sensitive data cannot be swapped to disk
- Guaranteed zeroing: Memory is zeroed after encryption completes
- Fallback mechanism: Graceful degradation if SecureMemory module unavailable
🔄 OpenAI Compatibility
The SecureChatCompletion class provides exact API compatibility with OpenAI's ChatCompletion.create() method.
Supported Parameters
All standard OpenAI parameters are supported:
model: Model identifiermessages: List of message objectstemperature: Sampling temperature (0-2)max_tokens: Maximum tokens to generatetop_p: Nucleus samplingfrequency_penalty: Frequency penaltypresence_penalty: Presence penaltystop: Stop sequencesn: Number of completionsstream: Streaming (not yet implemented)tools: Tool definitionstool_choice: Tool selection strategyuser: User identifier- And more...
Response Format
Responses follow the OpenAI format exactly, with an additional _metadata field for debugging and security information:
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1234567890,
"model": "Qwen/Qwen3-0.6B",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello! I'm doing well, thank you for asking.",
"tool_calls": [...] # if tools were used
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 10,
"completion_tokens": 20,
"total_tokens": 30
},
"_metadata": {
"payload_id": "openai-compat-abc123", # Unique identifier for this request
"processed_at": 1765250382, # Timestamp when server processed the request
"is_encrypted": True, # Indicates this response was decrypted
"encryption_algorithm": "hybrid-aes256-rsa4096", # Encryption method used
"response_status": "success" # Status of the decryption/processing
}
}
The _metadata field contains security-related information about the encrypted communication and is automatically added to all responses.
🛠️ Usage Examples
Basic Chat
import asyncio
from nomyo import SecureChatCompletion
async def main():
client = SecureChatCompletion(base_url="https://api.nomyo.ai")
response = await client.create(
model="Qwen/Qwen3-0.6B",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
],
security_tier="standard", #optional: standard, high or maximum
temperature=0.7
)
print(response['choices'][0]['message']['content'])
asyncio.run(main())
With Tools
import asyncio
from nomyo import SecureChatCompletion
async def main():
client = SecureChatCompletion(base_url="https://api.nomyo.ai")
response = await client.create(
model="Qwen/Qwen3-0.6B",
messages=[
{"role": "user", "content": "What's the weather in Paris?"}
],
tools=[
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather information",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}
],
security_tier="standard", #optional: standard, high or maximum
temperature=0.7
)
print(response['choices'][0]['message']['content'])
asyncio.run(main())
Using acreate() Alias
import asyncio
from nomyo import SecureChatCompletion
async def main():
client = SecureChatCompletion(base_url="https://api.nomyo.ai")
response = await client.acreate(
model="Qwen/Qwen3-0.6B",
messages=[
{"role": "user", "content": "Hello!"}
],
temperature=0.7
)
print(response['choices'][0]['message']['content'])
asyncio.run(main())
📦 Dependencies
anyio: Async compatibility layercertifi: TLS/SSL certificatescffi: C Foreign Function Interfacecryptography: Cryptographic primitives (RSA, AES, etc.)exceptiongroup: Exception groups backporth11: HTTP/1.1 protocol implementationhttpcore: Minimal HTTP clienthttpx: Async HTTP clientidna: Internationalized domain namespycparser: C parser for cffityping_extensions: Backported typing hints
🔧 Configuration
Custom Base URL
import asyncio
from nomyo import SecureChatCompletion
async def main():
client = SecureChatCompletion(base_url="https://NOMYO-Pro-Router:12434")
# ... rest of your code
asyncio.run(main())
```### API Key Authentication
```python
import asyncio
from nomyo import SecureChatCompletion
async def main():
# Initialize with API key (recommended for production)
client = SecureChatCompletion(
base_url="https://api.nomyo.ai",
api_key="your-api-key-here"
)
# Or pass API key in the create() method
response = await client.create(
model="Qwen/Qwen3-0.6B",
messages=[
{"role": "user", "content": "Hello!"}
],
api_key="your-api-key-here" # Overrides instance API key
)
asyncio.run(main())
Secure Memory Configuration
import asyncio
from nomyo import SecureChatCompletion
async def main():
# Enable secure memory protection (default, recommended)
client = SecureChatCompletion(
base_url="https://api.nomyo.ai",
secure_memory=True # Default
)
# Disable secure memory (not recommended, for testing only)
client = SecureChatCompletion(
base_url="https://api.nomyo.ai",
secure_memory=False
)
asyncio.run(main())
Key Management
Keys are automatically generated on first use.
Generate Keys Manually
import asyncio
from nomyo.SecureCompletionClient import SecureCompletionClient
async def main():
client = SecureCompletionClient()
await client.generate_keys(save_to_file=True, password="your-password")
asyncio.run(main())
Load Existing Keys
import asyncio
from nomyo.SecureCompletionClient import SecureCompletionClient
async def main():
client = SecureCompletionClient()
await client.load_keys("client_keys/private_key.pem", "client_keys/public_key.pem", password="your-password")
asyncio.run(main())
📚 API Reference
SecureChatCompletion
Constructor
SecureChatCompletion(
base_url: str = "https://api.nomyo.ai",
allow_http: bool = False,
api_key: Optional[str] = None,
secure_memory: bool = True,
max_retries: int = 2
)
Parameters:
base_url: Base URL of the NOMYO Router (must use HTTPS for production)allow_http: Allow HTTP connections (ONLY for local development, never in production)api_key: Optional API key for bearer authenticationsecure_memory: Enable secure memory protection (default: True)max_retries: Retries on retryable errors (429, 500, 502, 503, 504, network errors) with exponential backoff. Default: 2
Methods
create(model, messages, **kwargs): Create a chat completionacreate(model, messages, **kwargs): Async alias for create()
SecureCompletionClient
Constructor
SecureCompletionClient(router_url: str = "https://api.nomyo.ai", allow_http: bool = False, max_retries: int = 2)
Methods
generate_keys(save_to_file=False, key_dir="client_keys", password=None): Generate RSA key pairload_keys(private_key_path, public_key_path=None, password=None): Load keys from filesfetch_server_public_key(): Fetch server's public keyencrypt_payload(payload): Encrypt a payloaddecrypt_response(encrypted_response, payload_id): Decrypt a responsesend_secure_request(payload, payload_id): Send encrypted request and receive decrypted response
📝 Notes
Security Best Practices
- Always use password protection for private keys in production
- Keep private keys secure (permissions set to 600)
- Never share your private key
- Verify server's public key fingerprint before first use
Performance
- Key generation takes ~1-2 seconds (one-time operation)
- Encryption/decryption adds minimal overhead (~10-20ms per request)
Compatibility
- Works with any OpenAI-compatible code
- No changes needed to existing OpenAI client code
- Simply replace
openai.ChatCompletion.create()withSecureChatCompletion.create()
🤝 Contributing
Contributions are welcome! Please open issues or pull requests on the project repository.
📄 License
See LICENSE file for licensing information.
📞 Support
For questions or issues, please refer to the project documentation or open an issue.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nomyo-0.2.9.tar.gz.
File metadata
- Download URL: nomyo-0.2.9.tar.gz
- Upload date:
- Size: 220.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
baef9c1e79e305a0e23556313baa4d3982f640acdf41cc6b1025183c559bae37
|
|
| MD5 |
e9aaff226d7abd43fd1b28fd6fa37244
|
|
| BLAKE2b-256 |
bfcaef1d0724f94d6bfa183c27af34d2d6a121ab62be4415cb4aa203fc9dddff
|
File details
Details for the file nomyo-0.2.9-py3-none-any.whl.
File metadata
- Download URL: nomyo-0.2.9-py3-none-any.whl
- Upload date:
- Size: 28.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb2c99f65ffd8f75ca9a9e66208057c7fd1acc9db21d8a408d4771dcd43bb7ed
|
|
| MD5 |
d8a2c15a14da35cc590dff37ce6d33b6
|
|
| BLAKE2b-256 |
38a819a462bb1f22cfbc06d9e01ed1d95e575fa81e025405bdaa5d771406bb81
|