{"id":914,"library":"oscrypto","title":"oscrypto","description":"oscrypto is a compilation-free Python library that exposes cryptography primitives from the host operating system's crypto libraries, such as Windows CNG, macOS Security.framework, and OpenSSL/LibreSSL on Linux/BSD. It currently stands at version 1.3.0 and focuses on providing basic crypto functionality like TLS (SSL) sockets, key generation, encryption, decryption, signing, verification, and KDFs. The library relies on the OS for security patching, avoiding the need for recompilation with every new vulnerability.","status":"active","version":"1.3.0","language":"python","source_language":"en","source_url":"https://github.com/wbond/oscrypto","tags":["crypto","security","tls","ssl","asymmetric-encryption","symmetric-encryption","key-generation","os-native"],"install":[{"cmd":"pip install oscrypto","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Provides a fast, pure-Python ASN.1 parser upon which oscrypto is built.","package":"asn1crypto","optional":false}],"imports":[{"symbol":"generate_pair","correct":"from oscrypto.asymmetric import generate_pair"},{"symbol":"rsa_oaep_encrypt","correct":"from oscrypto.asymmetric import rsa_oaep_encrypt"},{"symbol":"aes_cbc_pkcs7_encrypt","correct":"from oscrypto.symmetric import aes_cbc_pkcs7_encrypt"},{"symbol":"TLSSocket","correct":"from oscrypto.tls import TLSSocket"},{"symbol":"rand_bytes","correct":"from oscrypto.util import rand_bytes"}],"quickstart":{"code":"from oscrypto.asymmetric import generate_pair, rsa_oaep_encrypt, rsa_oaep_decrypt\nfrom oscrypto.util import rand_bytes\n\n# Generate an RSA key pair\npublic_key, private_key = generate_pair('rsa', bit_size=2048)\n\n# Data to encrypt\noriginal_data = b'This is a secret message.'\n\n# Encrypt data using the public key\nencrypted_data = rsa_oaep_encrypt(public_key, original_data)\nprint(f'Encrypted data length: {len(encrypted_data)} bytes')\n\n# Decrypt data using the private key\ndecrypted_data = rsa_oaep_decrypt(private_key, encrypted_data)\n\nprint(f'Original data: {original_data.decode()}')\nprint(f'Decrypted data: {decrypted_data.decode()}')\nassert original_data == decrypted_data","lang":"python","description":"This quickstart demonstrates how to generate an RSA key pair, encrypt data using the public key with OAEP padding, and then decrypt it using the private key. This illustrates a fundamental asymmetric encryption workflow provided by `oscrypto.asymmetric`."},"warnings":[{"fix":"Review the 'Modern Cryptography' section in the oscrypto documentation and consider `pyca/pynacl` for new projects requiring modern cryptographic primitives.","message":"oscrypto explicitly states that many of its supported ciphers and hashes are for integration with legacy systems, and recommends modern cryptography libraries like `pyca/pynacl` or `scrypt` for new applications. Using `oscrypto` for modern crypto without proper cryptographic knowledge can lead to unsafe implementations.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Update code to check for 'mac' or handle both 'mac' and 'osx' if supporting older versions, or explicitly configure OpenSSL backend if 'osx' is strictly required for certain logic.","message":"In version 1.0.0, the `oscrypto.backend()` function was changed to return 'mac' instead of 'osx' when running on a Mac and not explicitly configured to use OpenSSL. Code relying on the exact string 'osx' will break.","severity":"breaking","affected_versions":"1.0.0+"},{"fix":"Review usage of `trust_list.get_path()` and adjust expectations or implementation if `map_vendor_oids` was previously used or if a broader set of CA certificates is required.","message":"In version 0.19.0, `trust_list.get_path()` no longer accepts the `map_vendor_oids` parameter and only includes CA certificates marked as trusted for TLS server authentication. This changed behavior may affect applications relying on the previous certificate list content.","severity":"breaking","affected_versions":"0.19.0+"},{"fix":"Update code that processes the output of `trust_list.get_list()` to unpack the 3-element tuples correctly.","message":"Version 0.16.0 changed the return format of `trust_list.get_list()`. It now returns a list of 3-element tuples (certificate byte string, set of trust OIDs, set of reject OIDs) instead of a list of certificate byte strings.","severity":"breaking","affected_versions":"0.16.0+"},{"fix":"For now, either downgrade OpenSSL to a version earlier than 3.0.10 or install `oscrypto` directly from the GitHub repository to get the unreleased fix: `pip install git+https://github.com/wbond/oscrypto`.","message":"oscrypto version 1.3.0 and earlier has a known bug that prevents it from detecting OpenSSL 3.0.10 or later, leading to `LibraryNotFoundError`. This affects users relying on newer OpenSSL versions. A fix exists on GitHub but is not yet released on PyPI.","severity":"gotcha","affected_versions":"<=1.3.0"},{"fix":"Prefer `PKCS#8` for private key serialization and storage whenever possible, avoiding `dump_openssl_private_key()` unless absolutely necessary for integration with systems that do not support PKCS#8.","message":"The `dump_openssl_private_key()` function is provided for compatibility with legacy systems, but its use is strongly discouraged. OpenSSL formats for private keys do not stretch the passphrase, making them vulnerable to brute-force attacks compared to PKCS#8, which offers superior encryption.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-09T19:33:32.345Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"If using a Linux distribution like Alpine, ensure a symlink exists from the specific libcrypto.so.X.Y version to libcrypto.so (e.g., `ln -s /usr/lib/libcrypto.so.1.1 /usr/lib/libcrypto.so`). If the issue is with OpenSSL version detection, consider upgrading to a newer oscrypto version (if available on PyPI with a fix) or installing the latest development version from the oscrypto GitHub repository. Alternatively, some users have found success by pinning their OpenSSL version to less than 3.0.10 or by setting the environment variable `OSCRYPTO_USE_CTYPES=true` to force oscrypto to use ctypes instead of cffi.","cause":"This error often occurs when oscrypto (especially versions 1.3.0 and earlier) fails to correctly parse the version of a multi-digit OpenSSL release (e.g., 3.0.10), or when the expected libcrypto.so symlink is missing on certain Linux distributions like Alpine Linux.","error":"oscrypto.errors.LibraryNotFoundError: Error detecting the version of libcrypto"},{"fix":"Install the cffi package using pip: `pip install cffi`. If you wish to explicitly avoid cffi and use ctypes (which is built into Python's standard library), set the environment variable `OSCRYPTO_USE_CTYPES=true` before running your application.","cause":"oscrypto prefers to use the cffi module for Foreign Function Interface (FFI) if it is installed. This error occurs when cffi is not found in the Python environment, preventing oscrypto from using its preferred FFI backend.","error":"ModuleNotFoundError: No module named 'cffi'"},{"fix":"Ensure that the input `source` provided to `oscrypto.asymmetric.load_private_key` is a correctly formatted private key (e.g., PKCS#8 or OpenSSL PEM/DER format). Verify the integrity and encoding of your key file. A common cause for key loading issues is incorrect line endings (CRLF instead of LF) in the key file, especially when transferring between Windows and Unix/Linux systems. Convert line endings to LF if necessary (e.g., using `dos2unix` or a text editor like Notepad++).","cause":"This KeyError typically arises when `oscrypto.asymmetric.load_private_key` attempts to parse ASN.1 encoded bytes that are malformed, not a valid private key structure, or a different cryptographic structure (like a PKCS#12 PDU). The underlying `asn1crypto` library might raise a KeyError when an unexpected OID is encountered during type determination.","error":"KeyError: '1.2.840.113549.1.7.1' (or similar OID) when calling oscrypto.asymmetric.load_private_key"}],"ecosystem":"pypi","meta_description":null,"install_score":50,"install_tag":"draft","quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"install_checks":{"last_tested":"2026-04-09","tag":"draft","tag_description":"notable install failures or slow imports","results":[{"runtime":"python:3.10-alpine","variant":"default","exit_code":1,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","variant":"default","exit_code":0,"import_time_s":0.1,"mem_mb":5.3,"disk_size":"21M"},{"runtime":"python:3.11-alpine","variant":"default","exit_code":1,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","variant":"default","exit_code":0,"import_time_s":0.2,"mem_mb":6.3,"disk_size":"23M"},{"runtime":"python:3.12-alpine","variant":"default","exit_code":1,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","variant":"default","exit_code":0,"import_time_s":0.2,"mem_mb":5.9,"disk_size":"15M"},{"runtime":"python:3.13-alpine","variant":"default","exit_code":1,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","variant":"default","exit_code":0,"import_time_s":0.19,"mem_mb":6.4,"disk_size":"15M"},{"runtime":"python:3.9-alpine","variant":"default","exit_code":1,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","variant":"default","exit_code":0,"import_time_s":0.12,"mem_mb":5.2,"disk_size":"21M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":0}]}}