You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebAuthn中Yubico密钥userHandle返回异常问题问询

Yubico密钥无密码登录:解决AGGUID无法获取及userHandle异常问题

问题背景

在用Yubico密钥实现无密码登录时,需在登录阶段解密数据,遇到两个核心问题:

  1. 原本计划使用密钥AGGUID,但该值仅在注册(navigator.credentials.create())阶段可获取,登录(navigator.credentials.get())阶段无法拿到,此方案不可行。
  2. 尝试通过create()的userHandle参数存储数据,登录时读取,但无论是否传入该参数,get()返回的userHandle始终是ArrayBuffer(1)。

问题原因

1. AGGUID的规范限制

WebAuthn规范明确规定,AGGUID仅在注册流程的attestation响应中返回,断言(登录)流程不会提供该字段,因此无法通过此途径获取密钥标识用于解密。

2. userHandle异常的本质

  • WebAuthn的PublicKeyCredentialCreationOptions参数中不存在userHandle字段,你传入的该参数会被浏览器忽略,根本不会存储到密钥上。
  • 你看到的ArrayBuffer(1),实际是你在create()的user.id中传入的Uint8Array(1)——user.id才是WebAuthn规范中定义的、会被密钥关联存储的用户标识,登录时会原样返回。

解决方案

正确存储自定义数据

将解密所需的编码后数据(比如用户唯一标识、加密密钥片段等)作为user.id传入注册流程,替代无效的userHandle参数:

// 注册阶段的create()参数(修正版)
const createOptions = {
  attestation: "direct",
  authenticatorSelection: {
    authenticatorAttachment: 'cross-platform',
    userVerification: 'required',
    requireResidentKey: true,
    residentKey: 'required'
  },
  challenge: new Uint8Array([113, 73, 120, 104, 50, 115, 117, 82, 57, 109, 111, 81, 119, 85, 65, 120, 69, 105, 108, 114, 112, 103, 53, 101, 68, 65, 73, 89, 85, 67, 71, 67]),
  pubKeyCredParams: [{ alg: -7 }], // 根据实际加密算法调整,-7为ES256
  rp: { id: 'domain', name: 'localhost' },
  timeout: 10000,
  user: {
    id: new Uint8Array([/* 此处放入你需要存储的32字节数据,比如用户ID的哈希值 */]),
    name: 'hello@netrizon.eu',
    displayName: 'Świerżewski'
  }
};

const credential = await navigator.credentials.create({ publicKey: createOptions });

登录阶段读取数据

登录时,response.userHandle会返回注册时传入的user.id,将其转换为对应格式即可获取存储的数据:

// 登录阶段的get()参数
const getOptions = {
  allowCredentials: [{/* 填入已注册的凭证信息,包括id、type、transports */}],
  challenge: new Uint8Array([68, 78, 65, 120, 97, 80, 56, 50, 78, 117, 71, 89, 86, 108, 86, 117, 65, 111, 114, 121, 78, 97, 105, 98, 81, 80, 104, 82, 101, 74, 86, 82]),
  rpId: "domain",
  timeout: 60000,
  userVerification: "required"
};

const assertion = await navigator.credentials.get({ publicKey: getOptions });
// 读取并转换userHandle
const storedData = new Uint8Array(assertion.response.userHandle);
// 用storedData进行解密操作

注意事项

  • Yubico密钥对user.id的长度有上限(通常建议不超过64字节),需确保存储的数据在限制范围内。
  • 存储的数据需提前编码为Uint8Array,避免字符编码问题。

内容的提问来源于stack exchange,提问作者Swiru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:42:28