bump: python ver
fix: race condition in SecureMemory global vs. client instance - no more global state mutation
This commit is contained in:
parent
0746b50ee9
commit
1f0890300d
4 changed files with 13 additions and 20 deletions
|
|
@ -4,14 +4,13 @@ from cryptography.hazmat.primitives import serialization, hashes
|
|||
from cryptography.hazmat.primitives.asymmetric import rsa, padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
||||
|
||||
# Setup module logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Import secure memory module
|
||||
try:
|
||||
from .SecureMemory import secure_bytearray, get_memory_protection_info, _get_secure_memory
|
||||
from .SecureMemory import secure_bytearray, _get_secure_memory
|
||||
_SECURE_MEMORY_AVAILABLE = True
|
||||
except ImportError:
|
||||
_SECURE_MEMORY_AVAILABLE = False
|
||||
|
|
@ -77,19 +76,21 @@ class SecureCompletionClient:
|
|||
- Response parsing
|
||||
"""
|
||||
|
||||
def __init__(self, router_url: str = "https://api.nomyo.ai:12435", allow_http: bool = False):
|
||||
def __init__(self, router_url: str = "https://api.nomyo.ai:12435", allow_http: bool = False, secure_memory: bool = True):
|
||||
"""
|
||||
Initialize the secure completion client.
|
||||
|
||||
Args:
|
||||
router_url: Base URL of the NOMYO Router (must use HTTPS for production)
|
||||
allow_http: Allow HTTP connections (ONLY for local development, never in production)
|
||||
secure_memory: Whether to use secure memory operations for this instance.
|
||||
"""
|
||||
self.router_url = router_url.rstrip('/')
|
||||
self.private_key = None
|
||||
self.public_key_pem = None
|
||||
self.key_size = 4096 # RSA key size
|
||||
self.allow_http = allow_http # Store for use in fetch_server_public_key
|
||||
self._use_secure_memory = _SECURE_MEMORY_AVAILABLE and secure_memory
|
||||
|
||||
# Validate HTTPS for security
|
||||
if not self.router_url.startswith("https://"):
|
||||
|
|
@ -122,7 +123,7 @@ class SecureCompletionClient:
|
|||
- Rotate keys regularly
|
||||
- Store keys outside the project directory in production
|
||||
"""
|
||||
if not _SECURE_MEMORY_AVAILABLE or not self.private_key:
|
||||
if not self._use_secure_memory or not self.private_key:
|
||||
return
|
||||
|
||||
try:
|
||||
|
|
@ -416,7 +417,7 @@ class SecureCompletionClient:
|
|||
|
||||
aes_key = secrets.token_bytes(32) # 256-bit key
|
||||
try:
|
||||
if _SECURE_MEMORY_AVAILABLE:
|
||||
if self._use_secure_memory:
|
||||
with secure_bytearray(payload_json) as protected_payload:
|
||||
with secure_bytearray(aes_key) as protected_aes_key:
|
||||
return await self._do_encrypt(
|
||||
|
|
@ -500,7 +501,7 @@ class SecureCompletionClient:
|
|||
)
|
||||
|
||||
# Use secure memory to protect AES key and decrypted plaintext
|
||||
if _SECURE_MEMORY_AVAILABLE:
|
||||
if self._use_secure_memory:
|
||||
with secure_bytearray(aes_key) as protected_aes_key:
|
||||
ciphertext = base64.b64decode(package["encrypted_payload"]["ciphertext"])
|
||||
nonce = base64.b64decode(package["encrypted_payload"]["nonce"])
|
||||
|
|
|
|||
|
|
@ -51,6 +51,6 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
__version__ = "0.1.1"
|
||||
__version__ = "0.2.1"
|
||||
__author__ = "NOMYO AI"
|
||||
__license__ = "Apache-2.0"
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import uuid
|
|||
from typing import Dict, Any, List, Optional
|
||||
from .SecureCompletionClient import SecureCompletionClient
|
||||
|
||||
# Import secure memory module for configuration
|
||||
# Check if secure memory module is available (used only for the user-facing warning)
|
||||
try:
|
||||
from .SecureMemory import disable_secure_memory, enable_secure_memory
|
||||
from . import SecureMemory as _ # noqa: F401
|
||||
_SECURE_MEMORY_AVAILABLE = True
|
||||
except ImportError:
|
||||
_SECURE_MEMORY_AVAILABLE = False
|
||||
|
|
@ -69,20 +69,14 @@ class SecureChatCompletion:
|
|||
key_dir: Directory to load/save RSA keys. If None, ephemeral keys are
|
||||
generated in memory for this session only.
|
||||
"""
|
||||
self.client = SecureCompletionClient(router_url=base_url, allow_http=allow_http)
|
||||
self.client = SecureCompletionClient(router_url=base_url, allow_http=allow_http, secure_memory=secure_memory)
|
||||
self._keys_initialized = False
|
||||
self._keys_lock = asyncio.Lock()
|
||||
self.api_key = api_key
|
||||
self._key_dir = key_dir
|
||||
self._secure_memory_enabled = secure_memory
|
||||
|
||||
# Configure secure memory if available
|
||||
if _SECURE_MEMORY_AVAILABLE:
|
||||
if secure_memory:
|
||||
enable_secure_memory()
|
||||
else:
|
||||
disable_secure_memory()
|
||||
elif secure_memory:
|
||||
if secure_memory and not _SECURE_MEMORY_AVAILABLE:
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"Secure memory requested but not available. "
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ classifiers = [
|
|||
"Intended Audience :: Information Technology",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
|
|
@ -27,7 +25,7 @@ classifiers = [
|
|||
"Topic :: Communications :: Chat",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
requires-python = ">=3.8"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"anyio==4.12.0",
|
||||
"certifi==2025.11.12",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue