Cross-platform cryptographic library providing TLS sockets, asymmetric/symmetric encryption, and key operations using OS-native crypto libraries
—
Core system configuration for selecting cryptographic backends and FFI libraries. This allows forcing specific implementations when needed for testing, compatibility, or when custom OpenSSL/LibreSSL libraries are required.
Query which cryptographic backend is currently active based on the operating system and configuration.
def backend() -> str:
"""
Get the current cryptographic backend name.
Returns:
Backend name: 'openssl' (Linux/BSD), 'mac' (macOS), 'win' (Windows Vista+), 'winlegacy' (Windows XP)
"""
def ffi() -> str:
"""
Get the current FFI (Foreign Function Interface) library being used.
Returns:
FFI library name: 'cffi' or 'ctypes'
"""Force the use of specific OpenSSL or LibreSSL dynamic libraries instead of system defaults.
def use_openssl(libcrypto_path: str, libssl_path: str, trust_list_path: str = None) -> None:
"""
Force use of specific OpenSSL/LibreSSL libraries.
Parameters:
- libcrypto_path: str - Path to libcrypto dynamic library (.so/.dylib/.dll)
- libssl_path: str - Path to libssl dynamic library
- trust_list_path: str - Optional path to CA certificate bundle (PEM format)
Raises:
ValueError if paths are not unicode strings
LibraryNotFoundError if libraries don't exist
OSError if trust_list_path doesn't exist
RuntimeError if called after oscrypto modules are imported
Note:
Must be called before importing any other oscrypto modules
"""Force the use of legacy Windows CryptoAPI instead of modern CNG on Windows systems.
def use_winlegacy() -> None:
"""
Force use of legacy Windows CryptoAPI (Windows XP compatibility).
Raises:
EnvironmentError if called on non-Windows systems
RuntimeError if called after oscrypto modules are imported
Note:
Only use for Windows XP support or testing. CNG is preferred on Vista+.
Must be called before importing any other oscrypto modules.
"""Force the use of ctypes instead of cffi for the foreign function interface.
def use_ctypes() -> None:
"""
Force use of ctypes instead of cffi for FFI operations.
Raises:
RuntimeError if called after oscrypto modules are imported
Note:
Must be called before importing any other oscrypto modules
"""Get the dependency order for live code reloading scenarios.
def load_order() -> List[str]:
"""
Get the module load order for oscrypto components.
Returns:
List of module names in dependency order for reloading
"""import oscrypto
# Check which backend is active
backend_name = oscrypto.backend()
ffi_name = oscrypto.ffi()
print(f"Cryptographic backend: {backend_name}")
print(f"FFI library: {ffi_name}")
# Platform-specific behavior
if backend_name == 'openssl':
print("Using OpenSSL/LibreSSL on Linux/BSD")
elif backend_name == 'mac':
print("Using Security.framework on macOS")
elif backend_name == 'win':
print("Using CNG on Windows Vista+")
elif backend_name == 'winlegacy':
print("Using legacy CryptoAPI on Windows XP")import oscrypto
import os
# Must configure before importing other modules
if not any('oscrypto.' in module for module in sys.modules if module.startswith('oscrypto.')):
# Paths to custom OpenSSL libraries
libcrypto_path = "/opt/openssl-3.0/lib/libcrypto.so.3"
libssl_path = "/opt/openssl-3.0/lib/libssl.so.3"
ca_bundle_path = "/opt/openssl-3.0/certs/ca-bundle.pem"
# Verify libraries exist
if os.path.exists(libcrypto_path) and os.path.exists(libssl_path):
# Force specific OpenSSL version
oscrypto.use_openssl(libcrypto_path, libssl_path, ca_bundle_path)
print(f"Configured to use custom OpenSSL: {libcrypto_path}")
else:
print("Custom OpenSSL libraries not found, using system default")
# Now safe to import other modules
from oscrypto import asymmetric, tls
print(f"Backend: {oscrypto.backend()}")import sys
import oscrypto
# Force Windows XP compatibility mode
if sys.platform == 'win32':
try:
# Must be called before other imports
oscrypto.use_winlegacy()
print("Configured for Windows legacy CryptoAPI mode")
except EnvironmentError as e:
print(f"Cannot use legacy mode: {e}")
except RuntimeError as e:
print(f"Too late to configure legacy mode: {e}")
from oscrypto import asymmetric
print(f"Backend: {oscrypto.backend()}")import oscrypto
# Force ctypes usage (useful if cffi has issues)
try:
oscrypto.use_ctypes()
print("Configured to use ctypes for FFI")
except RuntimeError as e:
print(f"Cannot configure ctypes: {e}")
from oscrypto import symmetric
print(f"FFI library: {oscrypto.ffi()}")import sys
import oscrypto
def reload_oscrypto():
"""Reload oscrypto modules in dependency order."""
load_order = oscrypto.load_order()
# Remove modules in reverse order
for module_name in reversed(load_order):
if module_name in sys.modules:
del sys.modules[module_name]
# Reimport in correct order
for module_name in load_order:
try:
__import__(module_name)
print(f"Reloaded: {module_name}")
except ImportError as e:
print(f"Failed to reload {module_name}: {e}")
# Example usage for development
if __name__ == "__main__":
print("Initial load order:")
for module in oscrypto.load_order():
print(f" {module}")
# Perform reload
reload_oscrypto()import oscrypto
from oscrypto.errors import LibraryNotFoundError
def validate_configuration():
"""Validate current oscrypto configuration."""
try:
backend = oscrypto.backend()
ffi = oscrypto.ffi()
print(f"✓ Backend: {backend}")
print(f"✓ FFI: {ffi}")
# Test basic functionality
from oscrypto.util import rand_bytes
test_bytes = rand_bytes(16)
print(f"✓ Random generation: {len(test_bytes)} bytes")
# Test asymmetric operations
from oscrypto import asymmetric
pub_key, priv_key = asymmetric.generate_pair('rsa', bit_size=1024)
print("✓ RSA key generation")
# Test symmetric operations
from oscrypto.symmetric import aes_cbc_pkcs7_encrypt
ciphertext = aes_cbc_pkcs7_encrypt(test_bytes, b"test message")
print("✓ AES encryption")
print("Configuration validation successful!")
return True
except LibraryNotFoundError as e:
print(f"✗ Library not found: {e}")
return False
except Exception as e:
print(f"✗ Configuration error: {e}")
return False
# Run validation
validate_configuration()Install with Tessl CLI
npx tessl i tessl/pypi-oscrypto