@xivdyetools/auth 1.0.1 → 1.0.2
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/dist/hmac.d.ts.map +1 -1
- package/dist/hmac.js +6 -4
- package/dist/hmac.js.map +1 -1
- package/dist/jwt.d.ts.map +1 -1
- package/dist/jwt.js +13 -12
- package/dist/jwt.js.map +1 -1
- package/package.json +3 -3
- package/src/hmac.ts +12 -3
- package/src/jwt.ts +14 -16
package/dist/hmac.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmac.d.ts","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"hmac.d.ts","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAM,GAAG,QAAQ,GAAG,MAAe,GACzC,OAAO,CAAC,SAAS,CAAC,CAcpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAelB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,OAAO,CAAC,CAgClB"}
|
package/dist/hmac.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module hmac
|
|
8
8
|
*/
|
|
9
|
-
import { base64UrlEncodeBytes, bytesToHex, hexToBytes, } from '@xivdyetools/crypto';
|
|
9
|
+
import { base64UrlEncodeBytes, base64UrlDecodeBytes, bytesToHex, hexToBytes, } from '@xivdyetools/crypto';
|
|
10
10
|
/**
|
|
11
11
|
* Create an HMAC-SHA256 CryptoKey from a secret string.
|
|
12
12
|
*
|
|
@@ -71,9 +71,11 @@ export async function hmacSignHex(data, secret) {
|
|
|
71
71
|
*/
|
|
72
72
|
export async function hmacVerify(data, signature, secret) {
|
|
73
73
|
try {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
const key = await createHmacKey(secret, 'verify');
|
|
75
|
+
const encoder = new TextEncoder();
|
|
76
|
+
const signatureBytes = base64UrlDecodeBytes(signature);
|
|
77
|
+
// Use crypto.subtle.verify() which is inherently timing-safe
|
|
78
|
+
return crypto.subtle.verify('HMAC', key, signatureBytes, encoder.encode(data));
|
|
77
79
|
}
|
|
78
80
|
catch {
|
|
79
81
|
return false;
|
package/dist/hmac.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmac.js","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,UAAU,GACX,MAAM,qBAAqB,CAAC;AAY7B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,QAAoC,MAAM;IAE1C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvC,MAAM,SAAS,GACb,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAElD,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B,KAAK,EACL,OAAO,EACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,SAAS,CACV,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAc;IACzD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,OAAO,oBAAoB,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,MAAc;IAEd,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,OAAO,UAAU,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,SAAiB,EACjB,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,
|
|
1
|
+
{"version":3,"file":"hmac.js","sourceRoot":"","sources":["../src/hmac.ts"],"names":[],"mappings":"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"}
|
package/dist/jwt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,wCAAwC;IACxC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAY1D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAkD5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAqD5B;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOxD"}
|
package/dist/jwt.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module jwt
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { base64UrlDecode, base64UrlDecodeBytes, } from '@xivdyetools/crypto';
|
|
15
15
|
import { createHmacKey } from './hmac.js';
|
|
16
16
|
/**
|
|
17
17
|
* Decode a JWT without verifying the signature.
|
|
@@ -76,14 +76,14 @@ export async function verifyJWT(token, secret) {
|
|
|
76
76
|
if (header.alg !== 'HS256') {
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
|
-
// Verify signature
|
|
79
|
+
// SECURITY: Verify signature using crypto.subtle.verify() which is
|
|
80
|
+
// inherently timing-safe (comparison happens in native crypto, not JS)
|
|
80
81
|
const signatureInput = `${headerB64}.${payloadB64}`;
|
|
81
|
-
const key = await createHmacKey(secret, '
|
|
82
|
+
const key = await createHmacKey(secret, 'verify');
|
|
82
83
|
const encoder = new TextEncoder();
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
if (signatureB64 !== expectedSignatureB64) {
|
|
84
|
+
const signatureBytes = base64UrlDecodeBytes(signatureB64);
|
|
85
|
+
const isValid = await crypto.subtle.verify('HMAC', key, signatureBytes, encoder.encode(signatureInput));
|
|
86
|
+
if (!isValid) {
|
|
87
87
|
return null;
|
|
88
88
|
}
|
|
89
89
|
// Decode payload
|
|
@@ -135,13 +135,14 @@ export async function verifyJWTSignatureOnly(token, secret, maxAgeMs) {
|
|
|
135
135
|
if (header.alg !== 'HS256') {
|
|
136
136
|
return null;
|
|
137
137
|
}
|
|
138
|
-
// Verify signature
|
|
138
|
+
// SECURITY: Verify signature using crypto.subtle.verify() which is
|
|
139
|
+
// inherently timing-safe (comparison happens in native crypto, not JS)
|
|
139
140
|
const signatureInput = `${headerB64}.${payloadB64}`;
|
|
140
|
-
const key = await createHmacKey(secret, '
|
|
141
|
+
const key = await createHmacKey(secret, 'verify');
|
|
141
142
|
const encoder = new TextEncoder();
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
if (
|
|
143
|
+
const signatureBytes = base64UrlDecodeBytes(signatureB64);
|
|
144
|
+
const isValid = await crypto.subtle.verify('HMAC', key, signatureBytes, encoder.encode(signatureInput));
|
|
145
|
+
if (!isValid) {
|
|
145
146
|
return null;
|
|
146
147
|
}
|
|
147
148
|
// Decode payload
|
package/dist/jwt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,eAAe,EACf,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AA+B1C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAe,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAAa,EACb,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC;QAEpD,6BAA6B;QAC7B,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAc,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAEjD,+EAA+E;QAC/E,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mEAAmE;QACnE,uEAAuE;QACvE,MAAM,cAAc,GAAG,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,cAAc,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QAE1D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CACxC,MAAM,EACN,GAAG,EACH,cAAc,EACd,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAC/B,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iBAAiB;QACjB,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,OAAO,GAAe,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEpD,mBAAmB;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,KAAa,EACb,MAAc,EACd,QAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC;QAEpD,6BAA6B;QAC7B,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAc,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAEjD,8CAA8C;QAC9C,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mEAAmE;QACnE,uEAAuE;QACvE,MAAM,cAAc,GAAG,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,cAAc,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QAE1D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CACxC,MAAM,EACN,GAAG,EACH,cAAc,EACd,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAC/B,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iBAAiB;QACjB,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,OAAO,GAAe,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEpD,6BAA6B;QAC7B,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;YAC1C,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;gBACxB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AACxC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xivdyetools/auth",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Shared authentication utilities for xivdyetools ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@cloudflare/workers-types": "^4.20241224.0",
|
|
48
|
-
"@vitest/coverage-v8": "^
|
|
48
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
49
49
|
"rimraf": "^6.0.1",
|
|
50
50
|
"typescript": "^5.7.2",
|
|
51
|
-
"vitest": "^
|
|
51
|
+
"vitest": "^4.0.18"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@cloudflare/workers-types": "^4.0.0"
|
package/src/hmac.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
base64UrlEncodeBytes,
|
|
12
|
+
base64UrlDecodeBytes,
|
|
12
13
|
bytesToHex,
|
|
13
14
|
hexToBytes,
|
|
14
15
|
} from '@xivdyetools/crypto';
|
|
@@ -109,9 +110,17 @@ export async function hmacVerify(
|
|
|
109
110
|
secret: string
|
|
110
111
|
): Promise<boolean> {
|
|
111
112
|
try {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
const key = await createHmacKey(secret, 'verify');
|
|
114
|
+
const encoder = new TextEncoder();
|
|
115
|
+
const signatureBytes = base64UrlDecodeBytes(signature);
|
|
116
|
+
|
|
117
|
+
// Use crypto.subtle.verify() which is inherently timing-safe
|
|
118
|
+
return crypto.subtle.verify(
|
|
119
|
+
'HMAC',
|
|
120
|
+
key,
|
|
121
|
+
signatureBytes,
|
|
122
|
+
encoder.encode(data)
|
|
123
|
+
);
|
|
115
124
|
} catch {
|
|
116
125
|
return false;
|
|
117
126
|
}
|
package/src/jwt.ts
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
-
base64UrlEncodeBytes,
|
|
17
16
|
base64UrlDecode,
|
|
18
17
|
base64UrlDecodeBytes,
|
|
19
18
|
} from '@xivdyetools/crypto';
|
|
@@ -119,22 +118,21 @@ export async function verifyJWT(
|
|
|
119
118
|
return null;
|
|
120
119
|
}
|
|
121
120
|
|
|
122
|
-
// Verify signature
|
|
121
|
+
// SECURITY: Verify signature using crypto.subtle.verify() which is
|
|
122
|
+
// inherently timing-safe (comparison happens in native crypto, not JS)
|
|
123
123
|
const signatureInput = `${headerB64}.${payloadB64}`;
|
|
124
|
-
const key = await createHmacKey(secret, '
|
|
124
|
+
const key = await createHmacKey(secret, 'verify');
|
|
125
125
|
const encoder = new TextEncoder();
|
|
126
|
+
const signatureBytes = base64UrlDecodeBytes(signatureB64);
|
|
126
127
|
|
|
127
|
-
const
|
|
128
|
+
const isValid = await crypto.subtle.verify(
|
|
128
129
|
'HMAC',
|
|
129
130
|
key,
|
|
131
|
+
signatureBytes,
|
|
130
132
|
encoder.encode(signatureInput)
|
|
131
133
|
);
|
|
132
|
-
const expectedSignatureB64 = base64UrlEncodeBytes(
|
|
133
|
-
new Uint8Array(expectedSignature)
|
|
134
|
-
);
|
|
135
134
|
|
|
136
|
-
|
|
137
|
-
if (signatureB64 !== expectedSignatureB64) {
|
|
135
|
+
if (!isValid) {
|
|
138
136
|
return null;
|
|
139
137
|
}
|
|
140
138
|
|
|
@@ -197,21 +195,21 @@ export async function verifyJWTSignatureOnly(
|
|
|
197
195
|
return null;
|
|
198
196
|
}
|
|
199
197
|
|
|
200
|
-
// Verify signature
|
|
198
|
+
// SECURITY: Verify signature using crypto.subtle.verify() which is
|
|
199
|
+
// inherently timing-safe (comparison happens in native crypto, not JS)
|
|
201
200
|
const signatureInput = `${headerB64}.${payloadB64}`;
|
|
202
|
-
const key = await createHmacKey(secret, '
|
|
201
|
+
const key = await createHmacKey(secret, 'verify');
|
|
203
202
|
const encoder = new TextEncoder();
|
|
203
|
+
const signatureBytes = base64UrlDecodeBytes(signatureB64);
|
|
204
204
|
|
|
205
|
-
const
|
|
205
|
+
const isValid = await crypto.subtle.verify(
|
|
206
206
|
'HMAC',
|
|
207
207
|
key,
|
|
208
|
+
signatureBytes,
|
|
208
209
|
encoder.encode(signatureInput)
|
|
209
210
|
);
|
|
210
|
-
const expectedSignatureB64 = base64UrlEncodeBytes(
|
|
211
|
-
new Uint8Array(expectedSignature)
|
|
212
|
-
);
|
|
213
211
|
|
|
214
|
-
if (
|
|
212
|
+
if (!isValid) {
|
|
215
213
|
return null;
|
|
216
214
|
}
|
|
217
215
|
|