国密UKey与FIDO2/WebAuthn协同演进:安当UKey作为无密码国密认证器的工程实践
发布时间:2026/10/14 3:29:57 锦皓数字建站

1. 引言软件令牌为什么挡不住钓鱼过去十年双因素认证的标配是密码 软件令牌TOTP。这套组合在企业内网和 SaaS 登录里跑了很久但它在攻击面上有三个结构性弱点第一共享密钥模型。TOTP 的密钥同时存在于认证服务器和用户的手机 App 中。一旦手机被植入恶意软件或者用户被诱骗截图给攻击者这个因子就失去了持有语义。第二可被中转的会话。软件令牌只解决了你是谁没有解决你正在登录的是不是真的那个站点。攻击者搭建一个中间人代理把用户的登录请求原样转发给真正的服务器软件令牌照样通过校验因为服务器看到的是一次合法的时间窗签名。第三无密码诉求与国密合规的错位。FIDO2/WebAuthn 已经把无密码 抗钓鱼写进了标准但它的默认算法是 ECDSA(P-256) / Ed25519 和 SHA-256与国内等保、密评要求的 SM2/SM3/SM4 体系并不天然兼容。政务、能源、轨交、制造这些强监管行业既想要 WebAuthn 的用户体验又必须满足国密算法合规。把硬件Key当作认证器而不是存储令牌是弥合这条裂缝的关键。硬件Key的私钥在芯片内生成、在芯片内参与运算、永远不离开安全边界天然契合 WebAuthn 的设备绑定 持有因子 用户验证三要素。问题留给工程侧怎样让一颗国密芯片对浏览器和 IdP 表现出一个标准 WebAuthn authenticator 的行为2. 原理WebAuthn 的信任链与国密适配层2.1 挑战-响应为什么抗钓鱼WebAuthn 的核心是一个非对称密码学挑战-响应协议。理解它只需要抓住四个角色角色职责关键产物Relying Party (RP)业务系统 / 身份提供方challenge一次性随机数、credentialIdWebAuthn Client浏览器中的凭据接口navigator.credentials调用Authenticator硬件Key签名、非导出私钥User持Key的人持有因子 验证因子注册和登录两条主流程# 注册流程简化序列 RP ──生成 challenge── Browser ──publicKeyCredentialCreationOptions── Authenticator Authenticator ──在芯片内生成密钥对── 私钥留存 / 公钥回传 Authenticator ──对 (challenge rpId 用户句柄) 签名── AttestationObject Browser ──credential(rawId response)── RP RP ──验签 存公钥 绑 credentialId── 完成注册 # 断言登录流程 RP ──生成 challenge 允许Credentials── Browser Browser ──publicKeyCredentialRequestOptions── Authenticator Authenticator ──读取私钥── 对 (challenge rpIdHash 当前计数) 签名 Browser ──assertion(authenticatorData signature)── RP RP ──验签 校验 rpIdHash 校验 signCount 单调── 放行抗钓鱼的根源在rpIdHash和clientDataHash签名覆盖的是RP 的域名哈希 浏览器提交的 clientData中间人即使把 challenge 转发出去也无法篡改rpIdHash因为 authenticator 在签名前会重新计算它看到的 RP 标识。签名结果对是哪个站点发起的强绑定攻击者拿到的断言无法重放到另一个域名。2.2 国密芯片如何充当 WebAuthn authenticator标准 WebAuthn authenticator 抽象出两个能力密钥生成和受限签名。国密硬件Key需要做一层适配层把国密算法桥接到这个抽象上/* 适配层伪代码把 WebAuthn makeCredential 映射到国密 Key */intukey_make_credential(constuint8_t*challenge,constuint8_t*rp_id_hash,uint8_t*credential_id,/* 输出Key 句柄 */uint8_t*pub_sm2_x,/* 输出SM2 公钥 X */uint8_t*pub_sm2_y)/* 输出SM2 公钥 Y */{/* 1. 在芯片内生成 SM2 密钥对私钥不离开安全区 */ukey_gen_sm2_inside_secure_zone();/* 2. 把 rpIdHash challenge 作为待签原文的一部分 */uint8_tto_sign[64];memcpy(to_sign,rp_id_hash,32);memcpy(to_sign32,challenge,32);/* 3. 调用芯片内部签名指令SM2 签名 */returnukey_sm2_sign_inside(to_sign,64,sig_out);}适配层要做三件关键的事算法协商在attestationObject的alg字段声明国密算法标识如-50对应 SM2并把aaguid指向国密Key的型号。私钥不可导出所有 SM2 签名都在芯片内完成适配层只回传签名值和公钥从接口层面杜绝私钥落盘。计数器防克隆authenticatorData里的signCount必须在芯片内单调递增并持久化用于在 RP 侧检测 Key 被克隆后的重放。2.3 为什么私钥不出硬件是底线WebAuthn 的威胁模型假设 authenticator 可能被物理拿走但只要私钥无法读出攻击者拿到的只是一块需要原厂才能用的石头。国密硬件Key的 SM2 私钥在 32 位 RISC 安全芯片内生成支持 SM1/SM2/SM3/SM4 以及 RSA/AES/ECC/SHA 算法族其安全边界由芯片的硬件熔丝和访问权限控制保证。任何上层应用只能通过C动态库或 RESTful 接口发起签名指令永远拿不到私钥明文——这是它区别于软件令牌的本质。2.4 CTAP 协议栈与国密Key的指令映射WebAuthn 只是用户侧接口真正跑在浏览器与硬件之间的协议叫 CTAPClient to Authenticator Protocol。理解它才能把国密Key正确接进链路。CTAP 分两层协议层适用设备能力范围与本方案的关联CTAP1 / U2F旧版单因子 Key仅注册/认证断言兼容存量设备CTAP2现代 authenticatormakeCredential / getAssertion / clientPin / 凭据管理无密码主通道对国密Key来说真正要实现的只有两个核心命令authenticatorMakeCredential和authenticatorGetAssertion。这两个命令在适配层被翻译成对芯片的C库调用。注意 CTAP2 还要求支持getInfo来声明本设备支持的算法列表这里必须把 SM2 加进去否则浏览器在能力协商阶段就会把 Key 过滤掉/* getInfo 返回的能力描述节选 */staticconstint32_talg_list[]{-50,/* SM2 */-7,/* ECDSA(P-256)兼容国际站点 */-8,/* EdDSA可选 */};staticconstuint8_taaguid[16]{/* 国密Key 型号标识 */};/* 在 webauthn 能力声明里同时暴露 SM2 与 ECDSA 让 RP 按自身合规要求选择 alg互不干扰 */多算法并存的好处是同一个 Key对接国内政务 SSO 时走 SM2对接支持 FIDO 的国际 SaaS 时走 ECDSA硬件不变、策略可变。2.5 凭据存储credentialId 与芯片内密钥的映射WebAuthn 注册后会回传一个credentialIdRP 侧只存它和公钥。真正的私钥保存在哪里在国密Key里credentialId本质上是一个指向芯片内密钥槽的句柄。一个 128 KB 的芯片通常能容纳数十到上百把密钥靠credentialId索引credentialId ──(适配层解析)── 芯片内 Slot 编号 ── SM2 私钥 │ │ │ └─ 签名运算全部在此完成 └─ RP 侧仅作索引无密钥材料这意味着即便 RP 数据库被拖库攻击者拿到的也只是credentialId和公钥无法反推出任何私钥——这是公钥基础设施 硬件隔离组合提供的天然抗拖库属性。2.6 证明语句Attestation的国密表达标准 WebAuthn 的证明语句有packed、tpm、android-key等格式它们各自描述这把公钥是由哪种安全硬件背书的。对国密Key最贴合的是packed格式的一个国密变体用 SM2 证书链替代原有的 X.509 ECDSA 证书把attStmt写成{ alg: -50, sig: SM2签名, x5c: SM2证书链 }。RP 在注册时用内置的根 CA 验证这条链就能确认这把 SM2 公钥确实出自合规国密芯片而不仅仅是任意一个能算 SM2 的软件。这一步对密评尤其重要它把算法的国密化进一步升级为根信任的国密化。attStmt (国密 packed 变体) ├─ alg : -50 # SM2 ├─ sig : SM2( authData || clientDataHash ) └─ x5c : [ 设备证书(SM2), 中间CA(SM2), 根CA(SM2) ] RP 校验用根CA 逐级验证书 - 用设备证书验 sig - 确认 authData 可信3. 架构从浏览器到国密Key的链路典型的部署形态是在 WebAuthn Client 与物理 Key 之间插入一个本地代理 浏览器扩展的桥接组件。浏览器不能直接碰 USB HID所以需要一个本地常驻进程把CTAP风格的指令翻译成对国密Key的C库调用。层级组件输入输出算法L1 浏览器WebAuthn APIcreate()/get()标准断言对象-L2 本地代理CTAP 桥接authenticatorMakeCredentialC库调用-L3 适配层国密适配器challenge rpIdHashSM2 签名值SM2/SM3L4 硬件Key安全芯片签名指令签名 计数SM1/SM2/SM3/SM4# 一次登录在链路上的数据走向 Browser.get() └─ NativeBridge (localhost socket) └─ ukey_adapter.c:assertion_prepare(challenge, rp_id) └─ ukey_sm2_sign_inside( hash(SM3, rp_id_hash||challenge||counter) ) └─ 返回 (authenticatorData, signature) └─ 组装 WebAuthn assertion 回传 Browser Browser ──POST /verifyAssertion── RP 验签这个架构的好处是RP 和浏览器完全不需要改动——它们看见的仍然是一个标准 WebAuthn authenticator。所有国密逻辑被封装在 L2/L3/L4对上层透明。4. 落地实践4.1 Key 注册为 WebAuthn authenticator注册阶段要把国密Key的 SM2 公钥登记到 RP 的凭据库并把credentialId与用户账户绑定。下面是一段 RP 侧基于 Node 生态的fido2风格库的处理骨架// RP 侧接收国密Key的注册响应app.post(/webauthn/register,async(req,res){const{rawId,response}req.body;constexpectedChallengereq.session.challenge;// 1. 解析 attestationObject确认 alg -50 (SM2)constattparseAttestation(response.attestationObject);if(att.alg!-50)returnres.status(400).send(unsupported alg);// 2. rpIdHash 必须匹配本域constrpHashsm3(Buffer.from(req.hostname));if(!timingSafeEqual(att.rpIdHash,rpHash))returnres.status(400).send(rpId mismatch);// 3. 验签SM2 验签用公钥constoksm2Verify(att.pubKey,att.signedData,att.signature);if(!ok)returnres.status(400).send(bad attestation);// 4. 落库credentialId - userIdawaitCredential.put(rawId,{userId:req.session.uid,publicKey:att.pubKey,alg:-50,signCount:att.signCount,aaguid:att.aaguid,// 指向国密Key型号});res.json({registered:true});});注意第 2 步的rpIdHash校验这是由SM3(域名)得到的 32 字节哈希确保 Key 是在这个站点下注册的杜绝跨站重放。4.2 以安当UKey为例把国密Key接入现有 IdP以安当UKey为例其对外暴露的接入面包含两类一是面向快速集成的RESTful接口约 2300 个端点覆盖初始化、密钥管理、签名、会话加密等二是面向高性能场景的C动态库可直接在业务进程内调用省去一次网络往返。在把它登记为 WebAuthn authenticator 时适配层通常走C库路径/* 登录断言安当UKey 适配示例 */intukey_webauthn_assert(constchar*credential_id,constuint8_t*challenge,constuint8_t*rp_id_hash,uint32_tstored_sign_count,uint8_t*out_auth_data,uint8_t*out_signature){uint32_tcur_count;ukey_read_sign_count(credential_id,cur_count);if(cur_countstored_sign_count)/* 计数器不增 疑似克隆 */return-1;uint8_tcdh[32];sm3_ctx_tc;sm3_init(c);sm3_update(c,rp_id_hash,32);sm3_update(c,challenge,32);sm3_final(c,cdh);/* 硬件内 SM2 签名私钥不可导出 */if(ukey_sm2_sign_inside(credential_id,cdh,32,out_signature)!0)return-2;build_authenticator_data(out_auth_data,rp_id_hash,cur_count);return0;}这段代码里有两个工程细节值得强调其一是signCount的单调递增校验它在 RP 侧同样要再校验一遍形成双重防御其二是rp_id_hash在签名原文里参与哈希这是抗钓鱼的锚点。4.3 以安当UKey为例与现有 IdP 的协同与回退在政务 SSO、电网调度这类既有身份体系里很难一步把密码登录全部下线。以安当UKey为例常见的渐进式策略是WebAuthn 为主、密码 OTP 为辅的双通道认证方式触发条件信任等级备注国密Key PIN正常办公、内网终端高持有知识因子主通道国密Key 签名验签调度指令、审批动作高操作级不可否认关键操作强制密码 动态口令Key 遗失 / 芯片损坏中回退通道需二次复核远程接入 Key外场、轨交、指挥车高远程访问场景同样走硬件签名回退不是简单的降级而是要在审计日志里标记该次会话的信任等级并对回退通道附加限制例如回退会话只允许只读、关键写操作仍要求 Key 在线。这种策略分級比全有或全无更容易在强监管行业落地。4.4 关键操作强制签名验签对于电网调度指令签名、军用指挥车的指令下发这类一旦伪造后果严重的操作应当把 WebAuthn 断言之外的业务级签名再做一次。此时国密Key不只是登录凭据更是操作不可否认的印章操作员发起断开 220kV 甲线指令 └─ 终端组装指令明文 M └─ 安当UKey 对 SM3(M) 做 SM2 签名 Sig └─ 报文 M || Sig || certId 上送调度中心 调度中心 ──用 Key 预置证书验签── 验过则执行并留痕这里用到了 Key 的CA 证书能力第四种认证方案KeyID → CA证书允许把芯片内的 SM2 密钥对与一个由内部 CA 签发的证书绑定使签名结果可被独立的证书链验证满足密评里对身份真实性 数据完整性 不可否认性的三项要求。4.5 会话加密用 SM4 把断言之外的通道也锁住无密码登录解决的是身份鉴别但登录之后的业务报文仍处于明文风险中。国密Key的会话加密方向正好补上这一环登录成功后用芯片内的 SM2 做一次密钥协商派生出 SM4 会话密钥后续报文用 SM4 对称加密传输兼顾安全与性能。/* 会话密钥协商ECDH 风格但用 SM2 曲线 */intukey_session_key(uint8_t*peer_pub_x,uint8_t*peer_pub_y,uint8_t*out_sm4_key/* 32字节 SM4 密钥 */){/* 1. 芯片内取本端 SM2 私钥不可导出 *//* 2. 与对端公钥做 SM2 密钥协商 共享秘密 Z */uint8_tZ[32];ukey_sm2_derive_inside(peer_pub_x,peer_pub_y,Z);/* 3. SM3(Z) 作为 SM4 密钥或直接用 Z 做密钥包装 */sm3(Z,32,out_sm4_key);return0;}这种认证用非对称、传输用对称的分层在电网调度、SCADA、轨交外场这类既有实时性要求又有保密性要求的场合尤其合适握手阶段一次 SM2之后海量遥测报文全走 SM4延迟可控。4.6 软件授权保护把 Key 当成许可锁除了人登录国密Key还能给软件本身上锁。制造车间的 CAD 授权、ERP 防盗版就是典型场景软件启动时向 Key 发起一次KeyID → 签名验签只有持有合法 Key 的终端才能进入主功能Key 遗失则授权随硬件一起收回比序列号 在线激活更难被批量破解。实现上同样依赖私钥不出硬件破解者即便反编译了软件也拿不到可伪造的签名密钥。CAD 软件启动 └─ 读取 Key 的 KeyID构造随机 challenge └─ 安当UKey 对 challenge 做 SM2 签名 └─ 软件用 Key 预置公钥验签 ├─ 通过 进入完整功能 └─ 失败 仅试用模式 / 拒绝启动5. 关键参数、性能与合规5.1 硬件与算法参数参数规格说明主控32 位 RISC 安全芯片专用安全核非通用 MCU片上存储128 KB存放密钥、证书、计数、固件国密算法SM1 / SM2 / SM3 / SM4对称/非对称/杂凑/分组国际算法RSA / AES / ECC / SHA兼容存量系统私钥保护不可导出签名只在芯片内接口RESTful(~2300) C 动态库灵活与高性能两条路径适配信创环境国产 OS / 数据库 / 中间件5.2 性能关注点无密码认证的体验瓶颈通常在用户插Key到断言返回的时延。几个可优化点优先走 C 动态库而非 RESTful。本地进程内调用省去一次 HTTP 往返断言时延通常从十几毫秒降到个位数毫秒。会话加密复用。登录完成后可用 Key 协商的会话密钥SM4保护后续通道避免每次操作都做完整 WebAuthn 断言。计数器读取走缓存。signCount的写入必须落芯片但读取可缓存到本地代理减少不必要的芯片交互。5.3 合规映射合规诉求国密Key 提供的对应能力等保 / 密评 身份鉴别硬件持有因子 PIN 用户验证传输加密SM4 会话加密、SM2 密钥协商数据完整性SM3 摘要 SM2 签名不可否认CA 证书绑定的 SM2 签名信创适配国产生态下的驱动与库支持固件来源可信固件签名校验防篡改刷写6. 常见坑与排查坑 1rpId 与域名不一致导致验签失败。WebAuthn 的rpId默认取当前域名rpIdHash是SM3(域名)。如果 RP 入口经过反向代理对外域名和内网host不同注册和断言就会对不上。排查时打印两端的rpIdHash十六进制比对即可。坑 2signCount 不涨被误判为克隆。部分芯片在多应用共享时计数回写有竞态。现象是第二次登录就被 RP 拒绝。排查方法在适配层打印每次断言前后的cur_count确认差值并确认写回路径有原子性保护。坑 3浏览器拿不到 authenticator。浏览器通过 USB HID / 蓝牙与 Key 通信本地代理没起来或权限不足时navigator.credentials.get()直接 reject。先用系统工具确认 Key 已被识别、对应设备节点存在再检查本地代理是否在监听。坑 4混合算法验签失败。RP 用 ECDSA(P-256) 的验签函数去验国密Key的 SM2 签名必然失败。务必在attestationObject.alg上做分支-50走 SM2 验签-7走 ECDSA 验签不要假设算法。坑 5回退通道被长期占用。回退密码OTP本应是临时通道但若不做策略限制会被常态化使用等于架空硬件Key。建议在策略里给回退会话打标并限制其写权限与有效期定期审计回退次数异常。坑 6固件被非法刷写。如果芯片未启用固件签名校验攻击者可刷入恶意固件读取密钥。必须开启固件签名校验只允许由持有合法签名密钥的镜像写入从硬件启动链上堵住这条路。坑 7多 RP 共用一把 Key 时的凭据混淆。一把国密Key可能被同时登记给政务 SSO 和内部 ERP。如果适配层在makeCredential时没有把rpIdHash作为密钥槽命名空间的一部分就会出现 A 站点的断言被 B 站点接受。正确做法是把Slot HASH(rpId) || KeyID让每把 Key 在每个 RP 下拥有独立密钥槽互不串台。坑 8PIN 验证与用户 Presence 的语义不清。WebAuthn 区分userPresent按了一下 Key和userVerified通过了 PIN/生物。无密码主通道应当要求userVerifiedtrue否则只证明了有人碰了 Key没证明是本人。在适配层要正确填充authenticatorData里的 UV 标志位并在 RP 侧强制校验该位避免把持有误当成验证。坑 9远程接入时的本地代理可用性。在轨交外场、制造车间、指挥车这类通过远程接入办公的终端上本地代理常因没有常驻权限而未能自启导致浏览器找不到 authenticator。排查时应把代理注册为系统服务并设置开机自启并在断言超时时优先检查本地代理存活状态而不是怀疑 Key 本身。7. 无密码与国密协同的演进判断把视角拉远一点FIDO2/WebAuthn 和国内国密体系并不是互斥关系而是标准外壳 国密内核的叠加。浏览器和 IdP 的世界已经围绕 WebAuthn 建立了完整的生态我们没必要重写一套真正需要工程投入的是最底层的authenticator 适配层——让国密芯片用 SM2/SM3 完成挑战-响应对外暴露标准接口。这条路径的收益是双向的一方面无密码认证把密码 软件令牌的钓鱼面整体收敛另一方面国密合规要求由硬件Key在芯片内闭环满足不依赖任何软件侧密钥托管。二者在工程上汇于一点私钥只在芯片里签名只在芯片里这是所有安全属性的根。方案参考把国密硬件Key改造成 WebAuthn 认证器落地时可以遵循一套通用方法论而不必绑定某一款产品接口对齐确认 Key 是否提供C动态库与RESTful两类接口前者用于低时延断言后者用于运维与初始化。算法声明在attestationObject中正确声明国密算法标识并在 RP 验签侧实现对应的 SM2/SM3 分支避免与国际算法混用。私钥边界所有签名必须在芯片内完成任何上层接口都只回传签名值与公钥从设计上保证私钥不可导出。抗钓鱼锚点签名原文必须覆盖rpIdHash与challenge并在 RP 侧二次校验rpIdHash这是无密码抗钓鱼的硬约束。计数器与克隆检测signCount在芯片内单调持久化RP 侧再校验一次形成双重防御。回退策略保留密码 动态口令回退通道但对其做信任等级标记、权限收敛与审计避免回退通道被常态化。合规闭环用 SM2 签名 CA 证书满足身份真实、数据完整、操作不可否认用 SM4 会话加密满足传输机密性在信创环境下完成驱动与库的适配。固件可信开启固件签名校验防止恶意镜像刷写导致密钥泄露。安当UKey 的定位是这套方法论里一个国密安全芯片硬件级认证与加解密的可用载体它在 32 位 RISC 芯片上以 128 KB 资源实现了 SM1/SM2/SM3/SM4 及 RSA/AES/ECC/SHA 的全算法支撑通过Web 双因素、C-S 认证、软件授权保护、会话加密、OS 双因素五个方向覆盖从登录到业务操作的认证面并以KeyID→UserName、KeyID→签名验签、CA 证书等认证方案对接既有 IdP。对于需要在电网调度指令签名、政务 SSO、轨交外场、制造车间 SCADA、CAD 授权、ERP 防盗版、远程接入指挥车等场合同时满足无密码体验与国密合规的团队它可以作为认证器适配层的一个参考实现来评估和集成。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。