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

询问将敏感数据存储到WebAuthN userHandle的安全性问题

更新于2024年2月28日

  • 已知首个问题:user handle(id)的长度限制为64字节

根据相关讨论,认证器可能不会将id视为敏感信息(不过我的测试未找到相关证据)


我刚开发了一款基于客户端的2FA应用。我希望它仅在客户端运行,无需服务器,用户数据将存储在客户端的安全容器中,并可(加密后)同步至Google Drive应用数据文件夹,该文件夹需结合API密钥与用户OAuth2令牌才能访问。

用户每次刷新浏览器,OTP数据库都会关闭,我正在寻找无需用户再次输入密码即可便捷打开容器的方法。

我的拟用方案是利用WebAuthN的id字段存储容器的哈希用户密码,用户每次登录时从中提取该密码。我知道这是一种“投机取巧”的做法,并非WebAuthN的设计用途,但想知道这种做法存在的问题?

以下是我计划实现的代码示例(已测试,可正常运行):

const LOCAL_STORAGE_KEY = "credentialId";

async function storeSensitiveDataToWebauthN(sensitiveString) {
  let userHandle = new TextEncoder().encode(sensitiveString);

  let createOptions = {
    publicKey: {
      rp: { name: "My local test" },
      user: {
        id: userHandle,
        name: "example@example.com",
        displayName: "Example User",
      },
      challenge: new Uint8Array(32), // In practice, should be generated by the server
      pubKeyCredParams: [{ alg: -7, type: "public-key" }],
    },
  };

  const credential = await navigator.credentials.create(createOptions);

  localStorage.setItem(
    LOCAL_STORAGE_KEY,
    btoa(String.fromCharCode.apply(null, new Uint8Array(credential.rawId)))
  );
}

async function retrieveSensitiveDataFromWebauthN() {
  let credentialId = localStorage.getItem(LOCAL_STORAGE_KEY);

  // Correctly decode the Base64-encoded credential ID before using it

  const decodedCredentialId = Uint8Array.from(atob(credentialId), (c) =>
    c.charCodeAt(0)
  );

  let getCredentialDefaultArgs = {
    publicKey: {
      challenge: new Uint8Array(32), // Should be securely generated
      allowCredentials: [{ id: decodedCredentialId, type: "public-key" }],
    },
  };

  const assertion = await navigator.credentials.get(getCredentialDefaultArgs);

  let userHandle = assertion.response.userHandle
    ? new TextDecoder().decode(assertion.response.userHandle)
    : null;

  return userHandle;
}

export async function testWebAuthN() {
  const sensitiveString = "USER_HASHED_PASSWORD";
  if (localStorage.getItem(LOCAL_STORAGE_KEY) === null) {
    await storeSensitiveDataToWebauthN(sensitiveString);
  }
  const dateRecieved = await retrieveSensitiveDataFromWebauthN();
  if (!dateRecieved === sensitiveString) {
    console.error("Error: WebauthN failed to retrieve the correct data");
  }
  console.log("dateRecieved = ", dateRecieved);
}

我非常希望了解将敏感数据存储到user id中是否存在安全问题,或是有其他我忽略的要点:-)

[各位请注意,我知道这是一种取巧方案,我的问题是这种做法是否存在任何问题]


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 09:09:52