@metamask-previews/passkey-controller 0.0.0-preview-4c0846313
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.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +155 -0
- package/dist/PasskeyController.cjs +448 -0
- package/dist/PasskeyController.cjs.map +1 -0
- package/dist/PasskeyController.d.cts +168 -0
- package/dist/PasskeyController.d.cts.map +1 -0
- package/dist/PasskeyController.d.mts +168 -0
- package/dist/PasskeyController.d.mts.map +1 -0
- package/dist/PasskeyController.mjs +443 -0
- package/dist/PasskeyController.mjs.map +1 -0
- package/dist/ceremony-manager.cjs +134 -0
- package/dist/ceremony-manager.cjs.map +1 -0
- package/dist/ceremony-manager.d.cts +71 -0
- package/dist/ceremony-manager.d.cts.map +1 -0
- package/dist/ceremony-manager.d.mts +71 -0
- package/dist/ceremony-manager.d.mts.map +1 -0
- package/dist/ceremony-manager.mjs +130 -0
- package/dist/ceremony-manager.mjs.map +1 -0
- package/dist/constants.cjs +33 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +30 -0
- package/dist/constants.d.cts.map +1 -0
- package/dist/constants.d.mts +30 -0
- package/dist/constants.d.mts.map +1 -0
- package/dist/constants.mjs +30 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/errors.cjs +57 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +34 -0
- package/dist/errors.d.cts.map +1 -0
- package/dist/errors.d.mts +34 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +53 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +9 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +1 -0
- package/dist/key-derivation.cjs +76 -0
- package/dist/key-derivation.cjs.map +1 -0
- package/dist/key-derivation.d.cts +43 -0
- package/dist/key-derivation.d.cts.map +1 -0
- package/dist/key-derivation.d.mts +43 -0
- package/dist/key-derivation.d.mts.map +1 -0
- package/dist/key-derivation.mjs +71 -0
- package/dist/key-derivation.mjs.map +1 -0
- package/dist/logger.cjs +9 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +5 -0
- package/dist/logger.d.cts.map +1 -0
- package/dist/logger.d.mts +5 -0
- package/dist/logger.d.mts.map +1 -0
- package/dist/logger.mjs +6 -0
- package/dist/logger.mjs.map +1 -0
- package/dist/types.cjs +3 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +92 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +92 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/dist/utils/crypto.cjs +55 -0
- package/dist/utils/crypto.cjs.map +1 -0
- package/dist/utils/crypto.d.cts +30 -0
- package/dist/utils/crypto.d.cts.map +1 -0
- package/dist/utils/crypto.d.mts +30 -0
- package/dist/utils/crypto.d.mts.map +1 -0
- package/dist/utils/crypto.mjs +49 -0
- package/dist/utils/crypto.mjs.map +1 -0
- package/dist/utils/encoding.cjs +42 -0
- package/dist/utils/encoding.cjs.map +1 -0
- package/dist/utils/encoding.d.cts +22 -0
- package/dist/utils/encoding.d.cts.map +1 -0
- package/dist/utils/encoding.d.mts +22 -0
- package/dist/utils/encoding.d.mts.map +1 -0
- package/dist/utils/encoding.mjs +36 -0
- package/dist/utils/encoding.mjs.map +1 -0
- package/dist/webauthn/constants.cjs +74 -0
- package/dist/webauthn/constants.cjs.map +1 -0
- package/dist/webauthn/constants.d.cts +68 -0
- package/dist/webauthn/constants.d.cts.map +1 -0
- package/dist/webauthn/constants.d.mts +68 -0
- package/dist/webauthn/constants.d.mts.map +1 -0
- package/dist/webauthn/constants.mjs +71 -0
- package/dist/webauthn/constants.mjs.map +1 -0
- package/dist/webauthn/decode-attestation-object.cjs +18 -0
- package/dist/webauthn/decode-attestation-object.cjs.map +1 -0
- package/dist/webauthn/decode-attestation-object.d.cts +10 -0
- package/dist/webauthn/decode-attestation-object.d.cts.map +1 -0
- package/dist/webauthn/decode-attestation-object.d.mts +10 -0
- package/dist/webauthn/decode-attestation-object.d.mts.map +1 -0
- package/dist/webauthn/decode-attestation-object.mjs +14 -0
- package/dist/webauthn/decode-attestation-object.mjs.map +1 -0
- package/dist/webauthn/decode-client-data-json.cjs +17 -0
- package/dist/webauthn/decode-client-data-json.cjs.map +1 -0
- package/dist/webauthn/decode-client-data-json.d.cts +9 -0
- package/dist/webauthn/decode-client-data-json.d.cts.map +1 -0
- package/dist/webauthn/decode-client-data-json.d.mts +9 -0
- package/dist/webauthn/decode-client-data-json.d.mts.map +1 -0
- package/dist/webauthn/decode-client-data-json.mjs +13 -0
- package/dist/webauthn/decode-client-data-json.mjs.map +1 -0
- package/dist/webauthn/match-expected-rp-id.cjs +43 -0
- package/dist/webauthn/match-expected-rp-id.cjs.map +1 -0
- package/dist/webauthn/match-expected-rp-id.d.cts +11 -0
- package/dist/webauthn/match-expected-rp-id.d.cts.map +1 -0
- package/dist/webauthn/match-expected-rp-id.d.mts +11 -0
- package/dist/webauthn/match-expected-rp-id.d.mts.map +1 -0
- package/dist/webauthn/match-expected-rp-id.mjs +39 -0
- package/dist/webauthn/match-expected-rp-id.mjs.map +1 -0
- package/dist/webauthn/parse-authenticator-data.cjs +69 -0
- package/dist/webauthn/parse-authenticator-data.cjs.map +1 -0
- package/dist/webauthn/parse-authenticator-data.d.cts +10 -0
- package/dist/webauthn/parse-authenticator-data.d.cts.map +1 -0
- package/dist/webauthn/parse-authenticator-data.d.mts +10 -0
- package/dist/webauthn/parse-authenticator-data.d.mts.map +1 -0
- package/dist/webauthn/parse-authenticator-data.mjs +65 -0
- package/dist/webauthn/parse-authenticator-data.mjs.map +1 -0
- package/dist/webauthn/types.cjs +3 -0
- package/dist/webauthn/types.cjs.map +1 -0
- package/dist/webauthn/types.d.cts +113 -0
- package/dist/webauthn/types.d.cts.map +1 -0
- package/dist/webauthn/types.d.mts +113 -0
- package/dist/webauthn/types.d.mts.map +1 -0
- package/dist/webauthn/types.mjs +2 -0
- package/dist/webauthn/types.mjs.map +1 -0
- package/dist/webauthn/verify-authentication-response.cjs +134 -0
- package/dist/webauthn/verify-authentication-response.cjs.map +1 -0
- package/dist/webauthn/verify-authentication-response.d.cts +63 -0
- package/dist/webauthn/verify-authentication-response.d.cts.map +1 -0
- package/dist/webauthn/verify-authentication-response.d.mts +63 -0
- package/dist/webauthn/verify-authentication-response.d.mts.map +1 -0
- package/dist/webauthn/verify-authentication-response.mjs +130 -0
- package/dist/webauthn/verify-authentication-response.mjs.map +1 -0
- package/dist/webauthn/verify-registration-response.cjs +205 -0
- package/dist/webauthn/verify-registration-response.cjs.map +1 -0
- package/dist/webauthn/verify-registration-response.d.cts +60 -0
- package/dist/webauthn/verify-registration-response.d.cts.map +1 -0
- package/dist/webauthn/verify-registration-response.d.mts +60 -0
- package/dist/webauthn/verify-registration-response.d.mts.map +1 -0
- package/dist/webauthn/verify-registration-response.mjs +201 -0
- package/dist/webauthn/verify-registration-response.mjs.map +1 -0
- package/dist/webauthn/verify-signature.cjs +176 -0
- package/dist/webauthn/verify-signature.cjs.map +1 -0
- package/dist/webauthn/verify-signature.d.cts +21 -0
- package/dist/webauthn/verify-signature.d.cts.map +1 -0
- package/dist/webauthn/verify-signature.d.mts +21 -0
- package/dist/webauthn/verify-signature.d.mts.map +1 -0
- package/dist/webauthn/verify-signature.mjs +172 -0
- package/dist/webauthn/verify-signature.mjs.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COSE Algorithms
|
|
3
|
+
*
|
|
4
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
|
|
5
|
+
*/
|
|
6
|
+
export declare enum COSEALG {
|
|
7
|
+
ES256 = -7,
|
|
8
|
+
EdDSA = -8,
|
|
9
|
+
ES384 = -35,
|
|
10
|
+
ES512 = -36,
|
|
11
|
+
PS256 = -37,
|
|
12
|
+
PS384 = -38,
|
|
13
|
+
PS512 = -39,
|
|
14
|
+
ES256K = -47,
|
|
15
|
+
RS256 = -257,
|
|
16
|
+
RS384 = -258,
|
|
17
|
+
RS512 = -259,
|
|
18
|
+
RS1 = -65535
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* COSE Key Types
|
|
22
|
+
*
|
|
23
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-type
|
|
24
|
+
*/
|
|
25
|
+
export declare enum COSEKTY {
|
|
26
|
+
OKP = 1,
|
|
27
|
+
EC2 = 2,
|
|
28
|
+
RSA = 3
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* COSE Curves
|
|
32
|
+
*
|
|
33
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
|
|
34
|
+
*/
|
|
35
|
+
export declare enum COSECRV {
|
|
36
|
+
P256 = 1,
|
|
37
|
+
P384 = 2,
|
|
38
|
+
P521 = 3,
|
|
39
|
+
ED25519 = 6,
|
|
40
|
+
SECP256K1 = 8
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* COSE Key common and type-specific parameter labels.
|
|
44
|
+
*
|
|
45
|
+
* EC2 and RSA re-use the same numeric labels (-1, -2, -3) with different
|
|
46
|
+
* semantics, so this is a plain object instead of an enum to avoid
|
|
47
|
+
* duplicate-value violations.
|
|
48
|
+
*
|
|
49
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters
|
|
50
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters
|
|
51
|
+
*/
|
|
52
|
+
export declare const COSEKEYS: {
|
|
53
|
+
/** Key Type (common) */
|
|
54
|
+
readonly Kty: 1;
|
|
55
|
+
/** Algorithm (common) */
|
|
56
|
+
readonly Alg: 3;
|
|
57
|
+
/** EC2 / OKP: curve identifier */
|
|
58
|
+
readonly Crv: -1;
|
|
59
|
+
/** EC2: x-coordinate / OKP: public key */
|
|
60
|
+
readonly X: -2;
|
|
61
|
+
/** EC2: y-coordinate */
|
|
62
|
+
readonly Y: -3;
|
|
63
|
+
/** RSA: modulus n (shares numeric label with Crv) */
|
|
64
|
+
readonly N: -1;
|
|
65
|
+
/** RSA: exponent e (shares numeric label with X) */
|
|
66
|
+
readonly E: -2;
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=constants.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.mts","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;;IAExB,yBAAyB;;IAGzB,kCAAkC;;IAElC,0CAA0C;;IAE1C,wBAAwB;;IAGxB,qDAAqD;;IAErD,oDAAoD;;CAE5C,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COSE Algorithms
|
|
3
|
+
*
|
|
4
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
|
|
5
|
+
*/
|
|
6
|
+
export var COSEALG;
|
|
7
|
+
(function (COSEALG) {
|
|
8
|
+
COSEALG[COSEALG["ES256"] = -7] = "ES256";
|
|
9
|
+
COSEALG[COSEALG["EdDSA"] = -8] = "EdDSA";
|
|
10
|
+
COSEALG[COSEALG["ES384"] = -35] = "ES384";
|
|
11
|
+
COSEALG[COSEALG["ES512"] = -36] = "ES512";
|
|
12
|
+
COSEALG[COSEALG["PS256"] = -37] = "PS256";
|
|
13
|
+
COSEALG[COSEALG["PS384"] = -38] = "PS384";
|
|
14
|
+
COSEALG[COSEALG["PS512"] = -39] = "PS512";
|
|
15
|
+
COSEALG[COSEALG["ES256K"] = -47] = "ES256K";
|
|
16
|
+
COSEALG[COSEALG["RS256"] = -257] = "RS256";
|
|
17
|
+
COSEALG[COSEALG["RS384"] = -258] = "RS384";
|
|
18
|
+
COSEALG[COSEALG["RS512"] = -259] = "RS512";
|
|
19
|
+
COSEALG[COSEALG["RS1"] = -65535] = "RS1";
|
|
20
|
+
})(COSEALG || (COSEALG = {}));
|
|
21
|
+
/**
|
|
22
|
+
* COSE Key Types
|
|
23
|
+
*
|
|
24
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-type
|
|
25
|
+
*/
|
|
26
|
+
export var COSEKTY;
|
|
27
|
+
(function (COSEKTY) {
|
|
28
|
+
COSEKTY[COSEKTY["OKP"] = 1] = "OKP";
|
|
29
|
+
COSEKTY[COSEKTY["EC2"] = 2] = "EC2";
|
|
30
|
+
COSEKTY[COSEKTY["RSA"] = 3] = "RSA";
|
|
31
|
+
})(COSEKTY || (COSEKTY = {}));
|
|
32
|
+
/**
|
|
33
|
+
* COSE Curves
|
|
34
|
+
*
|
|
35
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
|
|
36
|
+
*/
|
|
37
|
+
export var COSECRV;
|
|
38
|
+
(function (COSECRV) {
|
|
39
|
+
COSECRV[COSECRV["P256"] = 1] = "P256";
|
|
40
|
+
COSECRV[COSECRV["P384"] = 2] = "P384";
|
|
41
|
+
COSECRV[COSECRV["P521"] = 3] = "P521";
|
|
42
|
+
COSECRV[COSECRV["ED25519"] = 6] = "ED25519";
|
|
43
|
+
COSECRV[COSECRV["SECP256K1"] = 8] = "SECP256K1";
|
|
44
|
+
})(COSECRV || (COSECRV = {}));
|
|
45
|
+
/**
|
|
46
|
+
* COSE Key common and type-specific parameter labels.
|
|
47
|
+
*
|
|
48
|
+
* EC2 and RSA re-use the same numeric labels (-1, -2, -3) with different
|
|
49
|
+
* semantics, so this is a plain object instead of an enum to avoid
|
|
50
|
+
* duplicate-value violations.
|
|
51
|
+
*
|
|
52
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters
|
|
53
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters
|
|
54
|
+
*/
|
|
55
|
+
export const COSEKEYS = {
|
|
56
|
+
/** Key Type (common) */
|
|
57
|
+
Kty: 1,
|
|
58
|
+
/** Algorithm (common) */
|
|
59
|
+
Alg: 3,
|
|
60
|
+
/** EC2 / OKP: curve identifier */
|
|
61
|
+
Crv: -1,
|
|
62
|
+
/** EC2: x-coordinate / OKP: public key */
|
|
63
|
+
X: -2,
|
|
64
|
+
/** EC2: y-coordinate */
|
|
65
|
+
Y: -3,
|
|
66
|
+
/** RSA: modulus n (shares numeric label with Crv) */
|
|
67
|
+
N: -1,
|
|
68
|
+
/** RSA: exponent e (shares numeric label with X) */
|
|
69
|
+
E: -2,
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=constants.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.mjs","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"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeAttestationObject = void 0;
|
|
4
|
+
const tiny_cbor_1 = require("@levischuck/tiny-cbor");
|
|
5
|
+
/**
|
|
6
|
+
* CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,
|
|
7
|
+
* and `authData` entries.
|
|
8
|
+
*
|
|
9
|
+
* @param attestationObject - Raw attestation object bytes.
|
|
10
|
+
* @returns Decoded AttestationObject map.
|
|
11
|
+
*/
|
|
12
|
+
function decodeAttestationObject(attestationObject) {
|
|
13
|
+
const copy = new Uint8Array(attestationObject);
|
|
14
|
+
const [decoded] = (0, tiny_cbor_1.decodePartialCBOR)(copy, 0);
|
|
15
|
+
return decoded;
|
|
16
|
+
}
|
|
17
|
+
exports.decodeAttestationObject = decodeAttestationObject;
|
|
18
|
+
//# sourceMappingURL=decode-attestation-object.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-attestation-object.cjs","sourceRoot":"","sources":["../../src/webauthn/decode-attestation-object.ts"],"names":[],"mappings":";;;AAAA,qDAA0D;AAI1D;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,iBAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC/C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAA,6BAAiB,EAAC,IAAI,EAAE,CAAC,CAAgC,CAAC;IAC5E,OAAO,OAAO,CAAC;AACjB,CAAC;AAND,0DAMC","sourcesContent":["import { decodePartialCBOR } from '@levischuck/tiny-cbor';\n\nimport type { AttestationObject } from './types';\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"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AttestationObject } from "./types.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,
|
|
4
|
+
* and `authData` entries.
|
|
5
|
+
*
|
|
6
|
+
* @param attestationObject - Raw attestation object bytes.
|
|
7
|
+
* @returns Decoded AttestationObject map.
|
|
8
|
+
*/
|
|
9
|
+
export declare function decodeAttestationObject(attestationObject: Uint8Array): AttestationObject;
|
|
10
|
+
//# sourceMappingURL=decode-attestation-object.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-attestation-object.d.cts","sourceRoot":"","sources":["../../src/webauthn/decode-attestation-object.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAgB;AAEjD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,UAAU,GAC5B,iBAAiB,CAInB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AttestationObject } from "./types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,
|
|
4
|
+
* and `authData` entries.
|
|
5
|
+
*
|
|
6
|
+
* @param attestationObject - Raw attestation object bytes.
|
|
7
|
+
* @returns Decoded AttestationObject map.
|
|
8
|
+
*/
|
|
9
|
+
export declare function decodeAttestationObject(attestationObject: Uint8Array): AttestationObject;
|
|
10
|
+
//# sourceMappingURL=decode-attestation-object.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-attestation-object.d.mts","sourceRoot":"","sources":["../../src/webauthn/decode-attestation-object.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAgB;AAEjD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,UAAU,GAC5B,iBAAiB,CAInB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { decodePartialCBOR } from "@levischuck/tiny-cbor";
|
|
2
|
+
/**
|
|
3
|
+
* CBOR-decode an attestationObject buffer into a Map with `fmt`, `attStmt`,
|
|
4
|
+
* and `authData` entries.
|
|
5
|
+
*
|
|
6
|
+
* @param attestationObject - Raw attestation object bytes.
|
|
7
|
+
* @returns Decoded AttestationObject map.
|
|
8
|
+
*/
|
|
9
|
+
export function decodeAttestationObject(attestationObject) {
|
|
10
|
+
const copy = new Uint8Array(attestationObject);
|
|
11
|
+
const [decoded] = decodePartialCBOR(copy, 0);
|
|
12
|
+
return decoded;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=decode-attestation-object.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-attestation-object.mjs","sourceRoot":"","sources":["../../src/webauthn/decode-attestation-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;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';\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"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeClientDataJSON = void 0;
|
|
4
|
+
const encoding_1 = require("../utils/encoding.cjs");
|
|
5
|
+
/**
|
|
6
|
+
* Decode an authenticator's base64url-encoded clientDataJSON to JSON.
|
|
7
|
+
*
|
|
8
|
+
* @param data - Base64url-encoded clientDataJSON string.
|
|
9
|
+
* @returns Parsed ClientDataJSON object.
|
|
10
|
+
*/
|
|
11
|
+
function decodeClientDataJSON(data) {
|
|
12
|
+
const bytes = (0, encoding_1.base64URLToBytes)(data);
|
|
13
|
+
const text = new TextDecoder().decode(bytes);
|
|
14
|
+
return JSON.parse(text);
|
|
15
|
+
}
|
|
16
|
+
exports.decodeClientDataJSON = decodeClientDataJSON;
|
|
17
|
+
//# sourceMappingURL=decode-client-data-json.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-client-data-json.cjs","sourceRoot":"","sources":["../../src/webauthn/decode-client-data-json.ts"],"names":[],"mappings":";;;AAAA,oDAAqD;AAGrD;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,IAAY;IAC/C,MAAM,KAAK,GAAG,IAAA,2BAAgB,EAAC,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;AAJD,oDAIC","sourcesContent":["import { base64URLToBytes } from '../utils/encoding';\nimport type { ClientDataJSON } from './types';\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"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientDataJSON } from "./types.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Decode an authenticator's base64url-encoded clientDataJSON to JSON.
|
|
4
|
+
*
|
|
5
|
+
* @param data - Base64url-encoded clientDataJSON string.
|
|
6
|
+
* @returns Parsed ClientDataJSON object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function decodeClientDataJSON(data: string): ClientDataJSON;
|
|
9
|
+
//# sourceMappingURL=decode-client-data-json.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-client-data-json.d.cts","sourceRoot":"","sources":["../../src/webauthn/decode-client-data-json.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAgB;AAE9C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAIjE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientDataJSON } from "./types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Decode an authenticator's base64url-encoded clientDataJSON to JSON.
|
|
4
|
+
*
|
|
5
|
+
* @param data - Base64url-encoded clientDataJSON string.
|
|
6
|
+
* @returns Parsed ClientDataJSON object.
|
|
7
|
+
*/
|
|
8
|
+
export declare function decodeClientDataJSON(data: string): ClientDataJSON;
|
|
9
|
+
//# sourceMappingURL=decode-client-data-json.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-client-data-json.d.mts","sourceRoot":"","sources":["../../src/webauthn/decode-client-data-json.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAgB;AAE9C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAIjE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { base64URLToBytes } from "../utils/encoding.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Decode an authenticator's base64url-encoded clientDataJSON to JSON.
|
|
4
|
+
*
|
|
5
|
+
* @param data - Base64url-encoded clientDataJSON string.
|
|
6
|
+
* @returns Parsed ClientDataJSON object.
|
|
7
|
+
*/
|
|
8
|
+
export function decodeClientDataJSON(data) {
|
|
9
|
+
const bytes = base64URLToBytes(data);
|
|
10
|
+
const text = new TextDecoder().decode(bytes);
|
|
11
|
+
return JSON.parse(text);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=decode-client-data-json.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decode-client-data-json.mjs","sourceRoot":"","sources":["../../src/webauthn/decode-client-data-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,8BAA0B;AAGrD;;;;;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';\nimport type { ClientDataJSON } from './types';\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"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.matchExpectedRPID = void 0;
|
|
4
|
+
const sha2_1 = require("@noble/hashes/sha2");
|
|
5
|
+
const encoding_1 = require("../utils/encoding.cjs");
|
|
6
|
+
/**
|
|
7
|
+
* Compare two Uint8Arrays for equality in constant time.
|
|
8
|
+
*
|
|
9
|
+
* @param first - First array.
|
|
10
|
+
* @param second - Second array.
|
|
11
|
+
* @returns Whether the two arrays are equal.
|
|
12
|
+
*/
|
|
13
|
+
function areEqual(first, second) {
|
|
14
|
+
if (first.length !== second.length) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
let diff = 0;
|
|
18
|
+
for (let i = 0; i < first.length; i++) {
|
|
19
|
+
// eslint-disable-next-line no-bitwise
|
|
20
|
+
diff |= first[i] ^ second[i];
|
|
21
|
+
}
|
|
22
|
+
return diff === 0;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Verify that an authenticator data rpIdHash matches one of the expected
|
|
26
|
+
* RP IDs by SHA-256 hashing each candidate and comparing.
|
|
27
|
+
*
|
|
28
|
+
* @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).
|
|
29
|
+
* @param expectedRPIDs - One or more RP ID strings to check against.
|
|
30
|
+
* @returns The matching RP ID string.
|
|
31
|
+
* @throws If no expected RP ID matches.
|
|
32
|
+
*/
|
|
33
|
+
function matchExpectedRPID(rpIdHash, expectedRPIDs) {
|
|
34
|
+
for (const rpID of expectedRPIDs) {
|
|
35
|
+
const expectedHash = (0, sha2_1.sha256)(new TextEncoder().encode(rpID));
|
|
36
|
+
if (areEqual(rpIdHash, expectedHash)) {
|
|
37
|
+
return rpID;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`Unexpected RP ID hash: received ${(0, encoding_1.bytesToHex)(rpIdHash)}`);
|
|
41
|
+
}
|
|
42
|
+
exports.matchExpectedRPID = matchExpectedRPID;
|
|
43
|
+
//# sourceMappingURL=match-expected-rp-id.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-expected-rp-id.cjs","sourceRoot":"","sources":["../../src/webauthn/match-expected-rp-id.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAE5C,oDAA+C;AAE/C;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,KAAiB,EAAE,MAAkB;IACrD,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,sCAAsC;QACtC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,iBAAiB,CAC/B,QAAoB,EACpB,aAAuB;IAEvB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,IAAA,aAAM,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,IAAI,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAA,qBAAU,EAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC;AAXD,8CAWC","sourcesContent":["import { sha256 } from '@noble/hashes/sha2';\n\nimport { bytesToHex } from '../utils/encoding';\n\n/**\n * Compare two Uint8Arrays for equality in constant time.\n *\n * @param first - First array.\n * @param second - Second array.\n * @returns Whether the two arrays are equal.\n */\nfunction areEqual(first: Uint8Array, second: Uint8Array): boolean {\n if (first.length !== second.length) {\n return false;\n }\n let diff = 0;\n for (let i = 0; i < first.length; i++) {\n // eslint-disable-next-line no-bitwise\n diff |= first[i] ^ second[i];\n }\n return diff === 0;\n}\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 The matching RP ID string.\n * @throws If no expected RP ID matches.\n */\nexport function matchExpectedRPID(\n rpIdHash: Uint8Array,\n expectedRPIDs: string[],\n): string {\n for (const rpID of expectedRPIDs) {\n const expectedHash = sha256(new TextEncoder().encode(rpID));\n if (areEqual(rpIdHash, expectedHash)) {\n return rpID;\n }\n }\n throw new Error(`Unexpected RP ID hash: received ${bytesToHex(rpIdHash)}`);\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify that an authenticator data rpIdHash matches one of the expected
|
|
3
|
+
* RP IDs by SHA-256 hashing each candidate and comparing.
|
|
4
|
+
*
|
|
5
|
+
* @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).
|
|
6
|
+
* @param expectedRPIDs - One or more RP ID strings to check against.
|
|
7
|
+
* @returns The matching RP ID string.
|
|
8
|
+
* @throws If no expected RP ID matches.
|
|
9
|
+
*/
|
|
10
|
+
export declare function matchExpectedRPID(rpIdHash: Uint8Array, expectedRPIDs: string[]): string;
|
|
11
|
+
//# sourceMappingURL=match-expected-rp-id.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-expected-rp-id.d.cts","sourceRoot":"","sources":["../../src/webauthn/match-expected-rp-id.ts"],"names":[],"mappings":"AAuBA;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,UAAU,EACpB,aAAa,EAAE,MAAM,EAAE,GACtB,MAAM,CAQR"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify that an authenticator data rpIdHash matches one of the expected
|
|
3
|
+
* RP IDs by SHA-256 hashing each candidate and comparing.
|
|
4
|
+
*
|
|
5
|
+
* @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).
|
|
6
|
+
* @param expectedRPIDs - One or more RP ID strings to check against.
|
|
7
|
+
* @returns The matching RP ID string.
|
|
8
|
+
* @throws If no expected RP ID matches.
|
|
9
|
+
*/
|
|
10
|
+
export declare function matchExpectedRPID(rpIdHash: Uint8Array, expectedRPIDs: string[]): string;
|
|
11
|
+
//# sourceMappingURL=match-expected-rp-id.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-expected-rp-id.d.mts","sourceRoot":"","sources":["../../src/webauthn/match-expected-rp-id.ts"],"names":[],"mappings":"AAuBA;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,UAAU,EACpB,aAAa,EAAE,MAAM,EAAE,GACtB,MAAM,CAQR"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha2";
|
|
2
|
+
import { bytesToHex } from "../utils/encoding.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Compare two Uint8Arrays for equality in constant time.
|
|
5
|
+
*
|
|
6
|
+
* @param first - First array.
|
|
7
|
+
* @param second - Second array.
|
|
8
|
+
* @returns Whether the two arrays are equal.
|
|
9
|
+
*/
|
|
10
|
+
function areEqual(first, second) {
|
|
11
|
+
if (first.length !== second.length) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
let diff = 0;
|
|
15
|
+
for (let i = 0; i < first.length; i++) {
|
|
16
|
+
// eslint-disable-next-line no-bitwise
|
|
17
|
+
diff |= first[i] ^ second[i];
|
|
18
|
+
}
|
|
19
|
+
return diff === 0;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Verify that an authenticator data rpIdHash matches one of the expected
|
|
23
|
+
* RP IDs by SHA-256 hashing each candidate and comparing.
|
|
24
|
+
*
|
|
25
|
+
* @param rpIdHash - The rpIdHash from authenticatorData (32 bytes).
|
|
26
|
+
* @param expectedRPIDs - One or more RP ID strings to check against.
|
|
27
|
+
* @returns The matching RP ID string.
|
|
28
|
+
* @throws If no expected RP ID matches.
|
|
29
|
+
*/
|
|
30
|
+
export function matchExpectedRPID(rpIdHash, expectedRPIDs) {
|
|
31
|
+
for (const rpID of expectedRPIDs) {
|
|
32
|
+
const expectedHash = sha256(new TextEncoder().encode(rpID));
|
|
33
|
+
if (areEqual(rpIdHash, expectedHash)) {
|
|
34
|
+
return rpID;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Unexpected RP ID hash: received ${bytesToHex(rpIdHash)}`);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=match-expected-rp-id.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-expected-rp-id.mjs","sourceRoot":"","sources":["../../src/webauthn/match-expected-rp-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,2BAA2B;AAE5C,OAAO,EAAE,UAAU,EAAE,8BAA0B;AAE/C;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,KAAiB,EAAE,MAAkB;IACrD,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,sCAAsC;QACtC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAoB,EACpB,aAAuB;IAEvB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,IAAI,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,mCAAmC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { sha256 } from '@noble/hashes/sha2';\n\nimport { bytesToHex } from '../utils/encoding';\n\n/**\n * Compare two Uint8Arrays for equality in constant time.\n *\n * @param first - First array.\n * @param second - Second array.\n * @returns Whether the two arrays are equal.\n */\nfunction areEqual(first: Uint8Array, second: Uint8Array): boolean {\n if (first.length !== second.length) {\n return false;\n }\n let diff = 0;\n for (let i = 0; i < first.length; i++) {\n // eslint-disable-next-line no-bitwise\n diff |= first[i] ^ second[i];\n }\n return diff === 0;\n}\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 The matching RP ID string.\n * @throws If no expected RP ID matches.\n */\nexport function matchExpectedRPID(\n rpIdHash: Uint8Array,\n expectedRPIDs: string[],\n): string {\n for (const rpID of expectedRPIDs) {\n const expectedHash = sha256(new TextEncoder().encode(rpID));\n if (areEqual(rpIdHash, expectedHash)) {\n return rpID;\n }\n }\n throw new Error(`Unexpected RP ID hash: received ${bytesToHex(rpIdHash)}`);\n}\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAuthenticatorData = void 0;
|
|
4
|
+
const tiny_cbor_1 = require("@levischuck/tiny-cbor");
|
|
5
|
+
/* eslint-disable no-bitwise */
|
|
6
|
+
/**
|
|
7
|
+
* Parse an authenticator data buffer per §6.1 of the WebAuthn spec.
|
|
8
|
+
*
|
|
9
|
+
* @param authData - Raw authenticator data bytes.
|
|
10
|
+
* @returns Parsed authenticator data with flags, rpIdHash, counter, and
|
|
11
|
+
* optional attested credential data.
|
|
12
|
+
*/
|
|
13
|
+
function parseAuthenticatorData(authData) {
|
|
14
|
+
if (authData.byteLength < 37) {
|
|
15
|
+
throw new Error(`authenticatorData is ${authData.byteLength} bytes, expected at least 37`);
|
|
16
|
+
}
|
|
17
|
+
let pointer = 0;
|
|
18
|
+
const rpIdHash = authData.slice(pointer, pointer + 32);
|
|
19
|
+
pointer += 32;
|
|
20
|
+
const flagsByte = authData[pointer];
|
|
21
|
+
const flags = {
|
|
22
|
+
up: Boolean(flagsByte & (1 << 0)),
|
|
23
|
+
uv: Boolean(flagsByte & (1 << 2)),
|
|
24
|
+
be: Boolean(flagsByte & (1 << 3)),
|
|
25
|
+
bs: Boolean(flagsByte & (1 << 4)),
|
|
26
|
+
at: Boolean(flagsByte & (1 << 6)),
|
|
27
|
+
ed: Boolean(flagsByte & (1 << 7)),
|
|
28
|
+
flagsByte,
|
|
29
|
+
};
|
|
30
|
+
pointer += 1;
|
|
31
|
+
const counterView = new DataView(authData.buffer, authData.byteOffset + pointer, 4);
|
|
32
|
+
const counter = counterView.getUint32(0, false);
|
|
33
|
+
pointer += 4;
|
|
34
|
+
const result = {
|
|
35
|
+
rpIdHash,
|
|
36
|
+
flags,
|
|
37
|
+
counter,
|
|
38
|
+
};
|
|
39
|
+
if (flags.at) {
|
|
40
|
+
const aaguid = authData.slice(pointer, pointer + 16);
|
|
41
|
+
pointer += 16;
|
|
42
|
+
const credIDLenView = new DataView(authData.buffer, authData.byteOffset + pointer, 2);
|
|
43
|
+
const credIDLen = credIDLenView.getUint16(0, false);
|
|
44
|
+
pointer += 2;
|
|
45
|
+
const credentialID = authData.slice(pointer, pointer + credIDLen);
|
|
46
|
+
pointer += credIDLen;
|
|
47
|
+
const pubKeyBytes = authData.slice(pointer);
|
|
48
|
+
const [, nextOffset] = (0, tiny_cbor_1.decodePartialCBOR)(new Uint8Array(pubKeyBytes), 0);
|
|
49
|
+
const credentialPublicKey = authData.slice(pointer, pointer + nextOffset);
|
|
50
|
+
pointer += nextOffset;
|
|
51
|
+
result.aaguid = aaguid;
|
|
52
|
+
result.credentialID = credentialID;
|
|
53
|
+
result.credentialPublicKey = credentialPublicKey;
|
|
54
|
+
}
|
|
55
|
+
if (flags.ed) {
|
|
56
|
+
const remaining = authData.slice(pointer);
|
|
57
|
+
const [decoded, consumed] = (0, tiny_cbor_1.decodePartialCBOR)(new Uint8Array(remaining), 0);
|
|
58
|
+
result.extensionsData = decoded;
|
|
59
|
+
result.extensionsDataBuffer = remaining.slice(0, consumed);
|
|
60
|
+
pointer += consumed;
|
|
61
|
+
}
|
|
62
|
+
if (authData.byteLength > pointer) {
|
|
63
|
+
throw new Error('Leftover bytes detected while parsing authenticator data');
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
exports.parseAuthenticatorData = parseAuthenticatorData;
|
|
68
|
+
/* eslint-enable no-bitwise */
|
|
69
|
+
//# sourceMappingURL=parse-authenticator-data.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-authenticator-data.cjs","sourceRoot":"","sources":["../../src/webauthn/parse-authenticator-data.ts"],"names":[],"mappings":"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","sourcesContent":["import { decodePartialCBOR } from '@levischuck/tiny-cbor';\n\nimport type { ParsedAuthenticatorData, AuthenticatorDataFlags } from './types';\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"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParsedAuthenticatorData } from "./types.cjs";
|
|
2
|
+
/**
|
|
3
|
+
* Parse an authenticator data buffer per §6.1 of the WebAuthn spec.
|
|
4
|
+
*
|
|
5
|
+
* @param authData - Raw authenticator data bytes.
|
|
6
|
+
* @returns Parsed authenticator data with flags, rpIdHash, counter, and
|
|
7
|
+
* optional attested credential data.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseAuthenticatorData(authData: Uint8Array): ParsedAuthenticatorData;
|
|
10
|
+
//# sourceMappingURL=parse-authenticator-data.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-authenticator-data.d.cts","sourceRoot":"","sources":["../../src/webauthn/parse-authenticator-data.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAA0B,oBAAgB;AAI/E;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,UAAU,GACnB,uBAAuB,CAkFzB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParsedAuthenticatorData } from "./types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Parse an authenticator data buffer per §6.1 of the WebAuthn spec.
|
|
4
|
+
*
|
|
5
|
+
* @param authData - Raw authenticator data bytes.
|
|
6
|
+
* @returns Parsed authenticator data with flags, rpIdHash, counter, and
|
|
7
|
+
* optional attested credential data.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseAuthenticatorData(authData: Uint8Array): ParsedAuthenticatorData;
|
|
10
|
+
//# sourceMappingURL=parse-authenticator-data.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-authenticator-data.d.mts","sourceRoot":"","sources":["../../src/webauthn/parse-authenticator-data.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAA0B,oBAAgB;AAI/E;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,UAAU,GACnB,uBAAuB,CAkFzB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { decodePartialCBOR } from "@levischuck/tiny-cbor";
|
|
2
|
+
/* eslint-disable no-bitwise */
|
|
3
|
+
/**
|
|
4
|
+
* Parse an authenticator data buffer per §6.1 of the WebAuthn spec.
|
|
5
|
+
*
|
|
6
|
+
* @param authData - Raw authenticator data bytes.
|
|
7
|
+
* @returns Parsed authenticator data with flags, rpIdHash, counter, and
|
|
8
|
+
* optional attested credential data.
|
|
9
|
+
*/
|
|
10
|
+
export function parseAuthenticatorData(authData) {
|
|
11
|
+
if (authData.byteLength < 37) {
|
|
12
|
+
throw new Error(`authenticatorData is ${authData.byteLength} bytes, expected at least 37`);
|
|
13
|
+
}
|
|
14
|
+
let pointer = 0;
|
|
15
|
+
const rpIdHash = authData.slice(pointer, pointer + 32);
|
|
16
|
+
pointer += 32;
|
|
17
|
+
const flagsByte = authData[pointer];
|
|
18
|
+
const flags = {
|
|
19
|
+
up: Boolean(flagsByte & (1 << 0)),
|
|
20
|
+
uv: Boolean(flagsByte & (1 << 2)),
|
|
21
|
+
be: Boolean(flagsByte & (1 << 3)),
|
|
22
|
+
bs: Boolean(flagsByte & (1 << 4)),
|
|
23
|
+
at: Boolean(flagsByte & (1 << 6)),
|
|
24
|
+
ed: Boolean(flagsByte & (1 << 7)),
|
|
25
|
+
flagsByte,
|
|
26
|
+
};
|
|
27
|
+
pointer += 1;
|
|
28
|
+
const counterView = new DataView(authData.buffer, authData.byteOffset + pointer, 4);
|
|
29
|
+
const counter = counterView.getUint32(0, false);
|
|
30
|
+
pointer += 4;
|
|
31
|
+
const result = {
|
|
32
|
+
rpIdHash,
|
|
33
|
+
flags,
|
|
34
|
+
counter,
|
|
35
|
+
};
|
|
36
|
+
if (flags.at) {
|
|
37
|
+
const aaguid = authData.slice(pointer, pointer + 16);
|
|
38
|
+
pointer += 16;
|
|
39
|
+
const credIDLenView = new DataView(authData.buffer, authData.byteOffset + pointer, 2);
|
|
40
|
+
const credIDLen = credIDLenView.getUint16(0, false);
|
|
41
|
+
pointer += 2;
|
|
42
|
+
const credentialID = authData.slice(pointer, pointer + credIDLen);
|
|
43
|
+
pointer += credIDLen;
|
|
44
|
+
const pubKeyBytes = authData.slice(pointer);
|
|
45
|
+
const [, nextOffset] = decodePartialCBOR(new Uint8Array(pubKeyBytes), 0);
|
|
46
|
+
const credentialPublicKey = authData.slice(pointer, pointer + nextOffset);
|
|
47
|
+
pointer += nextOffset;
|
|
48
|
+
result.aaguid = aaguid;
|
|
49
|
+
result.credentialID = credentialID;
|
|
50
|
+
result.credentialPublicKey = credentialPublicKey;
|
|
51
|
+
}
|
|
52
|
+
if (flags.ed) {
|
|
53
|
+
const remaining = authData.slice(pointer);
|
|
54
|
+
const [decoded, consumed] = decodePartialCBOR(new Uint8Array(remaining), 0);
|
|
55
|
+
result.extensionsData = decoded;
|
|
56
|
+
result.extensionsDataBuffer = remaining.slice(0, consumed);
|
|
57
|
+
pointer += consumed;
|
|
58
|
+
}
|
|
59
|
+
if (authData.byteLength > pointer) {
|
|
60
|
+
throw new Error('Leftover bytes detected while parsing authenticator data');
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
/* eslint-enable no-bitwise */
|
|
65
|
+
//# sourceMappingURL=parse-authenticator-data.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-authenticator-data.mjs","sourceRoot":"","sources":["../../src/webauthn/parse-authenticator-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,8BAA8B;AAI1D,+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 { ParsedAuthenticatorData, AuthenticatorDataFlags } from './types';\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"]}
|