2024年2月22日木曜日

パスキー登録APIのレスポンスを解析する

こんにちは、富士榮です。

先日、いろいろな認証器でパスキー登録をしてみましたが、レスポンスの中のフラグをどうやって取得するの?というあたりについて細かく解説していないの今回解説していきたいと思います。

navigator.credentials.create()メソッドの返却値の定義がこちらのドキュメントにあります。

https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create#return_value_2

定義によると、PublicKeyCredentialが返されるようですね。

A Promise that resolves with an PublicKeyCredential instance matching the provided parameters. If no credential object can be created, the promise resolves with null.

では、PuiblicKeyCredentialの定義を見ていきましょう。

https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential

以下のメンバが含まれます。

  • PublicKeyCredential.authenticatorAttachment
  • PublicKeyCredential.id
  • PublicKeyCredential.rawId
  • PublicKeyCredential.response
  • PublicKeyCredential.type
上記のうち、PublicKeyCredential.responseの中に各種フラグなどが格納されます。
このresponseはAuthenticatorAttestationResponse(AuthenticatorResponseから継承)にはgetAuthenticatorData()というメソッドがあり、認証器のデータを取得できます。
このメソッドは最低37バイトからなるArrayBufferであるAuthenticator dataという形式のデータを返却します。
回りくどかったですが、このAuthenticator Dataの中に欲しい情報が入っています。
先に書いた通り、この返却値はArrayBufferで、
  • rpIdHash (32 bytes)
  • flags (1 bytes)
  • signCount (4 bytes)
  • attestedCredentialData (variable length)
  • extensions (variable length)
という構造になっています。

先日のポストではこの33バイト目にあるflagsの値を見ていたわけです。
flagsの値を再掲しますが、この1バイトの中の各ビットが認証器が使用されたときの状態を表しています。
Bit意味説明
0User Presence (UP)If set (i.e., to 1), the authenticator validated that the user was present through some Test of User Presence (TUP), such as touching a button on the authenticator.
1--
2User Verification (UV)If set, the authenticator verified the actual user through a biometric, PIN, or other method.
3Backup Eligibility (BE)If set, the public key credential source used by the authenticator to generate an assertion is backup-eligible. This means that it can be backed up in some fashion (for example via cloud or local network sync) and as such may become present on an authenticator other than its generating authenticator. Backup-eligible credential sources are therefore also known as multi-device credentials.
4Backup State (BS)If set, the public key credential source is currently backed up (see Bit 3 for context).
5--
6Attested Credential Data (AT)If set, the attested credential data will immediately follow the first 37 bytes of this authenticatorData.
7Extension Data (ED)If set, extension data is present. Extension data will follow attested credential data if it is present, or will immediately follow the first 37 bytes of the authenticatorData if no attested credential data is present.


この辺りをコードで表すとこんな感じになります。

まずはcreate()を行います。
// ブラウザAPIの呼び出し
const cred = await navigator.credentials.create({
publicKey: options,
});

フラグの値を取得します。
const flags = new DataView(cred.response.getAuthenticatorData()).getUint8(32).toString();
$("#userPresence").text("User Presence(UP) : "+ ((Number(flags) & 1)? 'Yes': 'No'));
$("#userVerification").text("User Verification(UV) : "+ ((Number(flags) & 4)? 'Yes': 'No'));
$("#backupEligibility").text("Backup Eligibility(BE) : "+ ((Number(flags) & 8)? 'Yes': 'No'));
$("#backupState").text("Backup State(BS) : "+ ((Number(flags) & 16)? 'Yes': 'No'));
$("#attestedCredentialData").text("Attested Credential Data(AT) : "+ ((Number(flags) & 64)? 'Yes': 'No'));
$("#extensionData").text("Extension Data(ED) : "+ ((Number(flags) & 128)? 'Yes': 'No'));

getUint8の引数で32バイトオフセットすることでflagsのところまで辿りつけるので、その値をNumber化した上で各ビット単位で論理和をとって状態を取得しています。

ざっとこんな感じでフラグを取得していました、という種明かしでした。









0 件のコメント: