| .idea | ||
| src | ||
| .gitignore | ||
| AGENTS.md | ||
| pom.xml | ||
| README.md | ||
NOMYO Secure Java Chat Client
OpenAI-compatible secure chat client with end-to-end encryption for 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 (Java)
🚀 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. Installation
via Maven (recommended):
<dependency>
<groupId>com.nomyo</groupId>
<artifactId>nomyo-java</artifactId>
<version>1.0.0</version>
</dependency>
via Gradle:
implementation 'com.nomyo:nomyo-java:1.0.0'
2. Use the client (same API as OpenAI)
import com.nomyo.client.SecureChatCompletion;
import com.nomyo.client.Constants;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
SecureChatCompletion secureChatCompletion = new SecureChatCompletion(
Constants.DEFAULT_BASE_URL,
"NOMYO_AI_E2EE_INFERENCE"
);
List<Map<String, Object>> messages = List.of(
Map.of("role", "user", "content", "Hello! How are you today?")
);
Map<String, Object> kwargs = Map.of(
"security_tier", "standard",
"temperature", 0.7
);
var response = secureChatCompletion.create(
"Qwen/Qwen3-0.6B",
messages,
kwargs);
System.out.println(response.toString());
}
}
🔐 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
- 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 objects (List<Map<String, Object>>)temperature: Sampling temperature (0-2)max_tokens: Maximum tokens to generatetop_p: Nucleus samplingfrequency_penalty: Frequency penaltypresence_penalty: Presence penaltystop: Stop sequencesn: Number of completionstools: 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 com.nomyo.client.SecureChatCompletion;
import com.nomyo.client.Constants;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
SecureChatCompletion client = new SecureChatCompletion(
Constants.DEFAULT_BASE_URL,
"NOMYO_AI_E2EE_INFERENCE"
);
List<Map<String, Object>> messages = List.of(
Map.of("role", "system", "content", "You are a helpful assistant."),
Map.of("role", "user", "content", "What is the capital of France?")
);
Map<String, Object> kwargs = Map.of("security_tier", "standard", "temperature", 0.7);
var response = client.create(
"Qwen/Qwen3-0.6B",
messages,
kwargs
);
// Extract content safely
System.out.println(response.get("choices").get(0).get("message").get("content"));
}
}
With Tools
import com.nomyo.client.SecureChatCompletion;
import com.nomyo.client.Constants;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
SecureChatCompletion client = new SecureChatCompletion(
Constants.DEFAULT_BASE_URL,
"NOMYO_AI_E2EE_INFERENCE"
);
List<Map<String, Object>> messages = List.of(
Map.of("role", "user", "content", "What's the weather in Paris?")
);
Map<String, Object> tools = Map.of(
"type", "function",
"function", Map.of(
"name", "get_weather",
"description", "Get weather information",
"parameters", Map.of(
"type", "object",
"properties", Map.of(
"location", Map.of("type", "string")
),
"required", List.of("location")
)
)
);
Map<String, Object> kwargs = Map.of("security_tier", "standard", "temperature", 0.7);
var response = client.create(
"Qwen/Qwen3-0.6B",
messages,
kwargs
);
System.out.println(response.get("choices").get(0).get("message").get("content"));
}
}
📦 Dependencies
- Maven Coordinates:
com.nomyo:nomyo-java - Java Version: Java 11+ (Required for HTTP Client and crypto primitives)
- JSON Processing: Jackson Databind (for Map/JSON handling)
- HTTP Client: Apache HttpClient or Java NIO (Included in core)
- Crypto: BouncyCastle or JDK Crypto (Included in core)
🔧 Configuration
Custom Base URL
SecureChatCompletion client = new SecureChatCompletion("https://NOMYO-Pro-Router:12434", "YOUR_API_KEY");
API Key Authentication
// Initialize with API key (recommended for production)
SecureChatCompletion client = new SecureChatCompletion(
"https://api.nomyo.ai",
"your-api-key-here"
);
// Or pass API key in the create() method if supported by extension
// Map<String, Object> kwargs = Map.of("security_tier", "standard", "api_key", "your-api-key-here");
Secure Memory Configuration
The library enables secure memory protection by default.
// Enable secure memory protection (default)
SecureChatCompletion client = new SecureChatCompletion("https://api.nomyo.ai", "YOUR_API_KEY");
// Disable secure memory (not recommended, for testing only)
// Requires passing specific config flag if available in version
SecureChatCompletion client = new SecureChatCompletion("https://api.nomyo.ai", "YOUR_API_KEY");
Key Management
Keys are automatically generated on first use.
Generate Keys Manually
import com.nomyo.client.SecureCompletionClient;
public class KeyManager {
public static void main(String[] args) {
SecureCompletionClient client = new SecureCompletionClient();
client.generateKeys(true, "client_keys", "your-password");
}
}
Load Existing Keys
import com.nomyo.client.SecureCompletionClient;
public class KeyManager {
public static void main(String[] args) {
SecureCompletionClient client = new SecureCompletionClient();
client.loadKeys("client_keys/private_key.pem", "client_keys/public_key.pem", "your-password");
}
}
📚 API Reference
SecureChatCompletion
Constructor
SecureChatCompletion(
String base_url,
String api_key
)
Parameters:
base_url: Base URL of the NOMYO Router (must use HTTPS for production)api_key: Optional API key for bearer authentication
Methods
create(String model, List<Map<String, Object>> messages, Map<String, Object> kwargs): Create a chat completion
SecureCompletionClient
Constructor
SecureCompletionClient(
String router_url
)
Methods
generateKeys(boolean saveToFile, String keyDir, String password): Generate RSA key pairloadKeys(String private_key_path, String public_key_path, String password): Load keys from filesfetchServerPublicKey(): Fetch server's public keyencryptPayload(Map<String, Object> payload): Encrypt a payloaddecryptResponse(Map<String, Object> encrypted_response, String payload_id): Decrypt a responsesendSecureRequest(Map<String, Object> payload, String 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.