Пример #1
0
    def _pythonify_key(self, key: SecKeyRef):
        assert isinstance(
            key, SecKeyRef
        ), f'Expected key to be of type SecKeyRef, but got: {type(key)}'

        error, der_key = SecItemExport(
            key,
            kSecFormatOpenSSL,  # outputFormat - OpenSSL == DER
            0,  # flags
            None,  # keyParams
            None,  # exportedData
        )

        if error or not der_key:
            raise KeyringError(f'Error calling SecItemExport: {error}')

        if self.key_class_type in [
            OSXKeyChainKeyClassType.Private.value,
            OSXKeyChainKeyClassType.Symmetric.value,
        ]:
            return serialization.load_der_private_key(
                der_key, password=None, backend=default_backend()
            )

        return serialization.load_der_public_key(der_key, default_backend())
Пример #2
0
    def get_password(self, service: Optional[str], username: Optional[str]):
        """
        Returns all keyring / enclave keys matching kSecAttrLabel = service and kSecAttrApplicationTag = username,
        python-wrapped.
        If a single key is matched, the result is a list of size 1.

        :param service: If set, will lookup the key with kSecAttrLabel = service
        :param username: If set, will lookup the key with kSecAttrApplicationTag = username
        :return: A python-wrapped private / public key of the key.
        """
        query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, None, None)
        CFDictionarySetValue(query, kSecClass, kSecClassKey)
        CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll)
        CFDictionarySetValue(query, kSecReturnRef, 1)

        if service:
            CFDictionarySetValue(query, kSecAttrLabel, service)

        if username:
            CFDictionarySetValue(
                query, kSecAttrApplicationTag, username.encode('utf-8')
            )

        if self.access_group:
            CFDictionarySetValue(query, kSecAttrAccessGroup, self.access_group)

        error, res = SecItemCopyMatching(query, None)
        if error:
            raise KeyringError(f'Error calling SecItemCopyMatching: {error}')

        return [self._pythonify_key(key) for key in res]
Пример #3
0
    def _get_access_control(self) -> Optional[SecAccessControlRef]:
        # Do note: Using access control, or the secure enclave, requires the executing binary (i.e. python interpreter)
        # to be code signed with specific apple entitlements.
        if not self.use_secure_enclave:
            return None

        access_control, error = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
            kSecAccessControlPrivateKeyUsage,
            None,
        )
        if error or not access_control:
            raise KeyringError(f'Failed in SecAccessControlCreateWithFlags: {error}')

        return access_control
Пример #4
0
    def _get_sec_key_from_password(self, password: Union[str, bytes]):
        if os.path.isfile(password):
            with open(password, 'rb') as f:
                password = f.read()

        key_params = SecItemImportExportKeyParameters(
            keyAttributes=(kSecAttrIsExtractable,), passphrase=self.key_password
        )
        error, input_format, item_type, out_items = SecItemImport(
            password,
            None,  # fileNameOrExtension
            None,  # inputFormat
            None,  # itemType
            0,  # flags
            key_params,  # keyParameters
            None,  # keychain
            None,  # outItems
        )

        if error or not out_items:
            raise KeyringError(f'Error calling SecItemImport: {error}')

        return out_items[-1]
Пример #5
0
 def delete_password(self, servicename, username):
     raise KeyringError()
Пример #6
0
 def set_password(self, servicename, username, password):
     raise KeyringError()