用户在确认窗口里看到“签署展品借阅凭证”服务端却收到另一份内容的签名这种问题无法通过给按钮加锁图标解决。可信确认最核心的要求是用户看见、明确同意和最终验证的内容保持一致。数字盾相关能力强调可信界面、输入与签名保护。实验使用一份无实际法律效力的测试凭证。公开能力介绍不等于所有应用已经具备调用资格在具体接口与接入资质确认前不用普通弹窗或旧版密钥接口冒充数字盾调用。先确定签名对象的唯一表达同一业务内容可能有多种 JSON 表达字段顺序不同、空字段省略、日期格式不同都可能产生不同字节。客户端与服务端应选择一致的规范化规则对最终字节计算摘要。凭证编号、展品编号、借阅期限、动作类型和挑战值都需要纳入保护范围。界面展示的友好名称可以保留但不能只签名称而忽略唯一编号。以下为应用自己的待确认结构。interfaceTestReceipt{schemaVersion:number;receiptId:string;exhibitId:string;action:acknowledge-test-receipt;validUntil:string;challenge:string;}序列化算法应有固定测试向量。遇到未支持的版本直接拒绝不在接收端默默补默认值后继续验证。测试材料明确标注模拟用途避免让体验者误以为正在签署真实凭证。可信界面承担什么职责应用普通页面负责说明业务上下文可信确认环节负责呈现实际待确认的重要信息并获取用户操作。两者之间不能隐藏关键差异例如普通页面说“查看”最终动作却是“授权”。当系统可信界面对文本长度、字段类型或交互方式有约束时应按文档映射业务信息。不能通过截断文本隐藏关键内容也不能把所有信息塞进无法辨识的摘要后声称用户已理解。需要系统证明的内容必须来自真实能力返回。普通 ArkUI 对话框只能验证业务流程和取消行为不能证明可信输入、受保护显示或安全硬件参与了签名。用户取消是正常结果确认流程至少区分等待、成功、取消、失败和过期。取消后不自动再次拉起失败重试时重新检查挑战是否仍然有效。应用切到后台后收到回调也不能直接改变已经关闭的业务页面。每次任务绑定唯一 requestId。旧任务完成时只有当前业务仍等待同一个请求才能消费结果。签名材料保存时间应尽可能短日志里不记录可复用的完整结果。如果用户在确认期间编辑了凭证内容应使当前确认失效。不能把旧摘要对应的签名挂到新版本凭证上。服务端以签名覆盖的版本作为唯一依据。服务端验证不能省略上下文验证端首先按官方要求检查可信来源与签名再核对凭证内容、挑战、动作和期限。密钥可信不等于任意业务都被授权另一个场景产生的签名不能直接用于当前操作。挑战的消费与凭证状态变更需要一致性保护。若网络在成功后中断客户端重试应得到同一业务结果不能创建第二份凭证。这里的幂等键属于业务协议不能拿设备标识替代。安全硬件保护私钥与业务语义正确是两层问题。即使密钥无法导出错误的字段映射仍然可能让用户确认错误内容因此字段一致性测试必须独立存在。验收用例围绕内容变化展开先签署固定测试凭证再逐项修改展品编号、动作、期限和挑战确认旧签名无法被接受。随后覆盖取消、超时、重复提交、旧页面回调和设备能力不可用。对可信界面的验收需要支持设备和官方接入链路。录屏可以辅助说明用户看见什么但不能单独证明安全能力执行成功还需要脱敏的请求关联、验证结果及设备环境。在接口未确认阶段Demo 可以完成规范化测试、业务状态机和验证端契约。它们应被标为流程原型。取得实际能力后再补系统调用和真实验签才能把文章升级为完整接入实战。让确认内容变化成为独立测试向量修改内容需要验证的结果只改变无语义的序列化字段顺序按选定规范化规则得到一致字节改变展品或动作得到不同待签内容旧结果不可复用新挑战替换旧挑战旧确认不完成新请求直接签任意 JSON 实现较短但双方规范不一致时难以定位失败固定版本的规范化契约增加前置工作能把签名争议落到具体字节。先用固定向量核对规范化再实现取消与幂等最后接可信界面和正式验证。普通弹窗仅承担前两个阶段的流程调试。参考华为开发者能力介绍。数字盾具体版本、开放范围及可信界面接口需另行核实旧有密钥存储或普通签名接口不能代替数字盾能力。可信文本、挑战与认证令牌的归属可信确认前先检查文本排版。结果非零时停止调用保留不能展示的位置。确认入口需要已有 authID、合法图片和 32 字节挑战挑战来自 HUKS 会话初始化不自行生成一个随机数替代。PIN 认证路径把相同文本放入 authContent避免展示内容与认证内容分叉。用户取消和 SDK 错误向调用方传播不返回成功令牌。页面只显示令牌字节数不把完整令牌输出到日志。exportclassTrustedProbe{asynccheckText(text:string):PromisetrustedAuthentication.TextCheckResult{returntrustedAuthentication.checkConfirmUITextFormat(InputRules.required(text,confirmation,2048));}asyncconfirm(challengeHex:string,authId:string,text:string,image:ArrayBuffer):PromisetrustedAuthentication.AuthToken{constchallenge:Uint8ArrayInputRules.hex(challengeHex);if(!/^[1-9][0-9]*$/.test(authId)){thrownewError(valid enrolled authID required);}InputRules.required(text,confirmation,2048);if(image.byteLength0){thrownewError(TUI label image required);}constchecked:trustedAuthentication.TextCheckResultawaitthis.checkText(text);if(checked.result!0){thrownewError(TUI format rejected at checked.lastIndex);}returntrustedAuthentication.procContentAuthentication(challenge,BigInt(authId),{reqType:trustedAuthentication.AuthType.AUTH_TYPE_TUI_PIN,authContent:[text]},{title:图鉴测试确认,image:image});}}辅助校验与边界处理使用以下实现exportclassInputRules{staticrequired(value:string,name:string,max:number256):string{if(typeofvalue!string||value.trim().length0||value.lengthmax){thrownewError(name is missing or too long);}returnvalue.trim();}statichex(value:string):Uint8Array{if(!/^[0-9a-fA-F]{64}$/.test(value)){thrownewError(challenge must be 32 bytes of hex);}constbytes:Uint8ArraynewUint8Array(32);for(leti:number0;ibytes.length;i){bytes[i]parseInt(value.substring(i*2,i*22),16);}returnbytes;}}用排版失败和认证调用次数核对源码数字盾登记、HUKS 会话和合法 TUI 图片令牌用于后续 HUKS 操作的完整流程。检查层当前处理不能替代的结果编译API 26 工程进行类型检查与打包目标设备支持逻辑校验输入、状态或资源释放边界平台服务真实返回联调按上面的输入和条件逐步执行不能以按钮文案代替核心结果可信认证与 HUKS 会话的版本约束以 HarmonyOS 官方文档中心和当前 SDK 声明为准。排版不合格时不会进入认证可信文本排版检查失败认证接口不得继续执行通过断言认证调用次数可检查这一前置条件。合法挑战仍须来自实际 HUKS 会话。宿主测试直接载入 TrustedProbe仅以替身代替 trustedAuthenticationload 与 test 属于测试框架。test(trusted: rejected format never opens authentication,async(){letcalled0;constCload(services/TrustedProbe,{kit.DeviceSecurityKit:{trustedAuthentication:{checkConfirmUITextFormat:async()({result:1019100011,lastIndex:0}),procContentAuthentication:async()called,AuthType:{AUTH_TYPE_TUI_PIN:32}}}}).TrustedProbe;awaitassert.rejects(newC().confirm(ab.repeat(32),1,text,newArrayBuffer(8)),/format/);assert.equal(called,0);});操作或边界应检查的结果输入不满足前提不调用后续平台操作平台拒绝或抛错保留错误不生成成功状态再次进入或重试检查旧状态不会污染新任务