WebAuthn は認証用の比較的新しいAPIであり、パスワードなどの代わりに公開鍵暗号を使用します。
暗号化の部分を別の目的に使用できるかどうか、特にブラウザーでドキュメントのデジタル署名を作成できるかどうか疑問に思っています。
アイデアは、サーバーが偽造したり操作したりできないように、ユーザーがブラウザーでドキュメントに署名する方法を見つけることです。したがって、Webアプリケーション自体は、署名に使用される秘密鍵を知ってはなりません。これは、私の知る限り、WebAuthnの場合です。
したがって、WebAuthnが期待するランダムなチャレンジの代わりに、ユーザーに署名してほしいドキュメントのコンテンツを送信する場合、MDNの説明を正しく理解していれば、ドキュメントの暗号で署名されたハッシュを返す必要があります。
最後に、このドキュメントが特定のハードウェアトークンからの特定の秘密キーによって署名されたことを証明するために使用できるデジタル署名が必要です。また、ブラウザー内のWebアプリケーションもサーバーコンポーネントも秘密鍵を見たことがないため、この署名を偽造することはできません(もちろん、アプリケーションは、署名する前にコンテンツを切り替えることでこれを危険にさらす可能性がありますが、後で署名することはできません)。
私はこの目的でWebAuthnを使用している人には何も見つけることができませんでした。ブラウザのデジタル署名に関連して見つけることができるものは、Javaアプレットのようなもので、今日のオプションではなくなりました。
私の考えは一般的に聞こえますか?それとも、WebAuthnのしくみを誤解していて、この方法でWebAuthnを使用することは不可能ですか?このアプローチに欠けている弱点や欠陥はありますか?
Web認証APIのセキュリティチャレンジは、任意のバイト配列(少なくとも16バイト)で可能であり、クライアントの安全な秘密鍵によって署名されます。したがって、navigator.credentials.get()
への呼び出しでPublicKeyCredentialRequestOptions.challenge
としてドキュメントを渡すことにより、ドキュメントまたはすべてのタイプのメッセージに署名するためにも使用できます。
呼び出しによって返されたPublicKeyCredential
にはresponse
プロパティが含まれています。これには、探している署名であるsignature
プロパティが含まれています。
ユースケースに合わせて若干変更されたdeveloper.mozilla.comのサンプルコード:
fetch(/* get file from server */).then(response => response.arrayBuffer()).then(fileFromServer => {
const options = {
challenge: fileFromServer,
rp: {
name: "Example CORP",
id : "login.example.com"
},
user: {
id: userId,
name: "[email protected]",
displayName: "John Doe"
},
pubKeyCredParams: [
{
type: "public-key",
alg: -7
}
]
}
navigator.credentials.get({ publickey: options })
.then(function (pubKeyCredential) {
const signature = pubKeyCredential.response.signature
fetch(/* Send signature to server */)
}).catch(function (err) {
// Deal with any error
})
})