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.8.tar.gz (220.3 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.8-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

Details for the file nomyo-0.2.8.tar.gz.

File metadata

  • Download URL: nomyo-0.2.8.tar.gz
  • Upload date:
  • Size: 220.3 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.8.tar.gz
Algorithm Hash digest
SHA256 7972106159be8be1ddfbbd281e173683f4e085efebc286dc066ac1920872a918
MD5 d6b2c16e28659a19d32d0681b1b4c436
BLAKE2b-256 dcd56d806f6f8066648e434df46a94800eea68102e22352d79402d87469ccb32

See more details on using hashes here.

File details

Details for the file nomyo-0.2.8-py3-none-any.whl.

File metadata

  • Download URL: nomyo-0.2.8-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.8-py3-none-any.whl
Algorithm Hash digest
SHA256 bca6da654cd9ba84945723faa8a658b26824c05c619f24cee2492c8dfe2c572c
MD5 2cf790faabbdc4cf864020cd6675e1ee
BLAKE2b-256 af8de9b9003a9cc645df54859750cbd9071fa0efb61d5e45240d26aa8d9c3730

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