
系列安全进阶篇·第34篇。之前的安全加固篇讲了应用层的混淆和加密有安全领域的读者追问“应用层的加密密钥如果放在沙箱里root后不还是能被dump出来吗鸿蒙有没有芯片级的硬安全方案” 这个问题问到了操作系统的根子上。今天我们将揭开HarmonyOS安全底座的神秘面纱深入通用密钥库系统HUKS和可信执行环境TEE实现密钥不出安全芯片的终极防护。我们将把之前存在沙箱里的AES密钥迁移到HUKS中并利用TEE进行指纹认证的私钥签名。全程基于API23含官方文档未涉及的“密钥访问控制列表ACL”和“安全启动链”验证技巧。一、前言为什么应用层加密不够用在之前的《安全加固实战》中我们使用CryptoArchitectureKit进行了AES加密但密钥Key是存储在应用沙箱的文件或内存中的。风险点Root/越狱攻击者获取Root权限后可以读取沙箱内的所有文件包括你的密钥文件。内存Dump攻击者通过调试工具如IDA ProAttach到进程Dump内存空间可以搜索到密钥的明文或密文。侧信道攻击通过分析功耗、电磁辐射等物理信息推测密钥。为了对抗这些高级攻击现代操作系统引入了TEETrusted Execution Environment可信执行环境。它是在CPU内部隔离出来的一个安全区域与主操作系统Rich OS如Android/HarmonyOS并行运行。TEE有自己的CPU、内存和存储主系统无法直接访问TEE的内部数据。HUKSUniversal KeyStore System则是HarmonyOS提供的密钥管理系统它负责对接底层的TEE或安全芯片SE为上层的CryptoKit提供统一的API。核心结论密钥不出TEE明文不出安全世界Secure World。这是金融级安全的底线。二、核心概念辨析REE vs TEE理解这两个概念是看懂本文的前提。维度REE (Rich Execution Environment)TEE (Trusted Execution Environment)通俗叫法普通世界 (Normal World)安全世界 (Secure World)运行环境Android/HarmonyOS主系统安全OS (如ARM TrustZone)资源访问可访问所有硬件资源只能访问分配给它的硬件资源安全性易受病毒、Root攻击物理隔离抗攻击能力强典型应用微信、淘宝、游戏指纹支付、人脸识别、DRM、HUKS数据可见性可以看到TEE的存在但看不到其内部数据完全封闭数据加密存储三、代码实现从“软密钥”到“硬密钥”我们将改造之前的AESCryptoUtil不再自己生成和管理密钥而是委托给HUKS。3.1 生成非对称密钥对用于签名/验签在TEE中生成RSA或ECC密钥对私钥永远留在TEE里只导出公钥。创建entry/src/main/ets/security/HuksManager.etsimport { huks } from kit.UniversalKeyStoreKit import { BusinessError } from kit.BasicServicesKit export class HuksManager { private static readonly KEY_ALIAS Demo_AES_Key_Alias // 密钥别名用于索引 private static readonly RSA_KEY_ALIAS Demo_RSA_Key_Alias /** * 在TEE中生成AES对称密钥 * 注意此操作不返回密钥明文只返回状态 */ static async generateAesKey(): Promiseboolean { try { const properties: huks.HuksParam[] [ { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES }, { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 }, { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT }, { tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_CBC }, { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksPadding.HUKS_PADDING_PKCS7 }, { tag: huks.HuksTag.HUKS_TAG_DIGEST, value: huks.HuksDigest.HUKS_DIGEST_SHA256 }, { tag: huks.HuksTag.HUKS_TAG_AUTH_STORAGE_LEVEL, value: huks.HuksAuthStorageLevel.HUKS_AUTH_STORAGE_LEVEL_DE // 仅在设备解锁后可用 } ] const options: huks.HuksOptions { properties } // 关键调用HUKS生成密钥密钥存储在安全环境中 await huks.generateKey(this.KEY_ALIAS, options) console.log(HUKS AES密钥生成成功密钥未离开TEE) return true } catch (err) { const e err as BusinessError console.error(HUKS密钥生成失败: ${e.code}, ${e.message}) return false } } /** * 使用TEE中的AES密钥进行加密 * param plainText 明文 * returns Base64密文 */ static async encryptWithHuks(plainText: string): Promisestring { try { const properties: huks.HuksParam[] [ { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES }, { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT }, { tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_CBC }, { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksPadding.HUKS_PADDING_PKCS7 } ] const options: huks.HuksOptions { properties, inData: new TextEncoder().encode(plainText) // 明文送入TEE } // 调用HUKS加密密钥不出TEE const outData await huks.encrypt(this.KEY_ALIAS, options) return btoa(String.fromCharCode(...outData.data)) } catch (err) { console.error(HUKS加密失败:, err) throw err } } /** * 使用TEE中的AES密钥进行解密 * param cipherText Base64密文 * returns 明文 */ static async decryptWithHuks(cipherText: string): Promisestring { try { const properties: huks.HuksParam[] [ { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES }, { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT }, { tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, value: huks.HuksCipherMode.HUKS_MODE_CBC }, { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksPadding.HUKS_PADDING_PKCS7 } ] const encryptedData Uint8Array.from(atob(cipherText), c c.charCodeAt(0)) const options: huks.HuksOptions { properties, inData: encryptedData } // 调用HUKS解密密钥不出TEE const outData await huks.decrypt(this.KEY_ALIAS, options) return new TextDecoder().decode(outData.data) } catch (err) { console.error(HUKS解密失败:, err) throw err } } /** * 生成RSA密钥对用于生物识别认证后的签名 */ static async generateRsaKey(): Promisevoid { const properties: huks.HuksParam[] [ { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_RSA }, { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_RSA_KEY_SIZE_2048 }, { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY }, { tag: huks.HuksTag.HUKS_TAG_DIGEST, value: huks.HuksDigest.HUKS_DIGEST_SHA256 }, { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksPadding.HUKS_PADDING_PKCS1_V1_5 } ] await huks.generateKey(this.RSA_KEY_ALIAS, { properties }) console.log(RSA密钥对生成成功私钥在TEE中) } /** * 使用TEE中的RSA私钥进行签名常用于支付验证 * param data 待签名数据如订单信息 * returns 签名结果 */ static async signWithRsa(data: Uint8Array): PromiseUint8Array { const properties: huks.HuksParam[] [ { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_RSA }, { tag: huks.HuksTag.HUKS_TAG_PURPOSE, value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN }, { tag: huks.HuksTag.HUKS_TAG_DIGEST, value: huks.HuksDigest.HUKS_DIGEST_SHA256 }, { tag: huks.HuksTag.HUKS_TAG_PADDING, value: huks.HuksPadding.HUKS_PADDING_PKCS1_V1_5 } ] const options: huks.HuksOptions { properties, inData: data } const result await huks.sign(this.RSA_KEY_ALIAS, options) return result.data } }3.2 结合生物识别指纹/人脸TEE的另一个核心功能是处理生物识别数据。这些数据如指纹特征模板绝不离开TEE。我们可以通过HUKS的访问控制要求只有指纹验证通过后才能使用特定的密钥。修改EntryAbility.ets的onCreateimport { huks } from kit.UniversalKeyStoreKit import { userIAM } from kit.UserAuthenticationKit async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promisevoid { // 1. 初始化HUKS密钥 await HuksManager.generateAesKey() // 2. 配置密钥访问控制需要指纹认证 const authChallenge await userIAM.getUserAuthInstance({ challenge: new Uint8Array([1, 2, 3, 4]), // 随机挑战值 authType: userIAM.AuthType.BIOMETRIC, // 生物识别 biometricLevel: userIAM.BiometricLevel.STRONG // 强安全级别指纹/3D人脸 }).startAuth() // 3. 将认证结果传递给HUKS解锁密钥 const unlockProperties: huks.HuksParam[] [ { tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT }, { tag: huks.HuksTag.HUKS_TAG_USER_AUTH_SECURE_ID, value: authChallenge.secureUserId // 关联认证会话 } ] await huks.unwrapKey(HuksManager.KEY_ALIAS, { properties: unlockProperties, inData: new Uint8Array() // 实际开发中这里传入加密后的密钥材料 }) console.log(密钥已通过指纹认证解锁可用于解密数据) }四、踩坑记录官方文档没写的内核细节密钥别名Alias的唯一性HUKS的密钥别名是全局的跨应用。如果你的应用使用了default_alias可能会被其他应用覆盖或冲突。务必使用带应用包名的唯一别名如com.example.shop.aes_key。TEE容量限制TEE的存储空间和运算能力是有限的。不要在TEE中存储大文件如图片也不要在TEE中进行长时间的计算。HUKS适合存储密钥、证书、少量敏感数据如Token。大文件加密应使用TEE中的密钥在REE中进行通过DMA等安全通道传输数据。密钥访问控制列表ACLHUKS支持设置密钥的使用条件如HUKS_TAG_AUTH_STORAGE_LEVEL需要设备锁屏密码、HUKS_TAG_USER_AUTH_TYPE需要生物识别。设置ACL后即使应用被攻破攻击者也无法在未解锁设备或未通过生物识别的情况下使用密钥。安全启动链HUKS的安全性依赖于系统的安全启动。如果Bootloader被解锁如RootTEE的安全性也会大打折扣。应用层无法检测Bootloader状态这是系统底层的责任。调试与发布环境在调试环境DebugHUKS可能运行在软件模拟的TEE中性能较差。在发布环境Release必须使用硬件支持的TEE。测试时要注意区分。