【HarmonyOS 7新能力|012】数字盾入门实战:从能力边界到最小可运行链路

【HarmonyOS 7新能力|012】数字盾入门实战:从能力边界到最小可运行链路

敏感操作的风险不只来自签名算法,还来自用户看到的内容、实际签名的内容和最终执行的内容不一致。如果普通页面显示"确认修改",后台却在确认后改变关键字段,那么签名本身再可靠,也无法证明用户同意了最终动作。

本文以"用户确认一项敏感设置变更"为最小场景,建立创建请求、固化摘要、展示可信界面、接收明确确认、生成绑定签名和验证执行的应用侧链路。文中的 ArkTS 类型、摘要结构和签名信封只是建议模型,不是华为官方 API;可信界面、可信输入、密钥能力和设备范围请以 HarmonyOS 7 / API 26 当前官方资料为准。本文不声称达到特定密码学或安全认证等级。

一、可信链路要保护三个一致性

第一是"所见即所签":可信界面展示的操作摘要与进入签名的摘要相同。第二是"所签即所验":验证方按相同规范重新计算摘要。第三是"所验即所执行":业务执行严格使用已经验证的不可变请求,而不是重新读取可能变化的页面草稿。

最小验收条件包括:敏感字段白名单固定;请求有唯一编号和期限;摘要规范确定;用户在可信区域明确确认;签名绑定请求、摘要和会话;相同结果不能重放;异常、取消和超时均不执行业务动作。

二、先建立不可变操作请求

业务页面提交的是结构化请求,而不是待拼接的说明文本:

ts 复制代码
type ProtectedAction = 'change_setting' | 'approve_export'

interface ProtectedRequest {
  requestId: string
  sessionId: string
  action: ProtectedAction
  targetId: string
  parameters: Record<string, string | boolean>
  createdAt: number
  expiresAt: number
  schemaVersion: string
}

parameters 必须由每种动作自己的白名单校验,不能接受任意嵌套对象。请求创建后冻结,页面修改输入时应生成新请求,而不是覆盖旧对象。

三、摘要规范必须跨端确定

对象键顺序、空值、数字格式和字符编码若不统一,同一业务内容会产生不同字节。先规范化,再调用可信能力计算摘要:

ts 复制代码
interface CanonicalRequest {
  action: ProtectedAction
  targetId: string
  parameters: Array<{ key: string; value: string }>
  schemaVersion: string
}

function canonicalize(request: ProtectedRequest): CanonicalRequest {
  const parameters = Object.keys(request.parameters).sort().map(key => ({
    key,
    value: String(request.parameters[key])
  }))
  return { action: request.action, targetId: request.targetId,
    parameters, schemaVersion: request.schemaVersion }
}

示例只说明确定性结构,不定义真实序列化或哈希算法。算法、编码和版本迁移必须使用官方或项目安全规范。

四、展示模型与签名模型共同派生

可信界面显示的标题、目标与关键参数,应和签名输入从同一不可变请求派生,避免两套映射规则漂移:

ts 复制代码
interface ConfirmationView {
  title: string
  targetLabel: string
  details: Array<{ label: string; value: string }>
  requestIdSuffix: string
}

interface PreparedOperation {
  request: ProtectedRequest
  canonical: CanonicalRequest
  view: ConfirmationView
  digest: string
}

页面不能传入自定义标题掩盖真实动作。敏感字段应使用明确名称与完整值或安全摘要,不能用模糊文案诱导确认。

五、完整链路在确认前固化内容

应用创建请求并完成白名单校验,然后固化规范数据与摘要;可信界面展示由同一请求生成的内容;用户在可信输入路径中明确确认;可信能力生成绑定签名;业务侧重新验证上下文后才执行。

摘要变化、会话过期或用户取消都进入拒绝并清理。确认页面一旦显示,任何关键字段变化都必须终止旧会话并重新展示,不能沿用之前的同意。

六、确认不是普通按钮回调

可信确认要区分展示完成、用户明确输入和签名完成三个状态。页面可用内部状态机描述编排,但不能假装普通点击等同平台可信输入:

ts 复制代码
type ShieldPhase = 'preparing' | 'presenting' | 'awaiting_input' |
  'signing' | 'verifying' | 'completed' | 'cancelled' | 'failed'

interface ShieldSession {
  sessionId: string
  requestId: string
  phase: ShieldPhase
  revision: number
  digest?: string
}

function canSign(session: ShieldSession): boolean {
  return session.phase === 'awaiting_input' && session.digest !== undefined
}

平台可信输入的真实条件必须按官方文档实现,应用状态机只负责阻止非法顺序和旧回调覆盖。

七、签名信封绑定完整上下文

签名不能只覆盖业务参数,还要绑定请求、会话、版本、摘要与期限:

ts 复制代码
interface SignatureEnvelope {
  requestId: string
  sessionId: string
  schemaVersion: string
  digest: string
  issuedAt: number
  expiresAt: number
  nonce: string
  signature: string
}

signature 是可信能力返回的不透明结果,应用不得自行实现私钥运算或记录密钥材料。nonce 必须满足真实安全规范,不能用时间戳或递增数字冒充随机挑战。

八、验证顺序先上下文后签名

先确认请求存在且未消费,再检查会话、版本、期限、随机挑战和摘要是否匹配,最后调用可信验证能力:

ts 复制代码
function contextMatches(
  envelope: SignatureEnvelope,
  request: ProtectedRequest,
  expectedDigest: string,
  now: number
): boolean {
  return envelope.requestId === request.requestId &&
    envelope.sessionId === request.sessionId &&
    envelope.schemaVersion === request.schemaVersion &&
    envelope.digest === expectedDigest && now <= envelope.expiresAt &&
    now <= request.expiresAt
}

签名有效不代表请求一定可执行;上下文错配、权限变化或业务对象失效时仍要拒绝。

九、执行必须使用已验证快照

验证通过后,将已验证请求与消费标记放进同一受控事务。不要回到页面重新读取参数:

ts 复制代码
interface ExecutionResult {
  requestId: string
  accepted: boolean
  reason?: 'expired' | 'replayed' | 'invalid_signature' |
    'context_changed' | 'cancelled'
}

interface ConsumptionRecord {
  requestId: string
  nonce: string
  consumedAt: number
}

相同请求或随机挑战并发到达时,只能有一次执行成功。记录只保留防重放必需信息,不保存完整签名内容和敏感参数。

十、四层架构隔离密钥与 UI

交互层负责操作摘要、可信确认和结果反馈;会话层管理请求绑定、版本校验、超时取消;签名层负责摘要、签名请求与验证结果;可信适配层封装可信界面、可信输入和密钥能力。

页面不能接触密钥句柄,签名层不能决定业务文案,可信适配层也不能直接执行设置变更。窄接口和单向依赖让每个边界可以单独审计与模拟测试。

十一、取消、超时与清理失败关闭

用户取消、页面销毁、应用切后台或会话超时后,状态立即进入终态,未开始的签名停止,迟到结果只清理不执行。是否允许后台继续必须严格服从官方能力和产品规则,不能以隐藏方式绕过系统限制。

清理包括可信界面、输入监听、计时器、临时规范数据、摘要和签名结果。日志不得写入私钥、完整签名、用户输入、完整敏感参数或稳定设备标识。

同一会话的完成、取消和超时可能并发到达,应采用"首次合法终态生效"的规则。后续事件只能进入审计与幂等清理,不能再次打开确认界面、生成新签名或触发业务动作。

十二、测试矩阵与落地清单

测试至少覆盖非法参数、字段顺序变化、摘要版本不一致、展示后参数变化、普通点击冒充确认、用户取消、签名失败、会话过期、摘要错配、并发重放、业务对象失效和清理失败。每项断言业务副作用次数、最终状态和临时数据数量。

真机集成还应覆盖深浅色、长文本、字体放大、无障碍、前后台切换和多窗口。密码学正确性、可信界面边界和设备支持必须用官方能力与真实环境验证;本文未执行这些验证,不提供安全认证结论。

落地前确认官方开放条件;请求字段白名单固定;规范化规则有版本;展示与签名来自同一请求;用户明确确认;签名绑定完整上下文;验证后使用不可变快照执行;消费原子防重放;异常失败关闭;临时数据统一清理。

数字盾链路的核心不是"加一次签名",而是让用户所见、所签、所验和所执行保持一致。先把内容绑定、会话状态和防重放设计清楚,再接入 HarmonyOS 7 的实际可信能力,才能让敏感操作真正可验证。

参考资料:

相关推荐
万物智能信息科技1 小时前
板载按键key的ADC转换和信号控制—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
嵌入式硬件·华为·开源·harmonyos·鸿蒙
威哥爱编程2 小时前
HarmonyOS 6.1 端侧 3DGS 重建实战:重建在 C 层,ArkTS 只管"看"和"改"
华为·harmonyos·arkts
威哥爱编程3 小时前
HarmonyOS 6.1 沉浸光感实战:接口路径选错,代码不报错、页面没效果
harmonyos
贾伟康3 小时前
【HarmonyOS 7新能力|014】冷启网络预建链入门实战:从能力边界到最小可运行链路
harmonyos·arkts·启动优化·网络优化·harmonyos 7
Sunny_G3 小时前
CodeMirror 6 代码块渲染踩坑:一个空行毒死全文档(鸿蒙编辑器卡片化/折叠/点击进源码)
ai编程·harmonyos
不羁的木木3 小时前
给鸿蒙 App 增加广播收发能力 —— flutter_broadcasts 的鸿蒙使用指南
flutter·harmonyos
不羁的木木4 小时前
给鸿蒙 App 增加打开外部网页能力 —— flutter_web_browser 的鸿蒙使用指南
前端·flutter·harmonyos
安好说AI5 小时前
Flutter 三方库 sound_mode 的鸿蒙化适配指南:免权限读取与受限写入的契约对齐
flutter·harmonyos·鸿蒙
●VON5 小时前
Flutter 鸿蒙 disk_space_2 1.0.13 使用实战:下载前检查磁盘空间
flutter·华为·harmonyos·鸿蒙
IT从业者张某某13 小时前
【鸿蒙PC命令行适配】GitUI 移植的工程实践:双 Git 引擎(libgit2/gitoxide)的鸿蒙适配之路
git·华为·harmonyos