【HarmonyOS 7新能力|037】数字盾工程封装:把接入逻辑放进可维护的分层结构

【HarmonyOS 7新能力|037】数字盾工程封装:把接入逻辑放进可维护的分层结构

转账、授权、删除密钥或提交重要合同,都不能把安全寄托在一个普通"确认"按钮上。页面可能被覆盖,待签内容可能在展示后发生变化,重复请求也可能导致同一操作执行两次。数字盾类能力的工程目标,是把用户看到的内容、用户作出的输入、最终签名的上下文和服务端执行结果连接成一条可核验闭环。

说明:文中的 TrustedUiPortSecureSignPort 等为教学抽象,不代表 HarmonyOS SDK 的真实接口。可信环境、认证方式、密钥硬件、权限与支持设备以当前官方文档和目标 SDK 为准;任何单项能力都不能构成"绝对安全"承诺。

1. 先定义需要保护的确认语义

安全确认不是给任意字符串盖章。业务要先定义操作类型、主体、对象、金额或范围、有效期以及执行后的影响。只有这些字段稳定,用户看到的摘要和签名输入才能来自同一份数据。

ts 复制代码
export interface ProtectedOperation {
  operationId: string
  action: 'authorize' | 'transfer' | 'delete' | 'submit'
  subjectId: string
  target: string
  consequence: string
  expiresAt: number
  nonce: string
}

不要把页面文案直接作为签名载荷,也不要让页面自行选择要签哪些字段。领域模型是唯一事实来源,展示摘要与待签摘要都由同一个规范化器生成。

2. 四层结构隔离可信边界

业务页面负责发起意图和显示最终结果;安全编排层校验请求并驱动状态机;可信能力适配层封装可信 UI、输入和签名;审计与密钥边界保存最少的核验记录,密钥材料始终留在受保护能力内部。

ts 复制代码
export interface TrustedUiPort {
  confirm(model: TrustedConfirmModel): Promise<TrustedInputResult>
}

export interface SecureSignPort {
  sign(input: SignInput): Promise<SignResult>
}

页面无法直接取得私钥句柄或调用底层签名,适配器也不决定业务是否执行。边界清晰后,平台接口升级集中在适配层,风险策略集中在编排层。

3. 请求校验必须早于可信界面

可信界面只能保证其自身展示过程,不会替业务修复一份过期或字段缺失的请求。进入流程时先检查操作 ID、随机数、时间窗、动作白名单、目标格式以及当前会话是否有权发起。

ts 复制代码
export function validateOperation(op: ProtectedOperation, now: number): CheckResult {
  if (!op.operationId || !op.nonce) return fail('MISSING_IDENTITY')
  if (op.expiresAt <= now) return fail('OPERATION_EXPIRED')
  if (!allowedActions.has(op.action)) return fail('ACTION_NOT_ALLOWED')
  if (!isTargetValid(op.target)) return fail('INVALID_TARGET')
  return pass()
}

无效请求直接关闭,不进入认证与签名。这样既减少不必要的敏感交互,也避免攻击者利用可信流程试探系统状态。

4. 上下文摘要必须确定且可复现

同一业务对象在不同设备、语言或字段顺序下应得到相同摘要。使用明确字段顺序、字符编码、版本号和长度边界进行规范化,再由经过验证的密码学能力计算摘要。

ts 复制代码
export interface CanonicalEnvelope {
  schema: 'protected-operation/v1'
  operationId: string
  action: string
  subjectId: string
  target: string
  expiresAt: number
  nonce: string
}

function canonicalize(op: ProtectedOperation): string {
  return stableSerialize(toEnvelope(op))
}

不要依赖普通对象默认序列化顺序,也不要自创摘要算法。摘要版本随结构记录,服务端按相同规范重建并核验。

5. 可信界面展示真正被签的内容

可信界面应展示操作类型、关键对象、不可逆后果和请求来源,而不是笼统的"是否继续"。展示模型从规范化信封生成,禁止页面临时覆盖关键字段。

ts 复制代码
export interface TrustedConfirmModel {
  title: string
  primaryFacts: readonly { label: string; value: string }[]
  consequence: string
  digestPreview: string
  timeoutAt: number
}

摘要预览不是让用户人工校验哈希,而是让诊断和审计能确认展示与签名的绑定。普通说明文字可以本地化,关键事实必须保持语义一致。

6. 可信输入只表达明确同意

认证成功不等于用户同意。可信输入需要发生在用户已看到完整关键内容之后,并明确区分确认、取消、超时与认证失败。页面不能把取消自动转换成重试。

ts 复制代码
export type TrustedInputResult =
  | { status: 'confirmed'; proof: string; confirmedAt: number }
  | { status: 'cancelled' }
  | { status: 'timeout' }
  | { status: 'failed'; code: string }

快速连点应只产生一个有效结果。交互期间禁用普通页面的重复入口,流程结束后再恢复,避免并发创建多份待签请求。

7. 签名输入绑定操作与确认结果

签名输入至少包含规范化摘要、操作 ID、随机数、验证方、确认时间和有效期。可信输入返回的证明若平台支持,也应按官方方式绑定,而不是只签业务正文。

ts 复制代码
export interface SignInput {
  operationDigest: string
  operationId: string
  verifierId: string
  nonce: string
  confirmedAt: number
  expiresAt: number
}

私钥生成、选择、认证和签名由可信能力负责。应用不导出密钥,不把签名前明文或认证秘密写入日志与普通持久化。

8. 状态机保证流程只能向前

编排器使用 validatingpresentingconfirmingsigningverifyingcompletedcancelledfailed 状态。每个状态只接受允许的事件,完成态不能再次进入签名。

ts 复制代码
export type ShieldFlowState =
  | { kind: 'validating' }
  | { kind: 'confirming'; operationId: string }
  | { kind: 'signing'; digest: string }
  | { kind: 'completed'; receiptId: string }
  | { kind: 'cancelled' }
  | { kind: 'failed'; code: string; retryable: boolean }

页面旋转、进入后台或组件重建只重新订阅状态,不重新发起操作。涉及可信交互时的后台策略按官方能力与产品安全要求处理,不能猜测继续执行。

9. 服务端核验后才执行业务

客户端得到签名不代表操作已经完成。服务端必须重建规范化摘要,验证签名、密钥或证书状态、随机数、时间窗、主体权限和操作 ID 的未消费状态,全部通过后才在同一事务语义中执行业务并消费随机数。

ts 复制代码
export interface VerificationReceipt {
  operationId: string
  accepted: boolean
  reasonCode: string
  receiptId?: string
  verifiedAt: number
}

客户端只根据服务端回执展示成功。网络超时属于"结果未知",应凭 operationId 查询状态,不能直接再次提交。

10. 防重放与幂等是一套设计

随机数防止旧签名换场景复用,操作 ID 防止同一业务重复执行,短有效期缩小攻击窗口。服务端为操作建立 pending/consumed/expired/rejected 记录,并以原子方式完成核验与消费。

ts 复制代码
async function submitOnce(payload: SignedOperation): Promise<VerificationReceipt> {
  const known = await receiptRepository.find(payload.operationId)
  if (known?.terminal) return known.receipt
  return verifier.verifyAndConsume(payload)
}

重试必须携带相同操作 ID;创建新 ID 等价于新业务请求,需要重新展示和确认,不能静默替换。

11. 失败关闭与安全审计

取消、超时、界面失效、签名失败、上下文不一致或核验失败都应终止当前流程。允许重试时重新校验请求,必要时重新展示,不复用已过期确认。

ts 复制代码
export interface ShieldAuditRecord {
  operationId: string
  action: string
  state: string
  reasonCode: string
  digestVersion: string
  occurredAt: number
}

审计不保存私钥、认证数据、完整敏感正文或可重放载荷。记录用于定位流程在哪一层失败,而不是复制全部请求。用户主动取消应作为正常结果,不应标记为攻击。

12. 测试清单与总结

测试至少覆盖字段篡改、过期请求、重复随机数、重复操作 ID、可信界面取消、输入超时、签名失败、服务端拒绝、网络结果未知和回执查询。还要验证页面展示摘要与实际签名摘要一致,普通页面不能覆盖可信区域,日志中没有密钥与认证材料。

数字盾工程化的核心,是让"看见、同意、签名、执行"指向同一操作。用规范化信封固定语义,用可信界面和可信输入收集明确同意,用签名绑定上下文,用服务端核验和幂等消费完成闭环。任何一环失败就安全关闭,任何一次成功都有可验证回执,才是可维护的高风险操作保护方案。

相关推荐
m0_715674431 小时前
智能化+基于行标+场景化 政务数据库审计与风险监测全维度解决方案
网络·数据库·安全·网络安全·政务
ai安歌1 小时前
不调用外部 typst 命令:Draftmark 用 FRB 内嵌排版引擎的实现
harmonyos
山东科恩光电2 小时前
安全触边系统在工业自动化设备中的重要性及应用前景
安全
看浪的路人2 小时前
第8讲:运行时安全与沙箱隔离——Agent 能做什么,不能做什么
安全
威哥爱编程2 小时前
HarmonyOS 首开提速实战:首屏白屏的三种归因与对症方案
harmonyos·arkts
威哥爱编程2 小时前
HarmonyOS 折叠屏与鸿蒙电脑适配:布局一崩,八成是断点没定义
华为·harmonyos·arkts
威哥爱编程2 小时前
HarmonyOS 穿戴独立 UX 实战:三道坎、两个降级、一张自检清单
华为·harmonyos·arkts
贾伟康2 小时前
【HarmonyOS 7新能力|038】游戏快启工程封装:把接入逻辑放进可维护的分层结构
性能优化·harmonyos·arkts·游戏开发·软件架构
云杂项2 小时前
Safety at Scale: A Comprehensive Survey of Large Model and Agent Safety(LLMs章节)
人工智能·安全