""" Android Security 组件 — KeyChain, NetworkSecurityPolicy, AppUriAuthenticationPolicy 等 方法签名完全对齐 Android SDK (android.security 包) """ from typing import Any, Callable, Dict, List, Optional from .._core import Stub, AndroidOnlyError # ═══════════════════════════════════════════════════════════════ # KeyChain # ═══════════════════════════════════════════════════════════════ class KeyChain(Stub): """KeyChain — 系统级密钥链访问 (桌面环境不可用)""" ACTION_KEYCHAIN_CHANGED = "android.security.action.KEYCHAIN_CHANGED" ACTION_KEY_ACCESS_CHANGED = "android.security.action.KEY_ACCESS_CHANGED" EXTRA_KEY_ACCESSIBLE = "android.security.extra.KEY_ACCESSIBLE" EXTRA_KEY_ALIAS = "android.security.extra.KEY_ALIAS" EXTRA_RESULT = "android.security.extra.RESULT" def __init__(self): super().__init__() @staticmethod def createInstallIntent() -> Any: """创建安装证书的 Intent (Android-only)""" raise AndroidOnlyError("KeyChain.createInstallIntent() 仅在 Android 设备上可用") @staticmethod def choosePrivateKeyAlias(activity: Any, response: Any, keyTypes: Optional[List[str]] = None, issuers: Optional[List[Any]] = None, host: Optional[str] = None, port: int = -1, alias: Optional[str] = None): """选择私钥别名 (Android-only)""" raise AndroidOnlyError("KeyChain.choosePrivateKeyAlias() 仅在 Android 设备上可用") @staticmethod def isKeyAlgorithmSupported(algorithm: str) -> bool: """检查密钥算法是否支持""" supported = {"RSA", "EC", "DSA", "AES", "HmacSHA256", "HmacSHA1"} return algorithm in supported @staticmethod def isBoundKeyAlgorithm(algorithm: str) -> bool: """检查是否是绑定到硬件的密钥算法 (桌面环境不支持)""" return False @staticmethod def getPrivateKey(context: Any, alias: str) -> Any: """获取私钥 (Android-only)""" raise AndroidOnlyError("KeyChain.getPrivateKey() 仅在 Android 设备上可用") @staticmethod def getCertificateChain(context: Any, alias: str) -> Optional[List[Any]]: """获取证书链 (Android-only)""" raise AndroidOnlyError("KeyChain.getCertificateChain() 仅在 Android 设备上可用") def toString(self) -> str: return "KeyChain(desktop-stub)" def hashCode(self) -> int: return hash("android.security.KeyChain") & 0x7FFFFFFF def equals(self, other) -> bool: return isinstance(other, KeyChain) # ═══════════════════════════════════════════════════════════════ # AppUriAuthenticationPolicy # ═══════════════════════════════════════════════════════════════ class AppUriAuthenticationPolicy(Stub): """AppUriAuthenticationPolicy — URI 认证策略 (Android 11+)""" def __init__(self): super().__init__() self._rules: Dict[str, List[str]] = {} def addAppAndUriMapping(self, app: Any, uri: Any, alias: str): """添加应用与 URI 映射""" app_pkg = str(app) if app else "" uri_str = str(uri) if uri else "" if app_pkg not in self._rules: self._rules[app_pkg] = [] self._rules[app_pkg].append(uri_str) def getAppAndUriMappings(self) -> Dict[str, List[str]]: """获取所有规则映射""" return dict(self._rules) def toString(self) -> str: return f"AppUriAuthenticationPolicy(rules={self._rules})" def hashCode(self) -> int: return hash(str(self._rules)) & 0x7FFFFFFF def equals(self, other) -> bool: if not isinstance(other, AppUriAuthenticationPolicy): return False return self._rules == other._rules # ═══════════════════════════════════════════════════════════════ # KeyChainAliasResponse # ═══════════════════════════════════════════════════════════════ class KeyChainAliasResponse(Stub): """KeyChainAliasResponse — 密钥别名选择响应""" def __init__(self, alias: Optional[str] = None): super().__init__() self._alias = alias def getAlias(self) -> Optional[str]: """获取选定的密钥别名""" return self._alias def toString(self) -> str: return f"KeyChainAliasResponse(alias={self._alias})" def hashCode(self) -> int: return hash(self._alias) & 0x7FFFFFFF def equals(self, other) -> bool: if not isinstance(other, KeyChainAliasResponse): return False return self._alias == other._alias # ═══════════════════════════════════════════════════════════════ # NetworkSecurityPolicy # ═══════════════════════════════════════════════════════════════ class NetworkSecurityPolicy(Stub): """NetworkSecurityPolicy — 网络安全策略""" _instance: Optional["NetworkSecurityPolicy"] = None def __init__(self): super().__init__() self._cleartext_permitted = True @staticmethod def getInstance() -> "NetworkSecurityPolicy": """获取全局 NetworkSecurityPolicy 实例""" if NetworkSecurityPolicy._instance is None: NetworkSecurityPolicy._instance = NetworkSecurityPolicy() return NetworkSecurityPolicy._instance def isCleartextTrafficPermitted(self, host: Optional[str] = None) -> bool: """检查是否允许明文流量 (桌面默认允许)""" return self._cleartext_permitted def setCleartextTrafficPermitted(self, permitted: bool): """设置是否允许明文流量""" self._cleartext_permitted = permitted def toString(self) -> str: return f"NetworkSecurityPolicy(cleartextPermitted={self._cleartext_permitted})" def hashCode(self) -> int: return id(self) & 0x7FFFFFFF def equals(self, other) -> bool: return self is other # ═══════════════════════════════════════════════════════════════ # __all__ # ═══════════════════════════════════════════════════════════════ __all__ = [ "KeyChain", "AppUriAuthenticationPolicy", "KeyChainAliasResponse", "NetworkSecurityPolicy", ]