【HarmonyOS 7新能力|011】分布式数字身份入门实战:从能力边界到最小可运行链路

【HarmonyOS 7新能力|011】分布式数字身份入门实战:从能力边界到最小可运行链路

数字身份验证常见的错误做法,是为了证明一个简单条件而复制整份身份资料。例如业务只需确认用户是否满足某项条件,却要求上传姓名、证件号码和完整出生日期。分布式数字身份的工程价值之一,是让凭证由持有者控制,并围绕一次明确请求生成最小必要证明。

本文以"验证方请求证明某项资格,持有方确认后提交最小披露"为场景,建立创建挑战、选择凭证、用户确认、生成披露、验证签名和消费结果的应用侧链路。文中的 ArkTS 类型与流程属于建议模型,不是华为官方 API,也不代表某个特定 DID 或密码协议;凭证格式、算法、开放范围和安全要求请以 HarmonyOS 7 / API 26 当前官方资料为准。本文未完成安全认证或攻击验证。

一、先区分三种角色与责任

签发方对凭证中的声明负责;持有方保存凭证并决定是否披露;验证方提出有用途边界的请求并验证证明。三者不能混成一个"登录服务",否则很难解释谁创建声明、谁授权披露、谁在什么范围内消费结果。

最小验收条件是:请求描述用途和必要声明;持有方能看懂并确认;证明绑定本次挑战与验证方;验证方检查签名、期限和会话;相同证明不能被再次使用;业务只获得完成动作所需结果。

角色边界还决定错误归属:签发信息有误由签发流程处理,用户拒绝披露不能记作验证失败,验证方自身挑战过期也不能要求持有方承担。把错误归到正确角色,才能设计合理重试与提示。

二、验证请求必须限定用途

请求不应只给出字段列表,还要说明验证目的、接收方、挑战值和有效期:

ts 复制代码
interface VerificationRequest {
  requestId: string
  verifierId: string
  purpose: string
  requiredClaims: string[]
  challenge: string
  expiresAt: number
}

type VerificationOutcome = 'verified' | 'rejected' | 'cancelled'

purpose 用于向用户解释,不应包含可执行指令。requiredClaims 必须来自业务白名单;挑战由验证会话生成,不能重复或长期固定。

三、凭证选择不等于自动披露

钱包或凭证层可以找出满足声明要求的候选,但最终披露内容仍需显式计算并交给用户确认:

ts 复制代码
interface CredentialSummary {
  credentialId: string
  issuerLabel: string
  claimNames: string[]
  expiresAt?: number
  revoked?: boolean
}

function supports(credential: CredentialSummary, claims: string[]): boolean {
  if (credential.revoked) return false
  return claims.every(name => credential.claimNames.includes(name))
}

摘要不包含原始敏感值。候选凭证有多个时,不应暗自选择权限最大的一个;优先选择披露更少且仍满足请求的凭证,必要时让用户决定。

四、声明最小化由请求交集决定

应用不得把凭证中所有字段都塞进证明。可以先计算请求声明与凭证声明的交集,并拒绝未知字段:

ts 复制代码
interface DisclosurePlan {
  requestId: string
  credentialId: string
  disclosedClaims: string[]
  omittedClaims: string[]
}

function planClaims(requested: string[], available: string[]): string[] {
  const allowed = new Set(available)
  return [...new Set(requested)].filter(name => allowed.has(name))
}

若业务只需要布尔结论,应优先披露"条件满足",而不是支撑结论的完整原始字段。具体是否支持这种证明及其密码学实现,必须由官方能力和所采用标准确认。

五、完整链路必须绑定一次挑战

验证方先创建带期限的随机挑战;持有方选择可用凭证并展示披露计划;用户确认后生成最小证明;验证方检查签名、挑战、接收方、用途和期限;成功结果只能在本次请求范围内消费一次。

挑战过期、声明缺失或会话不匹配都应拒绝并重新发起,不能沿用旧证明补字段。一次证明只服务一次明确请求,是防重放和防用途扩张的基础。

六、用户确认页面不能模糊处理

确认页至少应展示验证方、用途、将披露的声明和可取消入口。不要只显示"是否授权",也不要把必要声明和可选声明混在一起。用户取消后,生成任务和临时披露计划必须失效。

确认页展示的是语义摘要,不直接渲染未经处理的验证方自由文本。长文本要截断并提供详情入口,深浅色、字体放大和读屏状态下仍需可理解。

如果披露计划在确认期间发生变化,例如凭证过期或请求被更新,旧确认立即作废并重新展示。不能把用户对旧字段集合的同意延伸到新增声明。

七、证明对象需要明确上下文

下面只描述应用侧封装,不定义真实密码字段:

ts 复制代码
interface PresentationEnvelope {
  presentationId: string
  requestId: string
  verifierId: string
  challenge: string
  purpose: string
  disclosedClaims: Record<string, string | boolean>
  createdAt: number
  expiresAt: number
  proof: string
}

proof 必须由官方或经过审查的可信能力生成,不能自行拼接哈希冒充签名。应用层只传递不透明证明,并保证上下文字段与用户确认内容一致。

八、验证顺序要先上下文后业务

验证方收到证明后,先检查请求是否存在、是否过期、是否已消费,再检查接收方、挑战和用途是否一致,之后才调用可信签名验证,最后检查必要声明。

ts 复制代码
function matchesRequest(
  envelope: PresentationEnvelope,
  request: VerificationRequest,
  now: number
): boolean {
  return envelope.requestId === request.requestId &&
    envelope.verifierId === request.verifierId &&
    envelope.challenge === request.challenge &&
    envelope.purpose === request.purpose &&
    now <= request.expiresAt && now <= envelope.expiresAt
}

上下文不匹配时立即停止,不把失败证明送入业务逻辑。签名有效也不代表用途、期限和声明范围必然正确。

九、防重放需要原子消费

只在内存里先查询"未使用",再异步标记"已使用",会产生并发窗口。验证成功与消费标记应形成单一原子结果:

ts 复制代码
interface ConsumptionRecord {
  presentationId: string
  requestId: string
  consumedAt: number
}

interface ConsumeResult {
  accepted: boolean
  reason?: 'replayed' | 'expired' | 'invalid' | 'missing_request'
}

同一证明并发到达时只能有一个请求成功。记录保留周期应按安全与隐私要求设计,只保存防重放需要的最小标识和时间,不保存整份披露内容。

十、四层架构隔离密钥与页面

交互层负责验证请求、披露确认和结果反馈;会话层负责挑战管理、用途绑定与防重放;凭证层选择凭证、最小化声明并请求证明;可信适配层封装密钥、签名验证和安全存储能力。

页面不能读取私钥或原始密钥句柄,验证业务也不应自行实现密码算法。各层通过窄接口传递请求和最小证明,错误只返回稳定原因码。

十一、生命周期与数据清理同样重要

页面退出、用户取消、挑战过期或应用切换账号时,应销毁披露计划和临时证明,停止相关异步任务。迟到结果必须携带会话修订号,不能重新唤醒已经结束的确认页。

日志不得写入完整凭证、披露值、证明正文、私钥材料或稳定身份标识。确需审计时,只记录请求类别、结果原因、策略版本和去标识时间,并明确保存期限与访问边界。

清理验证不只检查页面变量,还要确认挑战计时器、凭证订阅和待完成回调已解除。恢复页面时重新查询请求状态,绝不能凭本地缓存再次提交旧证明。

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

测试至少覆盖无匹配凭证、多个候选、声明缺失、用户取消、挑战过期、验证方不匹配、用途变化、签名失败、证明过期、并发重放、消费记录失败和页面恢复。每项都断言披露字段、最终结果、消费次数和临时数据清理。

集成验证还应覆盖凭证撤销或状态变化、设备迁移、深浅色、长文案与无障碍。密码算法、安全存储和跨设备行为必须使用官方能力与真实环境验证;本文未执行这些测试,不提供认证结论。

落地前确认官方开放范围;角色责任明确;请求包含用途、接收方、挑战和期限;披露字段是最小交集;用户看到完整摘要;证明绑定请求上下文;验证顺序正确;消费原子且防重放;密钥不进入页面;取消和过期统一清理。

分布式数字身份的核心不是把传统证件搬到设备里,而是让每次验证只披露必要内容,并且只对一个明确会话有效。先把请求、凭证、证明和消费边界建模清楚,再接入 HarmonyOS 7 的实际可信能力,才能真正减少身份数据暴露。

参考资料:

相关推荐
颜颜yan_2 小时前
Geany 鸿蒙 PC 适配全记录:以 Qt 重建轻量 IDE,打通编辑、项目检索与命令执行
ide·qt·harmonyos
●VON2 小时前
Flutter 鸿蒙插件适配实战:用 app_version_details 1.0.3 读取版本号与包名
flutter·华为·harmonyos
承渊政道2 小时前
PR-Agent鸿蒙PC适配全记录:从Python服务端代理到ArkTS原生评审客户端
python·华为·代理模式·agent·harmonyos·pc端
网络豆3 小时前
Apache Hive 鸿蒙 PC 适配全记录:以 Qt 客户端打通 HiveQL、监控与元数据访问
hive·apache·harmonyos
网络豆3 小时前
Apache HBase 鸿蒙 PC 适配全记录:用 Qt 原生客户端打通 REST 管理与数据读写
apache·hbase·harmonyos
hacker7074 小时前
bolt.diy 鸿蒙 PC 适配全记录:让 AI 全栈开发工作台在 HarmonyOS PC 上真正跑起来
人工智能·华为·harmonyos
●VON5 小时前
Flutter 鸿蒙插件适配实战:用 locale_plus 2.0.0 读取语言、地区与格式偏好
flutter·华为·harmonyos·鸿蒙
贾伟康14 小时前
【HarmonyOS 7新能力|008】互动卡片入门实战:从能力边界到最小可运行链路
harmonyos·arkts·arkui·harmonyos 7·互动卡片
●VON14 小时前
Flutter 鸿蒙插件适配实战:用 clipboard_watcher 0.3.0 监听剪贴板变化
flutter·华为·harmonyos