我想使用 WebAuthn 在移动 Safari 上安全地存储和检索一些敏感信息。
我特别提到 Safari,因为它是我的主要目标浏览器,并且那里不支持密码凭据的存储和检索。理想情况下,我想在 iOS 上使用设备生物识别传感器,据我了解,只能使用 WebAuthn 和公钥凭证。
我不想创建一个基于服务器的服务来存储这些敏感信息并评估凭证签名。我想完全在客户端实现。
是否有任何简单或解决方法可以实现此目的?
密钥是用于防网络钓鱼身份验证的凭证。它并非旨在存储任意信息,WebAuthn 也并非旨在存储或检索任意信息。
我为此编写了这个演示代码。
所以这是可能的。
我仍在等待人们回答这个问题有多糟糕,以及是否有任何问题。
将数据存储到 webAuthN userHandle 有多糟糕?
[这里附上演示代码供您尝试]
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: "[email protected]",
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);
}