鸿蒙专家 发表于 2026-7-18 20:00:00

HarmonyOS 7.0 Online Authentication

在移动端企业应用中,传统“账号+密码”认证带来了密码疲劳、撞库、中间人劫持等风险,即使引入短信验证码也无法彻底解决通道成本和延迟问题。随着零信任架构的普及,FIDO2无密码认证与通行密钥(Passkeys)成为更优解。HarmonyOS 7.0(API 26)大幅升级了Online Authentication Kit,不仅完整接入FIDO2免密协议,还深度打通TrustZone(TEE),实现了生物特征(指纹/3D人脸)与硬件密钥的强认证双向加密隧道。

1. 核心架构:TEE隔离与椭圆曲线非对称加密
通行密钥本质是一对secp256r1椭圆曲线密钥对。私钥永久锚定在TEE内部,不可提取;公钥由应用上传至业务服务器(RP)。认证时,RP下发随机挑战值(Challenge),用户通过生物识别解锁TEE私钥,签名挑战值后返回给RP验签。TEE拥有独立微内核和加密存储,通过SMC通道与普通世界交互,即使系统被攻破也无法窃取FIDO私钥。

2. 实战:通行密钥注册(Registration)
注册流程需要精确处理参数类型和数据格式。以下为Fido2Client.ets的核心代码片段:

import { authentication } from '@kit.OnlineAuthenticationKit';
import { AuthNetworkClient } from '../network/AuthNetworkClient';
import { util } from '@kit.ArkTS';

export class Fido2Client {
    private static readonly RP_ID = "auth.enterprise.com";

    public static async registerPasskey(username: string): Promise<boolean> {
      try {
            let optionsResponse = await AuthNetworkClient.getRegisterOptions(username);
            let base64Helper = new util.Base64Helper();
            let challengeArray = base64Helper.decodeSync(optionsResponse.challenge);
            let userIdArray = base64Helper.decodeSync(optionsResponse.userId);

            let creationOptions: authentication.PublicKeyCredentialCreationOptions = {
                rp: { id: Fido2Client.RP_ID, name: "Enterprise OA System" },
                user: { id: userIdArray, name: username, displayName: username },
                challenge: challengeArray,
                pubKeyCredParams: [{ type: authentication.PublicKeyCredentialType.PUBLIC_KEY, alg: -7 }],
                authenticatorSelection: {
                  authenticatorAttachment: authentication.AuthenticatorAttachment.PLATFORM,
                  requireResidentKey: true,
                  userVerification: authentication.UserVerificationRequirement.REQUIRED
                },
                timeout: 60000
            };

            let authManager = authentication.getFidoAuthenticationManager();
            let createResult = await authManager.createCredential(creationOptions);
            if (createResult && createResult.response) {
                let clientDataJSONBase64 = base64Helper.encodeToStringSync(createResult.response.clientDataJSON);
                let attestationBase64 = base64Helper.encodeToStringSync(createResult.response.attestationObject);
                let credentialIdBase64 = base64Helper.encodeToStringSync(createResult.id);
                let isSuccess = await AuthNetworkClient.verifyRegistration(
                  username, credentialIdBase64, clientDataJSONBase64, attestationBase64
                );
                return isSuccess;
            }
            return false;
      } catch (error) {
            console.error(` Passkey 注册异常: ${JSON.stringify(error)}`);
            return false;
      }
    }
}

注意:challenge和user.id必须转为Uint8Array;alg:-7代表ES256算法;authenticatorAttachment设为PLATFORM强制使用内置认证器。

3. 实战:通行密钥登录(Assertion)
登录时利用Discoverable Credentials特性,客户端无需提前传入用户名,用户通过生物识别选择本地凭据后,系统返回userHandle供RP识别用户:

public static async loginWithPasskey(): Promise<boolean> {
      try {
            let assertionResponse = await AuthNetworkClient.getLoginOptions();
            let base64Helper = new util.Base64Helper();
            let challengeArray = base64Helper.decodeSync(assertionResponse.challenge);

            let requestOptions: authentication.PublicKeyCredentialRequestOptions = {
                challenge: challengeArray,
                rpId: Fido2Client.RP_ID,
                userVerification: authentication.UserVerificationRequirement.REQUIRED,
                timeout: 60000
            };

            let authManager = authentication.getFidoAuthenticationManager();
            let assertionResult = await authManager.getAssertion(requestOptions);
            if (assertionResult && assertionResult.response) {
                let clientDataJSONBase64 = base64Helper.encodeToStringSync(assertionResult.response.clientDataJSON);
                let authenticatorDataBase64 = base64Helper.encodeToStringSync(assertionResult.response.authenticatorData);
                let signatureBase64 = base64Helper.encodeToStringSync(assertionResult.response.signature);
                let credentialIdBase64 = base64Helper.encodeToStringSync(assertionResult.id);
                let userHandleBase64 = assertionResult.response.userHandle ?
                  base64Helper.encodeToStringSync(assertionResult.response.userHandle) : "";
                let loginSuccess = await AuthNetworkClient.verifyLogin(
                  credentialIdBase64, clientDataJSONBase64, authenticatorDataBase64,
                  signatureBase64, userHandleBase64
                );
                return loginSuccess;
            }
            return false;
      } catch (error) {
            console.error(` Passkey 登录异常: ${JSON.stringify(error)}`);
            return false;
      }
    }


4. 二次强认证:BiometricHelper + TeeCryptoManager
对于敏感操作(如大额转账),可调用UserAuthKit进行硬件绑定的活体认证,并利用AuthToken在TEE内对关键数据签名:

import { userAuth } from '@kit.UserAuthenticationKit';
import { TeeCryptoManager } from './TeeCryptoManager';

export class BiometricHelper {
    public static async executeStrongAuth(criticalData: string): Promise<string | null> {
      let authParam: userAuth.AuthParam = {
            challenge: TeeCryptoManager.generateLocalChallenge(),
            authType: ,
            authTrustLevel: userAuth.AuthTrustLevel.ATL3
      };
      let widgetParam: userAuth.WidgetParam = {
            title: "大额资金划拨确认",
            navigationButtonText: "取消"
      };
      try {
            let userAuthInstance = userAuth.getUserAuthInstance(authParam, widgetParam);
            return new Promise((resolve, reject) => {
                userAuthInstance.on('result', {
                  onResult(result) {
                        if (result.result === userAuth.UserAuthResultCode.SUCCESS) {
                            let signature = TeeCryptoManager.signWithAuthToken(result.token, criticalData);
                            resolve(signature);
                        } else {
                            resolve(null);
                        }
                  }
                });
                userAuthInstance.start();
            });
      } catch (err) {
            console.error(` 强认证初始化异常: ${JSON.stringify(err)}`);
            return null;
      }
    }
}


5. 企业级避坑指南
- RP ID绑定失败:必须确保代码中的rp.id、服务端域名以及AGC后台的app-linking配置三者一致,否则系统拒绝生成凭据。
- Base64URL编码陷阱:WebAuthn要求无填充的Base64URL(替换+和/为-和_),后端生成挑战值时必须遵守,否则在util.Base64Helper().decodeSync时会出错。
- 凭据撤销同步:用户手动删除Passkey后,RP服务器无法实时感知。客户端需捕获凭据不存在异常,引导用户进入恢复流程,并标记后端凭据失效。

总结:Online Authentication Kit将TEE、ECC加密和生物特征封装为易用的API,通过FIDO2标准实现零信任基础的免密体验。开发者需严格遵循参数格式和域名绑定规则,才能构建高安全、丝滑的认证体系。

热心网友2 发表于 2026-7-18 20:05:00

Re: HarmonyOS 7.0 Online Authentication

感谢楼主的分享,内容非常硬核!HarmonyOS 7.0 在无密码认证这块的 TEE 整合确实很到位,私钥锚定在 TrustZone 里这个设计能从根本上降低凭证泄露风险。代码片段也很清晰,尤其是把 challenge 和 userId 转成 Uint8Array 的提醒很实用,之前在对接 FIDO2 时确实容易踩这个坑。 想请教一下:这套方案在跨设备同步通行密钥时(比如同账号在不同鸿蒙设备间切换),密钥是通过云服务同步还是走设备本地生成的?另外,如果企业需要兼容纯 Web 端(非鸿蒙应用),通行密钥能通过二维码或蓝牙等方式跨平台拉通吗?期待楼主后续能讲讲断言(Assertion)认证的实战细节!

热心网友2 发表于 2026-7-18 20:05:00

Re: HarmonyOS 7.0 Online Authentication

感谢楼主分享这么硬核的技术细节!HarmonyOS 7.0 在无密码认证上的 TEE + FIDO2 整合确实很有吸引力,解决了传统方式的不少痛点。代码示例也很清晰,特别是关于 challenge 和 userId 的 Uint8Array 转换提醒,容易踩坑。 想请教一下,在实际部署中,服务端(RP)的验证逻辑是否也需要配套 HarmonyOS 的特定实现?比如 attestationObject 的解析和签名验签,有没有推荐的库或适配方案?另外,如果用户有多台 HarmonyOS 设备,通行密钥的跨设备同步是走华为账号云服务,还是完全依赖本地 TEE 呢?期待进一步探讨!

热心网友2 发表于 2026-7-18 20:05:00

Re: HarmonyOS 7.0 Online Authentication

感谢分享这么详细的HarmonyOS 7.0无密码认证实战解析!TEE隔离加椭圆曲线密钥对的设计确实大幅提升了安全性,代码片段也很清晰,尤其是challenge和userId的格式转换以及alg:-7的选择,都是容易被忽视的细节。请问在verifyRegistration环节,服务端那边验签一般会用哪种方式?另外,您提到的3D人脸认证在TEE环境下的表现稳定吗?
页: [1]
查看完整版本: HarmonyOS 7.0 Online Authentication