@metamask/passkey-controller 3.1.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/README.md +101 -9
  3. package/dist/{PasskeyController-method-action-types.d.mts → PasskeyController-method-action-types.d.ts} +44 -3
  4. package/dist/PasskeyController-method-action-types.d.ts.map +1 -0
  5. package/dist/{PasskeyController-method-action-types.mjs → PasskeyController-method-action-types.js} +1 -1
  6. package/dist/PasskeyController-method-action-types.js.map +1 -0
  7. package/dist/{PasskeyController.d.cts → PasskeyController.d.ts} +41 -6
  8. package/dist/PasskeyController.d.ts.map +1 -0
  9. package/dist/PasskeyController.js +828 -0
  10. package/dist/PasskeyController.js.map +1 -0
  11. package/dist/{ceremony-manager.d.cts → ceremony-manager.d.ts} +2 -2
  12. package/dist/ceremony-manager.d.ts.map +1 -0
  13. package/dist/ceremony-manager.js +150 -0
  14. package/dist/ceremony-manager.js.map +1 -0
  15. package/dist/{constants.d.mts → constants.d.ts} +18 -12
  16. package/dist/constants.d.ts.map +1 -0
  17. package/dist/{constants.mjs → constants.js} +7 -1
  18. package/dist/constants.js.map +1 -0
  19. package/dist/{errors.d.mts → errors.d.ts} +2 -2
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/{errors.mjs → errors.js} +4 -1
  22. package/dist/errors.js.map +1 -0
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +5 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/{key-derivation.d.cts → key-derivation.d.ts} +3 -3
  28. package/dist/key-derivation.d.ts.map +1 -0
  29. package/dist/{key-derivation.mjs → key-derivation.js} +5 -5
  30. package/dist/key-derivation.js.map +1 -0
  31. package/dist/logger.d.ts +4 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +6 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/{types.d.cts → types.d.ts} +23 -9
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/utils/{crypto.d.mts → crypto.d.ts} +1 -1
  40. package/dist/utils/crypto.d.ts.map +1 -0
  41. package/dist/utils/{crypto.mjs → crypto.js} +10 -8
  42. package/dist/utils/crypto.js.map +1 -0
  43. package/dist/utils/{encoding.d.cts → encoding.d.ts} +1 -1
  44. package/dist/utils/encoding.d.ts.map +1 -0
  45. package/dist/utils/{encoding.mjs → encoding.js} +2 -2
  46. package/dist/utils/encoding.js.map +1 -0
  47. package/dist/webauthn/{constants.d.mts → constants.d.ts} +1 -1
  48. package/dist/webauthn/constants.d.ts.map +1 -0
  49. package/dist/webauthn/{constants.mjs → constants.js} +1 -1
  50. package/dist/webauthn/constants.js.map +1 -0
  51. package/dist/webauthn/{decode-attestation-object.d.mts → decode-attestation-object.d.ts} +2 -2
  52. package/dist/webauthn/decode-attestation-object.d.ts.map +1 -0
  53. package/dist/webauthn/{decode-attestation-object.mjs → decode-attestation-object.js} +2 -2
  54. package/dist/webauthn/decode-attestation-object.js.map +1 -0
  55. package/dist/webauthn/{decode-client-data-json.d.cts → decode-client-data-json.d.ts} +2 -2
  56. package/dist/webauthn/decode-client-data-json.d.ts.map +1 -0
  57. package/dist/webauthn/{decode-client-data-json.mjs → decode-client-data-json.js} +2 -2
  58. package/dist/webauthn/decode-client-data-json.js.map +1 -0
  59. package/dist/webauthn/{match-expected-rp-id.d.cts → match-expected-rp-id.d.ts} +3 -3
  60. package/dist/webauthn/match-expected-rp-id.d.ts.map +1 -0
  61. package/dist/webauthn/{match-expected-rp-id.mjs → match-expected-rp-id.js} +6 -7
  62. package/dist/webauthn/match-expected-rp-id.js.map +1 -0
  63. package/dist/webauthn/{parse-authenticator-data.d.cts → parse-authenticator-data.d.ts} +2 -2
  64. package/dist/webauthn/parse-authenticator-data.d.ts.map +1 -0
  65. package/dist/webauthn/{parse-authenticator-data.mjs → parse-authenticator-data.js} +2 -2
  66. package/dist/webauthn/parse-authenticator-data.js.map +1 -0
  67. package/dist/webauthn/{types.d.mts → types.d.ts} +2 -2
  68. package/dist/webauthn/types.d.ts.map +1 -0
  69. package/dist/webauthn/types.js +2 -0
  70. package/dist/webauthn/types.js.map +1 -0
  71. package/dist/webauthn/{verify-authentication-response.d.cts → verify-authentication-response.d.ts} +3 -3
  72. package/dist/webauthn/verify-authentication-response.d.ts.map +1 -0
  73. package/dist/webauthn/{verify-authentication-response.mjs → verify-authentication-response.js} +13 -11
  74. package/dist/webauthn/verify-authentication-response.js.map +1 -0
  75. package/dist/webauthn/{verify-registration-response.d.mts → verify-registration-response.d.ts} +3 -3
  76. package/dist/webauthn/verify-registration-response.d.ts.map +1 -0
  77. package/dist/webauthn/{verify-registration-response.mjs → verify-registration-response.js} +12 -13
  78. package/dist/webauthn/verify-registration-response.js.map +1 -0
  79. package/dist/webauthn/{verify-signature.d.cts → verify-signature.d.ts} +4 -3
  80. package/dist/webauthn/verify-signature.d.ts.map +1 -0
  81. package/dist/webauthn/{verify-signature.mjs → verify-signature.js} +17 -16
  82. package/dist/webauthn/verify-signature.js.map +1 -0
  83. package/package.json +16 -21
  84. package/dist/PasskeyController-method-action-types.cjs +0 -7
  85. package/dist/PasskeyController-method-action-types.cjs.map +0 -1
  86. package/dist/PasskeyController-method-action-types.d.cts +0 -204
  87. package/dist/PasskeyController-method-action-types.d.cts.map +0 -1
  88. package/dist/PasskeyController-method-action-types.d.mts.map +0 -1
  89. package/dist/PasskeyController-method-action-types.mjs.map +0 -1
  90. package/dist/PasskeyController.cjs +0 -685
  91. package/dist/PasskeyController.cjs.map +0 -1
  92. package/dist/PasskeyController.d.cts.map +0 -1
  93. package/dist/PasskeyController.d.mts +0 -208
  94. package/dist/PasskeyController.d.mts.map +0 -1
  95. package/dist/PasskeyController.mjs +0 -680
  96. package/dist/PasskeyController.mjs.map +0 -1
  97. package/dist/ceremony-manager.cjs +0 -135
  98. package/dist/ceremony-manager.cjs.map +0 -1
  99. package/dist/ceremony-manager.d.cts.map +0 -1
  100. package/dist/ceremony-manager.d.mts +0 -72
  101. package/dist/ceremony-manager.d.mts.map +0 -1
  102. package/dist/ceremony-manager.mjs +0 -131
  103. package/dist/ceremony-manager.mjs.map +0 -1
  104. package/dist/constants.cjs +0 -39
  105. package/dist/constants.cjs.map +0 -1
  106. package/dist/constants.d.cts +0 -36
  107. package/dist/constants.d.cts.map +0 -1
  108. package/dist/constants.d.mts.map +0 -1
  109. package/dist/constants.mjs.map +0 -1
  110. package/dist/errors.cjs +0 -57
  111. package/dist/errors.cjs.map +0 -1
  112. package/dist/errors.d.cts +0 -34
  113. package/dist/errors.d.cts.map +0 -1
  114. package/dist/errors.d.mts.map +0 -1
  115. package/dist/errors.mjs.map +0 -1
  116. package/dist/index.cjs +0 -15
  117. package/dist/index.cjs.map +0 -1
  118. package/dist/index.d.cts +0 -8
  119. package/dist/index.d.cts.map +0 -1
  120. package/dist/index.d.mts +0 -8
  121. package/dist/index.d.mts.map +0 -1
  122. package/dist/index.mjs +0 -5
  123. package/dist/index.mjs.map +0 -1
  124. package/dist/key-derivation.cjs +0 -44
  125. package/dist/key-derivation.cjs.map +0 -1
  126. package/dist/key-derivation.d.cts.map +0 -1
  127. package/dist/key-derivation.d.mts +0 -20
  128. package/dist/key-derivation.d.mts.map +0 -1
  129. package/dist/key-derivation.mjs.map +0 -1
  130. package/dist/logger.cjs +0 -9
  131. package/dist/logger.cjs.map +0 -1
  132. package/dist/logger.d.cts +0 -5
  133. package/dist/logger.d.cts.map +0 -1
  134. package/dist/logger.d.mts +0 -5
  135. package/dist/logger.d.mts.map +0 -1
  136. package/dist/logger.mjs +0 -6
  137. package/dist/logger.mjs.map +0 -1
  138. package/dist/types.cjs +0 -4
  139. package/dist/types.cjs.map +0 -1
  140. package/dist/types.d.cts.map +0 -1
  141. package/dist/types.d.mts +0 -132
  142. package/dist/types.d.mts.map +0 -1
  143. package/dist/types.mjs +0 -2
  144. package/dist/types.mjs.map +0 -1
  145. package/dist/utils/crypto.cjs +0 -66
  146. package/dist/utils/crypto.cjs.map +0 -1
  147. package/dist/utils/crypto.d.cts +0 -37
  148. package/dist/utils/crypto.d.cts.map +0 -1
  149. package/dist/utils/crypto.d.mts.map +0 -1
  150. package/dist/utils/crypto.mjs.map +0 -1
  151. package/dist/utils/encoding.cjs +0 -42
  152. package/dist/utils/encoding.cjs.map +0 -1
  153. package/dist/utils/encoding.d.cts.map +0 -1
  154. package/dist/utils/encoding.d.mts +0 -22
  155. package/dist/utils/encoding.d.mts.map +0 -1
  156. package/dist/utils/encoding.mjs.map +0 -1
  157. package/dist/webauthn/constants.cjs +0 -74
  158. package/dist/webauthn/constants.cjs.map +0 -1
  159. package/dist/webauthn/constants.d.cts +0 -68
  160. package/dist/webauthn/constants.d.cts.map +0 -1
  161. package/dist/webauthn/constants.d.mts.map +0 -1
  162. package/dist/webauthn/constants.mjs.map +0 -1
  163. package/dist/webauthn/decode-attestation-object.cjs +0 -18
  164. package/dist/webauthn/decode-attestation-object.cjs.map +0 -1
  165. package/dist/webauthn/decode-attestation-object.d.cts +0 -10
  166. package/dist/webauthn/decode-attestation-object.d.cts.map +0 -1
  167. package/dist/webauthn/decode-attestation-object.d.mts.map +0 -1
  168. package/dist/webauthn/decode-attestation-object.mjs.map +0 -1
  169. package/dist/webauthn/decode-client-data-json.cjs +0 -17
  170. package/dist/webauthn/decode-client-data-json.cjs.map +0 -1
  171. package/dist/webauthn/decode-client-data-json.d.cts.map +0 -1
  172. package/dist/webauthn/decode-client-data-json.d.mts +0 -9
  173. package/dist/webauthn/decode-client-data-json.d.mts.map +0 -1
  174. package/dist/webauthn/decode-client-data-json.mjs.map +0 -1
  175. package/dist/webauthn/match-expected-rp-id.cjs +0 -26
  176. package/dist/webauthn/match-expected-rp-id.cjs.map +0 -1
  177. package/dist/webauthn/match-expected-rp-id.d.cts.map +0 -1
  178. package/dist/webauthn/match-expected-rp-id.d.mts +0 -11
  179. package/dist/webauthn/match-expected-rp-id.d.mts.map +0 -1
  180. package/dist/webauthn/match-expected-rp-id.mjs.map +0 -1
  181. package/dist/webauthn/parse-authenticator-data.cjs +0 -69
  182. package/dist/webauthn/parse-authenticator-data.cjs.map +0 -1
  183. package/dist/webauthn/parse-authenticator-data.d.cts.map +0 -1
  184. package/dist/webauthn/parse-authenticator-data.d.mts +0 -10
  185. package/dist/webauthn/parse-authenticator-data.d.mts.map +0 -1
  186. package/dist/webauthn/parse-authenticator-data.mjs.map +0 -1
  187. package/dist/webauthn/types.cjs +0 -3
  188. package/dist/webauthn/types.cjs.map +0 -1
  189. package/dist/webauthn/types.d.cts +0 -113
  190. package/dist/webauthn/types.d.cts.map +0 -1
  191. package/dist/webauthn/types.d.mts.map +0 -1
  192. package/dist/webauthn/types.mjs +0 -2
  193. package/dist/webauthn/types.mjs.map +0 -1
  194. package/dist/webauthn/verify-authentication-response.cjs +0 -133
  195. package/dist/webauthn/verify-authentication-response.cjs.map +0 -1
  196. package/dist/webauthn/verify-authentication-response.d.cts.map +0 -1
  197. package/dist/webauthn/verify-authentication-response.d.mts +0 -64
  198. package/dist/webauthn/verify-authentication-response.d.mts.map +0 -1
  199. package/dist/webauthn/verify-authentication-response.mjs.map +0 -1
  200. package/dist/webauthn/verify-registration-response.cjs +0 -242
  201. package/dist/webauthn/verify-registration-response.cjs.map +0 -1
  202. package/dist/webauthn/verify-registration-response.d.cts +0 -81
  203. package/dist/webauthn/verify-registration-response.d.cts.map +0 -1
  204. package/dist/webauthn/verify-registration-response.d.mts.map +0 -1
  205. package/dist/webauthn/verify-registration-response.mjs.map +0 -1
  206. package/dist/webauthn/verify-signature.cjs +0 -176
  207. package/dist/webauthn/verify-signature.cjs.map +0 -1
  208. package/dist/webauthn/verify-signature.d.cts.map +0 -1
  209. package/dist/webauthn/verify-signature.d.mts +0 -21
  210. package/dist/webauthn/verify-signature.d.mts.map +0 -1
  211. package/dist/webauthn/verify-signature.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
- import type { ControllerGetStateAction, ControllerStateChangedEvent } from "@metamask/base-controller";
2
- import type { KeyringControllerChangePasswordAction, KeyringControllerExportAccountAction, KeyringControllerExportEncryptionKeyAction, KeyringControllerExportSeedPhraseAction, KeyringControllerSubmitEncryptionKeyAction, KeyringControllerVerifyPasswordAction } from "@metamask/keyring-controller";
3
- import type { Messenger } from "@metamask/messenger";
4
- import { controllerName } from "./constants.cjs";
5
- import type { PasskeyControllerMethodActions } from "./PasskeyController-method-action-types.cjs";
1
+ import type { ControllerGetStateAction, ControllerStateChangedEvent } from '@metamask/base-controller';
2
+ import type { KeyringControllerChangePasswordAction, KeyringControllerExportAccountAction, KeyringControllerExportEncryptionKeyAction, KeyringControllerExportSeedPhraseAction, KeyringControllerSubmitEncryptionKeyAction, KeyringControllerVerifyPasswordAction } from '@metamask/keyring-controller';
3
+ import type { Messenger } from '@metamask/messenger';
4
+ import { controllerName } from './constants.js';
5
+ import type { PasskeyControllerMethodActions } from './PasskeyController-method-action-types.js';
6
6
  export type Base64String = string;
7
7
  export type Base64URLString = string;
8
8
  export type AuthenticatorTransportFuture = 'ble' | 'cable' | 'hybrid' | 'internal' | 'nfc' | 'smart-card' | 'usb';
@@ -60,9 +60,10 @@ export type PasskeyRecord = {
60
60
  };
61
61
  /**
62
62
  * In-memory state for one **in-flight** WebAuthn **registration** ceremony
63
- * (from `create()` options until `protectVaultKeyWithPasskey` completes). This is
64
- * not a user login session; it is keyed by challenge and distinct from the full
65
- * spec ceremony (which includes the authenticator round-trip).
63
+ * (from `create()` options until the enrollment or replacement completion
64
+ * method finishes). This is not a user login session; it is keyed by challenge
65
+ * and distinct from the full spec ceremony (which includes the authenticator
66
+ * round-trip).
66
67
  */
67
68
  export type PasskeyRegistrationCeremony = {
68
69
  userHandle: Base64URLString;
@@ -70,6 +71,14 @@ export type PasskeyRegistrationCeremony = {
70
71
  challenge: Base64URLString;
71
72
  /** When this ceremony was started (ms since epoch); used for TTL pruning. */
72
73
  createdAt: number;
74
+ /**
75
+ * Whether this ceremony is for replacing an existing passkey.
76
+ *
77
+ * Omitted or `false` for existing enrollment ceremonies.
78
+ */
79
+ isReplacement?: boolean;
80
+ /** Credential ID of the record being replaced. */
81
+ sourceCredentialId?: Base64URLString;
73
82
  };
74
83
  /**
75
84
  * In-memory state for one **in-flight** WebAuthn **authentication** ceremony
@@ -77,6 +86,11 @@ export type PasskeyRegistrationCeremony = {
77
86
  */
78
87
  export type PasskeyAuthenticationCeremony = {
79
88
  challenge: Base64URLString;
89
+ /**
90
+ * Registration challenge when this authentication is the post-registration
91
+ * step of an enrollment or replacement ceremony.
92
+ */
93
+ registrationChallenge?: Base64URLString;
80
94
  /** When this ceremony was started (ms since epoch); used for TTL pruning. */
81
95
  createdAt: number;
82
96
  };
@@ -129,4 +143,4 @@ export type PasskeyControllerOptions = {
129
143
  */
130
144
  getIsOnboardingCompleted: () => boolean;
131
145
  };
132
- //# sourceMappingURL=types.d.cts.map
146
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangedEvent,\n} from '@metamask/base-controller';\nimport type {\n KeyringControllerChangePasswordAction,\n KeyringControllerExportAccountAction,\n KeyringControllerExportEncryptionKeyAction,\n KeyringControllerExportSeedPhraseAction,\n KeyringControllerSubmitEncryptionKeyAction,\n KeyringControllerVerifyPasswordAction,\n} from '@metamask/keyring-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport { controllerName } from './constants.js';\nimport type { PasskeyControllerMethodActions } from './PasskeyController-method-action-types.js';\n\nexport type Base64String = string;\n\nexport type Base64URLString = string;\n\nexport type AuthenticatorTransportFuture =\n | 'ble'\n | 'cable'\n | 'hybrid'\n | 'internal'\n | 'nfc'\n | 'smart-card'\n | 'usb';\n\n/**\n * WebAuthn credential metadata used to identify the passkey and verify\n * subsequent assertions.\n */\nexport type PasskeyCredentialInfo = {\n /** WebAuthn credential ID (base64url). */\n id: Base64URLString;\n /** COSE-encoded credential public key (base64url) used to verify assertions. */\n publicKey: Base64URLString;\n /** Authenticator signature counter for replay/clone detection. */\n counter: number;\n /** Authenticator transports hint for `allowCredentials`. */\n transports?: AuthenticatorTransportFuture[];\n /** Authenticator AAGUID captured from attested credential data at registration. */\n aaguid: string;\n};\n\n/**\n * Vault key wrapped under the passkey-derived AES-256-GCM key.\n */\nexport type EncryptedVaultKey = {\n /** Base64-encoded AES-256-GCM ciphertext of the vault key. */\n ciphertext: Base64String;\n /** Base64-encoded AES-GCM IV used during encryption. */\n iv: Base64String;\n};\n\n/**\n * Parameters needed to reproduce the AES-256 wrapping key at unlock time.\n *\n * Encoded as a discriminated union so PRF-only fields (e.g. `prfSalt`) can\n * only exist on the PRF branch, removing the \"optional but actually\n * required\" footgun.\n */\nexport type PasskeyKeyDerivation =\n | {\n method: 'prf';\n /**\n * PRF salt sent in `get()` extension options to reproduce the same PRF\n * output that was generated at registration.\n */\n prfSalt: Base64URLString;\n }\n | { method: 'userHandle' };\n\n/** Discriminator value for {@link PasskeyKeyDerivation}. */\nexport type PasskeyDerivationMethod = PasskeyKeyDerivation['method'];\n\nexport type PasskeyRecord = {\n /** WebAuthn credential metadata used for assertion verification & re-discovery. */\n credential: PasskeyCredentialInfo;\n /** Vault key wrapped under the passkey-derived key. */\n encryptedVaultKey: EncryptedVaultKey;\n /** How the wrapping key is reconstructed at unlock time. */\n keyDerivation: PasskeyKeyDerivation;\n};\n\n/**\n * In-memory state for one **in-flight** WebAuthn **registration** ceremony\n * (from `create()` options until the enrollment or replacement completion\n * method finishes). This is not a user login session; it is keyed by challenge\n * and distinct from the full spec ceremony (which includes the authenticator\n * round-trip).\n */\nexport type PasskeyRegistrationCeremony = {\n userHandle: Base64URLString;\n prfSalt?: Base64URLString;\n challenge: Base64URLString;\n /** When this ceremony was started (ms since epoch); used for TTL pruning. */\n createdAt: number;\n /**\n * Whether this ceremony is for replacing an existing passkey.\n *\n * Omitted or `false` for existing enrollment ceremonies.\n */\n isReplacement?: boolean;\n /** Credential ID of the record being replaced. */\n sourceCredentialId?: Base64URLString;\n};\n\n/**\n * In-memory state for one **in-flight** WebAuthn **authentication** ceremony\n * (`get()` options until the assertion is verified). Not a user login session.\n */\nexport type PasskeyAuthenticationCeremony = {\n challenge: Base64URLString;\n /**\n * Registration challenge when this authentication is the post-registration\n * step of an enrollment or replacement ceremony.\n */\n registrationChallenge?: Base64URLString;\n /** When this ceremony was started (ms since epoch); used for TTL pruning. */\n createdAt: number;\n};\n\n/**\n * PRF extension types not covered by DOM typings.\n */\nexport type PrfEvalExtension = {\n eval: {\n first: Base64URLString;\n };\n};\n\nexport type PrfClientExtensionResults = {\n prf?: {\n enabled?: boolean;\n results?: { first?: Base64URLString };\n };\n};\n\nexport type PasskeyControllerState = {\n passkeyRecord: PasskeyRecord | null;\n};\n\nexport type PasskeyControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n PasskeyControllerState\n>;\n\n/**\n * KeyringController actions that {@link PasskeyController} may call during\n * orchestrated passkey flows. The restricted messenger must allow these at init.\n */\nexport type PasskeyControllerAllowedActions =\n | KeyringControllerVerifyPasswordAction\n | KeyringControllerExportEncryptionKeyAction\n | KeyringControllerSubmitEncryptionKeyAction\n | KeyringControllerChangePasswordAction\n | KeyringControllerExportSeedPhraseAction\n | KeyringControllerExportAccountAction;\n\n/**\n * Actions exposed by {@link PasskeyController} on its messenger, including\n * `:getState`, enrollment/unlock ceremony methods, and lifecycle helpers.\n */\nexport type PasskeyControllerActions =\n | PasskeyControllerGetStateAction\n | PasskeyControllerMethodActions;\n\nexport type PasskeyControllerStateChangedEvent = ControllerStateChangedEvent<\n typeof controllerName,\n PasskeyControllerState\n>;\n\nexport type PasskeyControllerEvents = PasskeyControllerStateChangedEvent;\n\nexport type PasskeyControllerMessenger = Messenger<\n typeof controllerName,\n PasskeyControllerActions | PasskeyControllerAllowedActions,\n PasskeyControllerEvents\n>;\n\nexport type PasskeyControllerOptions = {\n messenger: PasskeyControllerMessenger;\n state?: Partial<PasskeyControllerState>;\n rpId?: string;\n expectedRPID: string | string[];\n rpName: string;\n expectedOrigin: string | string[];\n userName?: string;\n userDisplayName?: string;\n /**\n * Returns whether wallet onboarding is complete. When `true`, enrollment\n * requires password step-up. The integrator typically supplies\n * `() => onboardingController.state.completedOnboarding`.\n */\n getIsOnboardingCompleted: () => boolean;\n};\n"]}
@@ -34,4 +34,4 @@ export declare function encryptWithKey(plaintext: string, key: Uint8Array): {
34
34
  * @returns Decrypted UTF-8 string.
35
35
  */
36
36
  export declare function decryptWithKey(ciphertext: string, iv: string, key: Uint8Array): string;
37
- //# sourceMappingURL=crypto.d.mts.map
37
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,UAAU,GACf,UAAU,CAIZ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,UAAU,GACd;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CASpC;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,UAAU,GACd,MAAM,CAMR"}
@@ -1,9 +1,9 @@
1
- import { bytesToBase64, base64ToBytes } from "@metamask/utils";
2
- import { gcm } from "@noble/ciphers/aes";
3
- import { randomBytes } from "@noble/ciphers/webcrypto";
4
- import { hkdf } from "@noble/hashes/hkdf";
5
- import { sha256 } from "@noble/hashes/sha2";
6
- import { bytesToBase64URL } from "./encoding.mjs";
1
+ import { bytesToBase64, base64ToBytes } from '@metamask/utils';
2
+ import { gcm } from '@noble/ciphers/aes';
3
+ import { randomBytes } from '@noble/ciphers/webcrypto';
4
+ import { hkdf } from '@noble/hashes/hkdf';
5
+ import { sha256 as nobleSha256 } from '@noble/hashes/sha2';
6
+ import { bytesToBase64URL } from './encoding.js';
7
7
  const PASSKEY_HKDF_INFO = 'metamask:passkey:encryption-key:v1';
8
8
  const AES_GCM_IV_LENGTH = 12;
9
9
  /**
@@ -24,7 +24,9 @@ export function randomBytesToBase64URL(byteLength) {
24
24
  * @returns 32-byte derived encryption key.
25
25
  */
26
26
  export function deriveEncryptionKey(ikm, salt) {
27
- return hkdf(sha256, ikm, salt, PASSKEY_HKDF_INFO, 32);
27
+ // @noble/hashes/hkdf accepts only a synchronous hash callback, so this
28
+ // synchronous HKDF path intentionally retains Noble SHA-256.
29
+ return hkdf(nobleSha256, ikm, salt, PASSKEY_HKDF_INFO, 32);
28
30
  }
29
31
  /**
30
32
  * Encrypts plaintext with an AES-256-GCM key.
@@ -56,4 +58,4 @@ export function decryptWithKey(ciphertext, iv, key) {
56
58
  const plaintext = gcm(key, ivBytes).decrypt(ciphertextBytes);
57
59
  return new TextDecoder().decode(plaintext);
58
60
  }
59
- //# sourceMappingURL=crypto.mjs.map
61
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,iBAAiB,GAAG,oCAAoC,CAAC;AAE/D,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,OAAO,gBAAgB,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAe,EACf,IAAgB;IAEhB,uEAAuE;IACvE,6DAA6D;IAC7D,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,GAAe;IAEf,MAAM,EAAE,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEtD,OAAO;QACL,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC;QAC1C,EAAE,EAAE,aAAa,CAAC,EAAE,CAAC;KACtB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAkB,EAClB,EAAU,EACV,GAAe;IAEf,MAAM,eAAe,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAE7D,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import { bytesToBase64, base64ToBytes } from '@metamask/utils';\nimport { gcm } from '@noble/ciphers/aes';\nimport { randomBytes } from '@noble/ciphers/webcrypto';\nimport { hkdf } from '@noble/hashes/hkdf';\nimport { sha256 as nobleSha256 } from '@noble/hashes/sha2';\n\nimport { bytesToBase64URL } from './encoding.js';\n\nconst PASSKEY_HKDF_INFO = 'metamask:passkey:encryption-key:v1';\n\nconst AES_GCM_IV_LENGTH = 12;\n\n/**\n * Generates random bytes and returns them as a base64url string (no padding).\n *\n * @param byteLength - Number of bytes to generate (e.g. WebAuthn challenge length).\n * @returns Base64url-encoded random bytes.\n */\nexport function randomBytesToBase64URL(byteLength: number): string {\n return bytesToBase64URL(randomBytes(byteLength));\n}\n\n/**\n * Derives an AES-256 encryption key from input key material and a credential ID\n * using HKDF-SHA256.\n *\n * @param ikm - Input key material (e.g. PRF output or userHandle).\n * @param salt - HKDF salt.\n * @returns 32-byte derived encryption key.\n */\nexport function deriveEncryptionKey(\n ikm: Uint8Array,\n salt: Uint8Array,\n): Uint8Array {\n // @noble/hashes/hkdf accepts only a synchronous hash callback, so this\n // synchronous HKDF path intentionally retains Noble SHA-256.\n return hkdf(nobleSha256, ikm, salt, PASSKEY_HKDF_INFO, 32);\n}\n\n/**\n * Encrypts plaintext with an AES-256-GCM key.\n *\n * @param plaintext - UTF-8 string to encrypt.\n * @param key - 32-byte AES-256 key from {@link deriveEncryptionKey}.\n * @returns Base64-encoded ciphertext and IV.\n */\nexport function encryptWithKey(\n plaintext: string,\n key: Uint8Array,\n): { ciphertext: string; iv: string } {\n const iv = randomBytes(AES_GCM_IV_LENGTH);\n const encoded = new TextEncoder().encode(plaintext);\n const ciphertextBytes = gcm(key, iv).encrypt(encoded);\n\n return {\n ciphertext: bytesToBase64(ciphertextBytes),\n iv: bytesToBase64(iv),\n };\n}\n\n/**\n * Decrypts AES-256-GCM ciphertext with the given key.\n *\n * @param ciphertext - Base64-encoded ciphertext.\n * @param iv - Base64-encoded initialization vector.\n * @param key - 32-byte AES-256 key from {@link deriveEncryptionKey}.\n * @returns Decrypted UTF-8 string.\n */\nexport function decryptWithKey(\n ciphertext: string,\n iv: string,\n key: Uint8Array,\n): string {\n const ciphertextBytes = base64ToBytes(ciphertext);\n const ivBytes = base64ToBytes(iv);\n const plaintext = gcm(key, ivBytes).decrypt(ciphertextBytes);\n\n return new TextDecoder().decode(plaintext);\n}\n"]}
@@ -19,4 +19,4 @@ export declare function base64URLToBytes(value: string): Uint8Array;
19
19
  * @returns Hex-encoded string.
20
20
  */
21
21
  export declare function bytesToHex(bytes: Uint8Array): string;
22
- //# sourceMappingURL=encoding.d.cts.map
22
+ //# sourceMappingURL=encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../../src/utils/encoding.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAK1D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAI1D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIpD"}
@@ -1,4 +1,4 @@
1
- import { bytesToBase64, base64ToBytes } from "@metamask/utils";
1
+ import { bytesToBase64, base64ToBytes } from '@metamask/utils';
2
2
  /**
3
3
  * Encode a byte array as a base64url string (RFC 4648 §5).
4
4
  *
@@ -33,4 +33,4 @@ export function bytesToHex(bytes) {
33
33
  .map((byte) => byte.toString(16).padStart(2, '0'))
34
34
  .join('');
35
35
  }
36
- //# sourceMappingURL=encoding.mjs.map
36
+ //# sourceMappingURL=encoding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../../src/utils/encoding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,aAAa,CAAC,KAAK,CAAC;SACxB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SACjD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC","sourcesContent":["import { bytesToBase64, base64ToBytes } from '@metamask/utils';\n\n/**\n * Encode a byte array as a base64url string (RFC 4648 §5).\n *\n * @param bytes - The bytes to encode.\n * @returns Base64url-encoded string without padding.\n */\nexport function bytesToBase64URL(bytes: Uint8Array): string {\n return bytesToBase64(bytes)\n .replace(/\\+/gu, '-')\n .replace(/\\//gu, '_')\n .replace(/[=]+$/u, '');\n}\n\n/**\n * Decode a base64url string (RFC 4648 §5) into bytes.\n *\n * @param value - Base64url-encoded string.\n * @returns Decoded bytes.\n */\nexport function base64URLToBytes(value: string): Uint8Array {\n const standard = value.replace(/-/gu, '+').replace(/_/gu, '/');\n const padLength = (4 - (standard.length % 4)) % 4;\n return Uint8Array.from(base64ToBytes(standard + '='.repeat(padLength)));\n}\n\n/**\n * Encode a byte array as a hexadecimal string.\n *\n * @param bytes - The bytes to encode.\n * @returns Hex-encoded string.\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n}\n"]}
@@ -65,4 +65,4 @@ export declare const COSEKEYS: {
65
65
  /** RSA: exponent e (shares numeric label with X) */
66
66
  readonly E: -2;
67
67
  };
68
- //# sourceMappingURL=constants.d.mts.map
68
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/webauthn/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,oBAAY,OAAO;IACjB,KAAK,KAAK;IACV,KAAK,KAAK;IACV,KAAK,MAAM;IACX,KAAK,MAAM;IACX,KAAK,MAAM;IACX,KAAK,MAAM;IACX,KAAK,MAAM;IACX,MAAM,MAAM;IACZ,KAAK,OAAO;IACZ,KAAK,OAAO;IACZ,KAAK,OAAO;IACZ,GAAG,SAAS;CACb;AAED;;;;GAIG;AACH,oBAAY,OAAO;IACjB,GAAG,IAAI;IACP,GAAG,IAAI;IACP,GAAG,IAAI;CACR;AAED;;;;GAIG;AACH,oBAAY,OAAO;IACjB,IAAI,IAAI;IACR,IAAI,IAAI;IACR,IAAI,IAAI;IACR,OAAO,IAAI;IACX,SAAS,IAAI;CACd;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;IACnB,wBAAwB;aACxB,GAAG,EAAE,CAAC;IACN,yBAAyB;aACzB,GAAG,EAAE,CAAC;IAEN,kCAAkC;aAClC,GAAG,EAAE,CAAC,CAAC;IACP,0CAA0C;aAC1C,CAAC,EAAE,CAAC,CAAC;IACL,wBAAwB;aACxB,CAAC,EAAE,CAAC,CAAC;IAEL,qDAAqD;aACrD,CAAC,EAAE,CAAC,CAAC;IACL,oDAAoD;aACpD,CAAC,EAAE,CAAC,CAAC;CACG,CAAC"}
@@ -68,4 +68,4 @@ export const COSEKEYS = {
68
68
  /** RSA: exponent e (shares numeric label with X) */
69
69
  E: -2,
70
70
  };
71
- //# sourceMappingURL=constants.mjs.map
71
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/webauthn/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAN,IAAY,OAaX;AAbD,WAAY,OAAO;IACjB,wCAAU,CAAA;IACV,wCAAU,CAAA;IACV,yCAAW,CAAA;IACX,yCAAW,CAAA;IACX,yCAAW,CAAA;IACX,yCAAW,CAAA;IACX,yCAAW,CAAA;IACX,2CAAY,CAAA;IACZ,0CAAY,CAAA;IACZ,0CAAY,CAAA;IACZ,0CAAY,CAAA;IACZ,wCAAY,CAAA;AACd,CAAC,EAbW,OAAO,KAAP,OAAO,QAalB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,OAIX;AAJD,WAAY,OAAO;IACjB,mCAAO,CAAA;IACP,mCAAO,CAAA;IACP,mCAAO,CAAA;AACT,CAAC,EAJW,OAAO,KAAP,OAAO,QAIlB;AAED;;;;GAIG;AACH,MAAM,CAAN,IAAY,OAMX;AAND,WAAY,OAAO;IACjB,qCAAQ,CAAA;IACR,qCAAQ,CAAA;IACR,qCAAQ,CAAA;IACR,2CAAW,CAAA;IACX,+CAAa,CAAA;AACf,CAAC,EANW,OAAO,KAAP,OAAO,QAMlB;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,wBAAwB;IACxB,GAAG,EAAE,CAAC;IACN,yBAAyB;IACzB,GAAG,EAAE,CAAC;IAEN,kCAAkC;IAClC,GAAG,EAAE,CAAC,CAAC;IACP,0CAA0C;IAC1C,CAAC,EAAE,CAAC,CAAC;IACL,wBAAwB;IACxB,CAAC,EAAE,CAAC,CAAC;IAEL,qDAAqD;IACrD,CAAC,EAAE,CAAC,CAAC;IACL,oDAAoD;IACpD,CAAC,EAAE,CAAC,CAAC;CACG,CAAC","sourcesContent":["/**\n * COSE Algorithms\n *\n * @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms\n */\nexport enum COSEALG {\n ES256 = -7,\n EdDSA = -8,\n ES384 = -35,\n ES512 = -36,\n PS256 = -37,\n PS384 = -38,\n PS512 = -39,\n ES256K = -47,\n RS256 = -257,\n RS384 = -258,\n RS512 = -259,\n RS1 = -65535,\n}\n\n/**\n * COSE Key Types\n *\n * @see https://www.iana.org/assignments/cose/cose.xhtml#key-type\n */\nexport enum COSEKTY {\n OKP = 1,\n EC2 = 2,\n RSA = 3,\n}\n\n/**\n * COSE Curves\n *\n * @see https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves\n */\nexport enum COSECRV {\n P256 = 1,\n P384 = 2,\n P521 = 3,\n ED25519 = 6,\n SECP256K1 = 8,\n}\n\n/**\n * COSE Key common and type-specific parameter labels.\n *\n * EC2 and RSA re-use the same numeric labels (-1, -2, -3) with different\n * semantics, so this is a plain object instead of an enum to avoid\n * duplicate-value violations.\n *\n * @see https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters\n * @see https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters\n */\nexport const COSEKEYS = {\n /** Key Type (common) */\n Kty: 1,\n /** Algorithm (common) */\n Alg: 3,\n\n /** EC2 / OKP: curve identifier */\n Crv: -1,\n /** EC2: x-coordinate / OKP: public key */\n X: -2,\n /** EC2: y-coordinate */\n Y: -3,\n\n /** RSA: modulus n (shares numeric label with Crv) */\n N: -1,\n /** RSA: exponent e (shares numeric label with X) */\n E: -2,\n} as const;\n"]}
@@ -1,4 +1,4 @@
1
- import type { AttestationObject } from "./types.mjs";
1
+ import type { AttestationObject } from './types.js';
2
2
  /**
3
3
  * CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,
4
4
  * and `authData` entries.
@@ -7,4 +7,4 @@ import type { AttestationObject } from "./types.mjs";
7
7
  * @returns Decoded AttestationObject map.
8
8
  */
9
9
  export declare function decodeAttestationObject(attestationObject: Uint8Array): AttestationObject;
10
- //# sourceMappingURL=decode-attestation-object.d.mts.map
10
+ //# sourceMappingURL=decode-attestation-object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-attestation-object.d.ts","sourceRoot":"","sources":["../../src/webauthn/decode-attestation-object.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,UAAU,GAC5B,iBAAiB,CAInB"}
@@ -1,4 +1,4 @@
1
- import { decodePartialCBOR } from "@levischuck/tiny-cbor";
1
+ import { decodePartialCBOR } from '@levischuck/tiny-cbor';
2
2
  /**
3
3
  * CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,
4
4
  * and `authData` entries.
@@ -11,4 +11,4 @@ export function decodeAttestationObject(attestationObject) {
11
11
  const [decoded] = decodePartialCBOR(copy, 0);
12
12
  return decoded;
13
13
  }
14
- //# sourceMappingURL=decode-attestation-object.mjs.map
14
+ //# sourceMappingURL=decode-attestation-object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-attestation-object.js","sourceRoot":"","sources":["../../src/webauthn/decode-attestation-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAI1D;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACrC,iBAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC/C,MAAM,CAAC,OAAO,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAgC,CAAC;IAC5E,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { decodePartialCBOR } from '@levischuck/tiny-cbor';\n\nimport type { AttestationObject } from './types.js';\n\n/**\n * CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,\n * and `authData` entries.\n *\n * @param attestationObject - Raw attestation object bytes.\n * @returns Decoded AttestationObject map.\n */\nexport function decodeAttestationObject(\n attestationObject: Uint8Array,\n): AttestationObject {\n const copy = new Uint8Array(attestationObject);\n const [decoded] = decodePartialCBOR(copy, 0) as [AttestationObject, number];\n return decoded;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { ClientDataJSON } from "./types.cjs";
1
+ import type { ClientDataJSON } from './types.js';
2
2
  /**
3
3
  * Decode an authenticator's base64url-encoded clientDataJSON to JSON.
4
4
  *
@@ -6,4 +6,4 @@ import type { ClientDataJSON } from "./types.cjs";
6
6
  * @returns Parsed ClientDataJSON object.
7
7
  */
8
8
  export declare function decodeClientDataJSON(data: string): ClientDataJSON;
9
- //# sourceMappingURL=decode-client-data-json.d.cts.map
9
+ //# sourceMappingURL=decode-client-data-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-client-data-json.d.ts","sourceRoot":"","sources":["../../src/webauthn/decode-client-data-json.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAIjE"}
@@ -1,4 +1,4 @@
1
- import { base64URLToBytes } from "../utils/encoding.mjs";
1
+ import { base64URLToBytes } from '../utils/encoding.js';
2
2
  /**
3
3
  * Decode an authenticator's base64url-encoded clientDataJSON to JSON.
4
4
  *
@@ -10,4 +10,4 @@ export function decodeClientDataJSON(data) {
10
10
  const text = new TextDecoder().decode(bytes);
11
11
  return JSON.parse(text);
12
12
  }
13
- //# sourceMappingURL=decode-client-data-json.mjs.map
13
+ //# sourceMappingURL=decode-client-data-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-client-data-json.js","sourceRoot":"","sources":["../../src/webauthn/decode-client-data-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC;AAC5C,CAAC","sourcesContent":["import { base64URLToBytes } from '../utils/encoding.js';\nimport type { ClientDataJSON } from './types.js';\n\n/**\n * Decode an authenticator's base64url-encoded clientDataJSON to JSON.\n *\n * @param data - Base64url-encoded clientDataJSON string.\n * @returns Parsed ClientDataJSON object.\n */\nexport function decodeClientDataJSON(data: string): ClientDataJSON {\n const bytes = base64URLToBytes(data);\n const text = new TextDecoder().decode(bytes);\n return JSON.parse(text) as ClientDataJSON;\n}\n"]}
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).
6
6
  * @param expectedRPIDs - One or more RP ID strings to check against.
7
- * @returns The matching RP ID string.
7
+ * @returns A promise for the matching RP ID string.
8
8
  * @throws If no expected RP ID matches.
9
9
  */
10
- export declare function matchExpectedRPID(rpIdHash: Uint8Array, expectedRPIDs: string[]): string;
11
- //# sourceMappingURL=match-expected-rp-id.d.cts.map
10
+ export declare function matchExpectedRPID(rpIdHash: Uint8Array, expectedRPIDs: string[]): Promise<string>;
11
+ //# sourceMappingURL=match-expected-rp-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-expected-rp-id.d.ts","sourceRoot":"","sources":["../../src/webauthn/match-expected-rp-id.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,UAAU,EACpB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAQjB"}
@@ -1,22 +1,21 @@
1
- import { areUint8ArraysEqual } from "@metamask/utils";
2
- import { sha256 } from "@noble/hashes/sha2";
3
- import { bytesToHex } from "../utils/encoding.mjs";
1
+ import { areUint8ArraysEqual, sha256 } from '@metamask/utils';
2
+ import { bytesToHex } from '../utils/encoding.js';
4
3
  /**
5
4
  * Verify that an authenticator data rpIdHash matches one of the expected
6
5
  * RP IDs by SHA-256 hashing each candidate and comparing.
7
6
  *
8
7
  * @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).
9
8
  * @param expectedRPIDs - One or more RP ID strings to check against.
10
- * @returns The matching RP ID string.
9
+ * @returns A promise for the matching RP ID string.
11
10
  * @throws If no expected RP ID matches.
12
11
  */
13
- export function matchExpectedRPID(rpIdHash, expectedRPIDs) {
12
+ export async function matchExpectedRPID(rpIdHash, expectedRPIDs) {
14
13
  for (const rpID of expectedRPIDs) {
15
- const expectedHash = sha256(new TextEncoder().encode(rpID));
14
+ const expectedHash = await sha256(new TextEncoder().encode(rpID));
16
15
  if (areUint8ArraysEqual(rpIdHash, expectedHash)) {
17
16
  return rpID;
18
17
  }
19
18
  }
20
19
  throw new Error(`Unexpected RP ID hash: received ${bytesToHex(rpIdHash)}`);
21
20
  }
22
- //# sourceMappingURL=match-expected-rp-id.mjs.map
21
+ //# sourceMappingURL=match-expected-rp-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-expected-rp-id.js","sourceRoot":"","sources":["../../src/webauthn/match-expected-rp-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAoB,EACpB,aAAuB;IAEvB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAClE,IAAI,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,mCAAmC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { areUint8ArraysEqual, sha256 } from '@metamask/utils';\n\nimport { bytesToHex } from '../utils/encoding.js';\n\n/**\n * Verify that an authenticator data rpIdHash matches one of the expected\n * RP IDs by SHA-256 hashing each candidate and comparing.\n *\n * @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).\n * @param expectedRPIDs - One or more RP ID strings to check against.\n * @returns A promise for the matching RP ID string.\n * @throws If no expected RP ID matches.\n */\nexport async function matchExpectedRPID(\n rpIdHash: Uint8Array,\n expectedRPIDs: string[],\n): Promise<string> {\n for (const rpID of expectedRPIDs) {\n const expectedHash = await sha256(new TextEncoder().encode(rpID));\n if (areUint8ArraysEqual(rpIdHash, expectedHash)) {\n return rpID;\n }\n }\n throw new Error(`Unexpected RP ID hash: received ${bytesToHex(rpIdHash)}`);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { ParsedAuthenticatorData } from "./types.cjs";
1
+ import type { ParsedAuthenticatorData } from './types.js';
2
2
  /**
3
3
  * Parse an authenticator data buffer per §6.1 of the WebAuthn spec.
4
4
  *
@@ -7,4 +7,4 @@ import type { ParsedAuthenticatorData } from "./types.cjs";
7
7
  * optional attested credential data.
8
8
  */
9
9
  export declare function parseAuthenticatorData(authData: Uint8Array): ParsedAuthenticatorData;
10
- //# sourceMappingURL=parse-authenticator-data.d.cts.map
10
+ //# sourceMappingURL=parse-authenticator-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-authenticator-data.d.ts","sourceRoot":"","sources":["../../src/webauthn/parse-authenticator-data.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EAExB,MAAM,YAAY,CAAC;AAIpB;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,UAAU,GACnB,uBAAuB,CAkFzB"}
@@ -1,4 +1,4 @@
1
- import { decodePartialCBOR } from "@levischuck/tiny-cbor";
1
+ import { decodePartialCBOR } from '@levischuck/tiny-cbor';
2
2
  /* eslint-disable no-bitwise */
3
3
  /**
4
4
  * Parse an authenticator data buffer per §6.1 of the WebAuthn spec.
@@ -62,4 +62,4 @@ export function parseAuthenticatorData(authData) {
62
62
  return result;
63
63
  }
64
64
  /* eslint-enable no-bitwise */
65
- //# sourceMappingURL=parse-authenticator-data.mjs.map
65
+ //# sourceMappingURL=parse-authenticator-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-authenticator-data.js","sourceRoot":"","sources":["../../src/webauthn/parse-authenticator-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAO1D,+BAA+B;AAE/B;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAoB;IAEpB,IAAI,QAAQ,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,wBAAwB,QAAQ,CAAC,UAAU,8BAA8B,CAC1E,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,CAAC,CAAC;IACvD,OAAO,IAAI,EAAE,CAAC;IAEd,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,KAAK,GAA2B;QACpC,EAAE,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,EAAE,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,EAAE,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,EAAE,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,EAAE,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,EAAE,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,SAAS;KACV,CAAC;IACF,OAAO,IAAI,CAAC,CAAC;IAEb,MAAM,WAAW,GAAG,IAAI,QAAQ,CAC9B,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,UAAU,GAAG,OAAO,EAC7B,CAAC,CACF,CAAC;IACF,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,CAAC;IAEb,MAAM,MAAM,GAA4B;QACtC,QAAQ;QACR,KAAK;QACL,OAAO;KACR,CAAC;IAEF,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,EAAE,CAAC;QAEd,MAAM,aAAa,GAAG,IAAI,QAAQ,CAChC,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,UAAU,GAAG,OAAO,EAC7B,CAAC,CACF,CAAC;QACF,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,CAAC;QAEb,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC;QAClE,OAAO,IAAI,SAAS,CAAC;QAErB,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG,iBAAiB,CACtC,IAAI,UAAU,CAAC,WAAW,CAAC,EAC3B,CAAC,CACmB,CAAC;QACvB,MAAM,mBAAmB,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC,CAAC;QAC1E,OAAO,IAAI,UAAU,CAAC;QAEtB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;QACnC,MAAM,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;IACnD,CAAC;IAED,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,iBAAiB,CAC3C,IAAI,UAAU,CAAC,SAAS,CAAC,EACzB,CAAC,CACgC,CAAC;QACpC,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC;QAChC,MAAM,CAAC,oBAAoB,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC3D,OAAO,IAAI,QAAQ,CAAC;IACtB,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,GAAG,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8BAA8B","sourcesContent":["import { decodePartialCBOR } from '@levischuck/tiny-cbor';\n\nimport type {\n ParsedAuthenticatorData,\n AuthenticatorDataFlags,\n} from './types.js';\n\n/* eslint-disable no-bitwise */\n\n/**\n * Parse an authenticator data buffer per §6.1 of the WebAuthn spec.\n *\n * @param authData - Raw authenticator data bytes.\n * @returns Parsed authenticator data with flags, rpIdHash, counter, and\n * optional attested credential data.\n */\nexport function parseAuthenticatorData(\n authData: Uint8Array,\n): ParsedAuthenticatorData {\n if (authData.byteLength < 37) {\n throw new Error(\n `authenticatorData is ${authData.byteLength} bytes, expected at least 37`,\n );\n }\n\n let pointer = 0;\n\n const rpIdHash = authData.slice(pointer, pointer + 32);\n pointer += 32;\n\n const flagsByte = authData[pointer];\n const flags: AuthenticatorDataFlags = {\n up: Boolean(flagsByte & (1 << 0)),\n uv: Boolean(flagsByte & (1 << 2)),\n be: Boolean(flagsByte & (1 << 3)),\n bs: Boolean(flagsByte & (1 << 4)),\n at: Boolean(flagsByte & (1 << 6)),\n ed: Boolean(flagsByte & (1 << 7)),\n flagsByte,\n };\n pointer += 1;\n\n const counterView = new DataView(\n authData.buffer,\n authData.byteOffset + pointer,\n 4,\n );\n const counter = counterView.getUint32(0, false);\n pointer += 4;\n\n const result: ParsedAuthenticatorData = {\n rpIdHash,\n flags,\n counter,\n };\n\n if (flags.at) {\n const aaguid = authData.slice(pointer, pointer + 16);\n pointer += 16;\n\n const credIDLenView = new DataView(\n authData.buffer,\n authData.byteOffset + pointer,\n 2,\n );\n const credIDLen = credIDLenView.getUint16(0, false);\n pointer += 2;\n\n const credentialID = authData.slice(pointer, pointer + credIDLen);\n pointer += credIDLen;\n\n const pubKeyBytes = authData.slice(pointer);\n const [, nextOffset] = decodePartialCBOR(\n new Uint8Array(pubKeyBytes),\n 0,\n ) as [unknown, number];\n const credentialPublicKey = authData.slice(pointer, pointer + nextOffset);\n pointer += nextOffset;\n\n result.aaguid = aaguid;\n result.credentialID = credentialID;\n result.credentialPublicKey = credentialPublicKey;\n }\n\n if (flags.ed) {\n const remaining = authData.slice(pointer);\n const [decoded, consumed] = decodePartialCBOR(\n new Uint8Array(remaining),\n 0,\n ) as [Map<string, unknown>, number];\n result.extensionsData = decoded;\n result.extensionsDataBuffer = remaining.slice(0, consumed);\n pointer += consumed;\n }\n\n if (authData.byteLength > pointer) {\n throw new Error('Leftover bytes detected while parsing authenticator data');\n }\n\n return result;\n}\n\n/* eslint-enable no-bitwise */\n"]}
@@ -1,4 +1,4 @@
1
- import type { AuthenticatorTransportFuture, Base64URLString as Base64URL } from "../types.mjs";
1
+ import type { AuthenticatorTransportFuture, Base64URLString as Base64URL } from '../types.js';
2
2
  export type PublicKeyCredentialDescriptorJSON = {
3
3
  id: Base64URL;
4
4
  type: 'public-key';
@@ -110,4 +110,4 @@ export type ParsedAuthenticatorData = {
110
110
  extensionsData?: Map<string, unknown>;
111
111
  extensionsDataBuffer?: Uint8Array;
112
112
  };
113
- //# sourceMappingURL=types.d.mts.map
113
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/webauthn/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webauthn/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n AuthenticatorTransportFuture,\n Base64URLString as Base64URL,\n} from '../types.js';\n\nexport type PublicKeyCredentialDescriptorJSON = {\n id: Base64URL;\n type: 'public-key';\n transports?: AuthenticatorTransportFuture[];\n};\n\nexport type PublicKeyCredentialHint =\n | 'hybrid'\n | 'security-key'\n | 'client-device';\n\nexport type PasskeyRegistrationOptions = {\n rp: { name: string; id?: string };\n user: {\n id: Base64URL;\n name: string;\n displayName: string;\n };\n challenge: Base64URL;\n pubKeyCredParams: { alg: number; type: 'public-key' }[];\n timeout?: number;\n excludeCredentials?: PublicKeyCredentialDescriptorJSON[];\n authenticatorSelection?: {\n authenticatorAttachment?: 'cross-platform' | 'platform';\n residentKey?: 'discouraged' | 'preferred' | 'required';\n requireResidentKey?: boolean;\n userVerification?: 'discouraged' | 'preferred' | 'required';\n };\n hints?: PublicKeyCredentialHint[];\n attestation?: 'direct' | 'enterprise' | 'indirect' | 'none';\n extensions?: Record<string, unknown>;\n};\n\nexport type PasskeyRegistrationResponse = {\n id: Base64URL;\n rawId: Base64URL;\n type: 'public-key';\n response: {\n clientDataJSON: Base64URL;\n attestationObject: Base64URL;\n transports?: string[];\n publicKeyAlgorithm?: number;\n publicKey?: Base64URL;\n authenticatorData?: Base64URL;\n };\n authenticatorAttachment?: 'cross-platform' | 'platform';\n clientExtensionResults: Record<string, unknown>;\n};\n\nexport type PasskeyAuthenticationOptions = {\n challenge: Base64URL;\n timeout?: number;\n rpId?: string;\n allowCredentials?: PublicKeyCredentialDescriptorJSON[];\n userVerification?: 'discouraged' | 'preferred' | 'required';\n hints?: PublicKeyCredentialHint[];\n extensions?: Record<string, unknown>;\n};\n\nexport type PasskeyAuthenticationResponse = {\n id: Base64URL;\n rawId: Base64URL;\n type: 'public-key';\n response: {\n clientDataJSON: Base64URL;\n authenticatorData: Base64URL;\n signature: Base64URL;\n userHandle?: Base64URL;\n };\n authenticatorAttachment?: 'cross-platform' | 'platform';\n clientExtensionResults: Record<string, unknown>;\n};\n\nexport type ClientDataJSON = {\n type: string;\n challenge: string;\n origin: string;\n crossOrigin?: boolean;\n tokenBinding?: {\n id?: string;\n status: 'present' | 'supported' | 'not-supported';\n };\n};\n\nexport type AttestationFormat =\n | 'fido-u2f'\n | 'packed'\n | 'android-safetynet'\n | 'android-key'\n | 'tpm'\n | 'apple'\n | 'none';\n\nexport type AttestationObject = {\n get(key: 'fmt'): AttestationFormat;\n get(key: 'attStmt'): AttestationStatement;\n get(key: 'authData'): Uint8Array;\n};\n\nexport type AttestationStatement = {\n get(key: 'sig'): Uint8Array | undefined;\n get(key: 'x5c'): Uint8Array[] | undefined;\n get(key: 'alg'): number | undefined;\n readonly size: number;\n};\n\nexport type AuthenticatorDataFlags = {\n up: boolean;\n uv: boolean;\n be: boolean;\n bs: boolean;\n at: boolean;\n ed: boolean;\n flagsByte: number;\n};\n\nexport type ParsedAuthenticatorData = {\n rpIdHash: Uint8Array;\n flags: AuthenticatorDataFlags;\n counter: number;\n aaguid?: Uint8Array;\n credentialID?: Uint8Array;\n credentialPublicKey?: Uint8Array;\n extensionsData?: Map<string, unknown>;\n extensionsDataBuffer?: Uint8Array;\n};\n"]}
@@ -1,5 +1,5 @@
1
- import type { AuthenticatorTransportFuture } from "../types.cjs";
2
- import type { PasskeyAuthenticationResponse } from "./types.cjs";
1
+ import type { AuthenticatorTransportFuture } from '../types.js';
2
+ import type { PasskeyAuthenticationResponse } from './types.js';
3
3
  export type VerifiedAuthenticationResponse = {
4
4
  verified: false;
5
5
  authenticationInfo?: never;
@@ -61,4 +61,4 @@ export declare function verifyAuthenticationResponse(opts: {
61
61
  };
62
62
  requireUserVerification?: boolean;
63
63
  }): Promise<VerifiedAuthenticationResponse>;
64
- //# sourceMappingURL=verify-authentication-response.d.cts.map
64
+ //# sourceMappingURL=verify-authentication-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-authentication-response.d.ts","sourceRoot":"","sources":["../../src/webauthn/verify-authentication-response.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAMhE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAGhE,MAAM,MAAM,8BAA8B,GACtC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/C;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,kBAAkB,EAAE;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,OAAO,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,uFAAuF;QACvF,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH,CAAC;AAEN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,4BAA4B,CAAC,IAAI,EAAE;IACvD,QAAQ,EAAE,6BAA6B,CAAC;IACxC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE;QACV,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,UAAU,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;KAC7C,CAAC;IACF,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAiJ1C"}
@@ -1,11 +1,10 @@
1
- import { decodePartialCBOR } from "@levischuck/tiny-cbor";
2
- import { concatBytes } from "@metamask/utils";
3
- import { sha256 } from "@noble/hashes/sha2";
4
- import { base64URLToBytes } from "../utils/encoding.mjs";
5
- import { decodeClientDataJSON } from "./decode-client-data-json.mjs";
6
- import { matchExpectedRPID } from "./match-expected-rp-id.mjs";
7
- import { parseAuthenticatorData } from "./parse-authenticator-data.mjs";
8
- import { verifySignature } from "./verify-signature.mjs";
1
+ import { decodePartialCBOR } from '@levischuck/tiny-cbor';
2
+ import { concatBytes, sha256 } from '@metamask/utils';
3
+ import { base64URLToBytes } from '../utils/encoding.js';
4
+ import { decodeClientDataJSON } from './decode-client-data-json.js';
5
+ import { matchExpectedRPID } from './match-expected-rp-id.js';
6
+ import { parseAuthenticatorData } from './parse-authenticator-data.js';
7
+ import { verifySignature } from './verify-signature.js';
9
8
  /**
10
9
  * Verifies a WebAuthn authentication (assertion) response per
11
10
  * W3C WebAuthn Level 3 §7.2.
@@ -90,7 +89,10 @@ export async function verifyAuthenticationResponse(opts) {
90
89
  const authDataBuffer = base64URLToBytes(assertionResponse.authenticatorData);
91
90
  const parsedAuthData = parseAuthenticatorData(authDataBuffer);
92
91
  const { rpIdHash, flags, counter } = parsedAuthData;
93
- const matchedRPID = expectedRPIDs.length > 0 ? matchExpectedRPID(rpIdHash, expectedRPIDs) : '';
92
+ let matchedRPID = '';
93
+ if (expectedRPIDs.length > 0) {
94
+ matchedRPID = await matchExpectedRPID(rpIdHash, expectedRPIDs);
95
+ }
94
96
  // WebAuthn only requires the user presence flag be true
95
97
  if (!flags.up) {
96
98
  throw new Error('User not present during authentication');
@@ -99,7 +101,7 @@ export async function verifyAuthenticationResponse(opts) {
99
101
  if (requireUserVerification && !flags.uv) {
100
102
  throw new Error('User verification required, but user could not be verified');
101
103
  }
102
- const clientDataHash = sha256(base64URLToBytes(assertionResponse.clientDataJSON));
104
+ const clientDataHash = await sha256(base64URLToBytes(assertionResponse.clientDataJSON));
103
105
  const signatureBase = concatBytes([authDataBuffer, clientDataHash]);
104
106
  const signature = base64URLToBytes(assertionResponse.signature);
105
107
  const cosePublicKey = decodePartialCBOR(new Uint8Array(credential.publicKey), 0)[0];
@@ -126,4 +128,4 @@ export async function verifyAuthenticationResponse(opts) {
126
128
  },
127
129
  };
128
130
  }
129
- //# sourceMappingURL=verify-authentication-response.mjs.map
131
+ //# sourceMappingURL=verify-authentication-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-authentication-response.js","sourceRoot":"","sources":["../../src/webauthn/verify-authentication-response.ts"],"names":[],"mappings":"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","sourcesContent":["import { decodePartialCBOR } from '@levischuck/tiny-cbor';\nimport { concatBytes, sha256 } from '@metamask/utils';\n\nimport type { AuthenticatorTransportFuture } from '../types.js';\nimport { base64URLToBytes } from '../utils/encoding.js';\nimport { decodeClientDataJSON } from './decode-client-data-json.js';\nimport { matchExpectedRPID } from './match-expected-rp-id.js';\nimport { parseAuthenticatorData } from './parse-authenticator-data.js';\nimport type { ParsedAuthenticatorData } from './types.js';\nimport type { PasskeyAuthenticationResponse } from './types.js';\nimport { verifySignature } from './verify-signature.js';\n\nexport type VerifiedAuthenticationResponse =\n | { verified: false; authenticationInfo?: never }\n | {\n verified: true;\n authenticationInfo: {\n credentialId: string;\n newCounter: number;\n userVerified: boolean;\n origin: string;\n /** Matched RP ID, or `\"\"` when `expectedRPIDs` is empty (RP ID hash check skipped). */\n rpID: string;\n };\n };\n\n/**\n * Verifies a WebAuthn authentication (assertion) response per\n * W3C WebAuthn Level 3 §7.2.\n *\n * Performs the following checks in order:\n * 1. Credential ID presence, base64url consistency, and type.\n * 2. `clientDataJSON` -- type is `\"webauthn.get\"`, challenge and origin\n * match.\n * 3. `authenticatorData` -- RP ID hash matches, user-presence flag is\n * set, and optional user-verification flag is checked.\n * 4. Signature verification -- `signature` is verified over\n * `authData || SHA-256(clientDataJSON)` using the stored credential\n * public key (COSE-encoded).\n * 5. Counter monotonicity -- if either the stored or returned counter\n * is non-zero, the new counter must exceed the stored value.\n *\n * @param opts - Verification options.\n * @param opts.response - The `PublicKeyCredential` result from\n * `navigator.credentials.get()`, serialized as JSON.\n * @param opts.expectedChallenge - The base64url challenge that was issued\n * for this ceremony.\n * @param opts.expectedOrigin - One or more acceptable origins.\n * @param opts.expectedRPIDs - Relying Party ID strings to match against `rpIdHash`.\n * @param opts.credential - The stored credential record to verify against.\n * @param opts.credential.id - The credential ID (base64url).\n * @param opts.credential.publicKey - The COSE-encoded public key bytes\n * persisted during registration.\n * @param opts.credential.counter - The last known signature counter value.\n * @param opts.credential.transports - Optional authenticator transports.\n * @param opts.requireUserVerification - When `true`, verification fails\n * if the UV flag is not set. Defaults to `false`.\n * @returns Verification result containing `verified` status and parsed\n * authentication info (new counter, origin, RP ID).\n */\nexport async function verifyAuthenticationResponse(opts: {\n response: PasskeyAuthenticationResponse;\n expectedChallenge: string;\n expectedOrigin: string | string[];\n expectedRPIDs: string[];\n credential: {\n id: string;\n publicKey: Uint8Array;\n counter: number;\n transports?: AuthenticatorTransportFuture[];\n };\n requireUserVerification?: boolean;\n}): Promise<VerifiedAuthenticationResponse> {\n const {\n response,\n expectedChallenge,\n expectedOrigin,\n expectedRPIDs,\n credential,\n requireUserVerification = false,\n } = opts;\n\n const {\n id,\n rawId,\n type: credentialType,\n response: assertionResponse,\n } = response;\n\n // Ensure credential specified an ID\n if (!id) {\n throw new Error('Missing credential ID');\n }\n\n // Ensure ID is base64url-encoded\n if (id !== rawId) {\n throw new Error('Credential ID was not base64url-encoded');\n }\n\n // Make sure credential type is public-key\n if (credentialType !== 'public-key') {\n throw new Error(\n `Unexpected credential type ${String(credentialType)}, expected \"public-key\"`,\n );\n }\n\n if (typeof assertionResponse?.clientDataJSON !== 'string') {\n throw new Error('Credential response clientDataJSON was not a string');\n }\n\n const clientDataJSON = decodeClientDataJSON(assertionResponse.clientDataJSON);\n const { type, challenge, origin, tokenBinding } = clientDataJSON;\n\n // Make sure we're handling an authentication\n if (type !== 'webauthn.get') {\n throw new Error(`Unexpected authentication response type: ${type}`);\n }\n\n // Ensure the device provided the challenge we gave it\n if (challenge !== expectedChallenge) {\n throw new Error(\n `Unexpected authentication response challenge \"${challenge}\", expected \"${expectedChallenge}\"`,\n );\n }\n\n // Check that the origin is our site\n const expectedOrigins = Array.isArray(expectedOrigin)\n ? expectedOrigin\n : [expectedOrigin];\n if (!expectedOrigins.includes(origin)) {\n throw new Error(\n `Unexpected authentication response origin \"${origin}\", expected one of: ${expectedOrigins.join(', ')}`,\n );\n }\n\n if (\n assertionResponse.userHandle &&\n typeof assertionResponse.userHandle !== 'string'\n ) {\n throw new Error('Credential response userHandle was not a string');\n }\n\n if (tokenBinding) {\n if (typeof tokenBinding !== 'object') {\n throw new Error('ClientDataJSON tokenBinding was not an object');\n }\n\n if (\n !['present', 'supported', 'not-supported'].includes(tokenBinding.status)\n ) {\n throw new Error(`Unexpected tokenBinding status ${tokenBinding.status}`);\n }\n }\n\n const authDataBuffer = base64URLToBytes(assertionResponse.authenticatorData);\n const parsedAuthData: ParsedAuthenticatorData =\n parseAuthenticatorData(authDataBuffer);\n const { rpIdHash, flags, counter } = parsedAuthData;\n\n let matchedRPID = '';\n if (expectedRPIDs.length > 0) {\n matchedRPID = await matchExpectedRPID(rpIdHash, expectedRPIDs);\n }\n\n // WebAuthn only requires the user presence flag be true\n if (!flags.up) {\n throw new Error('User not present during authentication');\n }\n\n // Enforce user verification if required\n if (requireUserVerification && !flags.uv) {\n throw new Error(\n 'User verification required, but user could not be verified',\n );\n }\n\n const clientDataHash = await sha256(\n base64URLToBytes(assertionResponse.clientDataJSON),\n );\n const signatureBase = concatBytes([authDataBuffer, clientDataHash]);\n\n const signature = base64URLToBytes(assertionResponse.signature);\n\n const cosePublicKey = decodePartialCBOR(\n new Uint8Array(credential.publicKey),\n 0,\n )[0] as Map<number, number | Uint8Array>;\n\n const verified = await verifySignature({\n cosePublicKey,\n signature,\n data: signatureBase,\n });\n\n if (!verified) {\n return { verified: false };\n }\n\n if (\n (counter > 0 || credential.counter > 0) &&\n counter <= credential.counter\n ) {\n throw new Error(\n `Response counter value ${counter} must be greater than stored counter ${credential.counter}`,\n );\n }\n\n return {\n verified: true,\n authenticationInfo: {\n credentialId: credential.id,\n newCounter: counter,\n userVerified: flags.uv,\n origin: clientDataJSON.origin,\n rpID: matchedRPID,\n },\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { AuthenticatorTransportFuture } from "../types.mjs";
2
- import type { PasskeyRegistrationResponse } from "./types.mjs";
1
+ import type { AuthenticatorTransportFuture } from '../types.js';
2
+ import type { PasskeyRegistrationResponse } from './types.js';
3
3
  export type VerifiedRegistrationResponse = {
4
4
  verified: false;
5
5
  registrationInfo?: never;
@@ -78,4 +78,4 @@ export declare function verifyRegistrationResponse(opts: {
78
78
  * @throws If the attestation object or its authenticator data is malformed.
79
79
  */
80
80
  export declare function getAAGUIDFromRegistrationResponse(registrationResponse: PasskeyRegistrationResponse): string | undefined;
81
- //# sourceMappingURL=verify-registration-response.d.mts.map
81
+ //# sourceMappingURL=verify-registration-response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-registration-response.d.ts","sourceRoot":"","sources":["../../src/webauthn/verify-registration-response.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAWhE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAG9D,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,gBAAgB,CAAC,EAAE,KAAK,CAAA;CAAE,GAC7C;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,gBAAgB,EAAE;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,UAAU,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;QAC5C,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,OAAO,CAAC;KACvB,CAAC;CACH,CAAC;AAEN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,QAAQ,EAAE,2BAA2B,CAAC;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAkLxC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iCAAiC,CAC/C,oBAAoB,EAAE,2BAA2B,GAChD,MAAM,GAAG,SAAS,CAMpB"}
@@ -1,13 +1,12 @@
1
- import { decodePartialCBOR } from "@levischuck/tiny-cbor";
2
- import { concatBytes } from "@metamask/utils";
3
- import { sha256 } from "@noble/hashes/sha2";
4
- import { base64URLToBytes, bytesToBase64URL, bytesToHex } from "../utils/encoding.mjs";
5
- import { COSEALG, COSEKEYS } from "./constants.mjs";
6
- import { decodeAttestationObject } from "./decode-attestation-object.mjs";
7
- import { decodeClientDataJSON } from "./decode-client-data-json.mjs";
8
- import { matchExpectedRPID } from "./match-expected-rp-id.mjs";
9
- import { parseAuthenticatorData } from "./parse-authenticator-data.mjs";
10
- import { verifySignature } from "./verify-signature.mjs";
1
+ import { decodePartialCBOR } from '@levischuck/tiny-cbor';
2
+ import { concatBytes, sha256 } from '@metamask/utils';
3
+ import { base64URLToBytes, bytesToBase64URL, bytesToHex, } from '../utils/encoding.js';
4
+ import { COSEALG, COSEKEYS } from './constants.js';
5
+ import { decodeAttestationObject } from './decode-attestation-object.js';
6
+ import { decodeClientDataJSON } from './decode-client-data-json.js';
7
+ import { matchExpectedRPID } from './match-expected-rp-id.js';
8
+ import { parseAuthenticatorData } from './parse-authenticator-data.js';
9
+ import { verifySignature } from './verify-signature.js';
11
10
  /**
12
11
  * Verifies a WebAuthn registration (attestation) response per
13
12
  * W3C WebAuthn Level 3 §7.1.
@@ -90,7 +89,7 @@ export async function verifyRegistrationResponse(opts) {
90
89
  const parsedAuthData = parseAuthenticatorData(authData);
91
90
  const { rpIdHash, flags, counter, credentialID, credentialPublicKey, aaguid, } = parsedAuthData;
92
91
  if (expectedRPIDs.length > 0) {
93
- matchExpectedRPID(rpIdHash, expectedRPIDs);
92
+ await matchExpectedRPID(rpIdHash, expectedRPIDs);
94
93
  }
95
94
  // Make sure someone was physically present
96
95
  if (!flags.up) {
@@ -226,7 +225,7 @@ async function verifyPackedAttestation(attStmt, authData, clientDataJSONB64url,
226
225
  if (attStmtAlg !== credAlg) {
227
226
  throw new Error(`Packed attestation alg ${attStmtAlg} does not match credential alg ${credAlg}`);
228
227
  }
229
- const clientDataHash = sha256(base64URLToBytes(clientDataJSONB64url));
228
+ const clientDataHash = await sha256(base64URLToBytes(clientDataJSONB64url));
230
229
  const signatureBase = concatBytes([authData, clientDataHash]);
231
230
  return verifySignature({
232
231
  cosePublicKey,
@@ -234,4 +233,4 @@ async function verifyPackedAttestation(attStmt, authData, clientDataJSONB64url,
234
233
  data: signatureBase,
235
234
  });
236
235
  }
237
- //# sourceMappingURL=verify-registration-response.mjs.map
236
+ //# sourceMappingURL=verify-registration-response.js.map