PyObjC Framework Security
PyObjC is a bridge between Python and Objective-C, enabling Python scripts to use and extend existing Objective-C class libraries on macOS. The `pyobjc-framework-security` package provides Python wrappers for Apple's Security framework, allowing developers to access macOS security services like authentication, authorization, and secure data handling from Python. The current version is 12.1.
Warnings
- breaking Support for Python 3.9 was dropped in PyObjC version 12.0.
- breaking Support for Python 3.8 was dropped in PyObjC version 11.0.
- breaking The `IMServicePlugIn` framework bindings were removed in PyObjC 10.0 as the entire framework was deprecated in macOS 10.13 and removed in macOS 14.
- gotcha PyObjC 10.3 initially broke the ability to use `__init__` when a class defined `__new__`. While partially re-enabled in 10.3.1 for user-defined `__new__` methods, `__init__` cannot be used with `__new__` provided by PyObjC itself.
- gotcha PyObjC 11.1 aligned the core bridge's behavior with `clang's` documentation for Automatic Reference Counting (ARC) regarding initializer methods. Methods in the 'init' family now correctly steal a reference to `self` and return a new reference.
- deprecated Several legacy Security.framework APIs, such as `SecKeychainItemCopyAttributesAndData` and `SecIdentityCopyPreference`, are not available from Python as they are soft-deprecated or explicitly not exposed by PyObjC.
Install
-
pip install pyobjc-framework-security
Imports
- Security
import Security
Quickstart
import Security
import objc
def generate_random_bytes(length):
"""Generates cryptographically secure random bytes using Security.framework."""
# SecRandomCopyBytes is a C function in the Security framework.
# We need to load it explicitly if not already exposed as a Python function.
# It's usually exposed automatically, but this demonstrates explicit loading for C functions.
# The 'b' format indicates a C array of bytes.
_functions = [
('SecRandomCopyBytes', 'iI^v'), # OSStatus SecRandomCopyBytes(SecRandomGeneratorRef, size_t, void *)
]
# Load the function from the Security framework bundle
# Security.bundle() is the NSBundle for the Security framework
# Use globals() to make the loaded function available directly
objc.loadBundleFunctions(Security.bundle(), globals(), _functions)
buffer = bytearray(length)
# kSecRandomDefault is typically passed as the first argument (generatorRef)
# Its value is usually 0 for the default generator, or None in PyObjC often works for NULL
# The correct value for kSecRandomDefault is implicitly handled by PyObjC for simple cases.
# If the function signature is 'iI^v', the 'I' is size_t (length), '^v' is void* (buffer).
# PyObjC often allows passing bytearray directly for buffer pointers.
# SecRandomCopyBytes(generator, count, bytes)
# We use 0 for kSecRandomDefault, and 'buffer' for the output bytes.
status = SecRandomCopyBytes(0, length, buffer)
if status == 0: # noErr
return bytes(buffer)
else:
raise RuntimeError(f"Failed to generate random bytes: {status}")
if __name__ == "__main__":
try:
random_data = generate_random_bytes(16)
print(f"Generated 16 random bytes: {random_data.hex()}")
except Exception as e:
print(f"Error: {e}")