Skip to main content

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 identifier
  • messages: List of message objects
  • temperature: Sampling temperature (0-2)
  • max_tokens: Maximum tokens to generate
  • top_p: Nucleus sampling
  • frequency_penalty: Frequency penalty
  • presence_penalty: Presence penalty
  • stop: Stop sequences
  • n: Number of completions
  • stream: Streaming (not yet implemented)
  • tools: Tool definitions
  • tool_choice: Tool selection strategy
  • user: 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 layer
  • certifi: TLS/SSL certificates
  • cffi: C Foreign Function Interface
  • cryptography: Cryptographic primitives (RSA, AES, etc.)
  • exceptiongroup: Exception groups backport
  • h11: HTTP/1.1 protocol implementation
  • httpcore: Minimal HTTP client
  • httpx: Async HTTP client
  • idna: Internationalized domain names
  • pycparser: C parser for cffi
  • typing_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 authentication
  • secure_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 completion
  • acreate(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 pair
  • load_keys(private_key_path, public_key_path=None, password=None): Load keys from files
  • fetch_server_public_key(): Fetch server's public key
  • encrypt_payload(payload): Encrypt a payload
  • decrypt_response(encrypted_response, payload_id): Decrypt a response
  • send_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() with SecureChatCompletion.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


Download files

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

Source Distribution

nomyo-0.2.9.tar.gz (220.5 kB view details)

Uploaded Source

Built Distribution

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

nomyo-0.2.9-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

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

Hashes for nomyo-0.2.9.tar.gz
Algorithm Hash digest
SHA256 baef9c1e79e305a0e23556313baa4d3982f640acdf41cc6b1025183c559bae37
MD5 e9aaff226d7abd43fd1b28fd6fa37244
BLAKE2b-256 bfcaef1d0724f94d6bfa183c27af34d2d6a121ab62be4415cb4aa203fc9dddff

See more details on using hashes here.

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

Hashes for nomyo-0.2.9-py3-none-any.whl
Algorithm Hash digest
SHA256 eb2c99f65ffd8f75ca9a9e66208057c7fd1acc9db21d8a408d4771dcd43bb7ed
MD5 d8a2c15a14da35cc590dff37ce6d33b6
BLAKE2b-256 38a819a462bb1f22cfbc06d9e01ed1d95e575fa81e025405bdaa5d771406bb81

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