@eggjs/cookies 4.0.0-beta.34 → 4.0.0-beta.36
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/cookie.d.ts +67 -64
- package/dist/cookie.js +70 -87
- package/dist/cookies.d.ts +43 -39
- package/dist/cookies.js +215 -275
- package/dist/error.d.ts +5 -2
- package/dist/error.js +11 -10
- package/dist/index.d.ts +5 -4
- package/dist/index.js +6 -5
- package/dist/keygrip.d.ts +13 -10
- package/dist/keygrip.js +86 -103
- package/package.json +24 -31
package/dist/keygrip.js
CHANGED
|
@@ -1,113 +1,96 @@
|
|
|
1
|
-
import
|
|
2
|
-
import crypto
|
|
3
|
-
import
|
|
4
|
-
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import { debuglog } from "node:util";
|
|
4
|
+
|
|
5
|
+
//#region src/keygrip.ts
|
|
6
|
+
const debug = debuglog("egg/cookies:keygrip");
|
|
5
7
|
const KEY_LEN = 32;
|
|
6
8
|
const IV_SIZE = 16;
|
|
7
|
-
const passwordCache = new Map();
|
|
9
|
+
const passwordCache = /* @__PURE__ */ new Map();
|
|
8
10
|
const replacer = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
"/": "_",
|
|
12
|
+
"+": "-",
|
|
13
|
+
"=": ""
|
|
12
14
|
};
|
|
13
15
|
function constantTimeCompare(a, b) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
return crypto.timingSafeEqual(a, b);
|
|
18
|
-
}
|
|
19
|
-
// patch from https://github.com/crypto-utils/keygrip
|
|
20
|
-
export class Keygrip {
|
|
21
|
-
#keys;
|
|
22
|
-
#hash = 'sha256';
|
|
23
|
-
#cipher = 'aes-256-cbc';
|
|
24
|
-
constructor(keys) {
|
|
25
|
-
assert(Array.isArray(keys) && keys.length > 0, 'keys must be provided and should be an array');
|
|
26
|
-
this.#keys = keys;
|
|
27
|
-
}
|
|
28
|
-
// encrypt a message
|
|
29
|
-
encrypt(data, key) {
|
|
30
|
-
key = key || this.#keys[0];
|
|
31
|
-
const password = keyToPassword(key);
|
|
32
|
-
const cipher = crypto.createCipheriv(this.#cipher, password.key, password.iv);
|
|
33
|
-
return crypt(cipher, data);
|
|
34
|
-
}
|
|
35
|
-
// decrypt a single message
|
|
36
|
-
// returns false on bad decrypts
|
|
37
|
-
decrypt(data) {
|
|
38
|
-
// decrypt every key
|
|
39
|
-
const keys = this.#keys;
|
|
40
|
-
for (let i = 0; i < keys.length; i++) {
|
|
41
|
-
const value = this.#decryptByKey(data, keys[i]);
|
|
42
|
-
if (value !== false) {
|
|
43
|
-
return { value, index: i };
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
#decryptByKey(data, key) {
|
|
49
|
-
try {
|
|
50
|
-
const password = keyToPassword(key);
|
|
51
|
-
const cipher = crypto.createDecipheriv(this.#cipher, password.key, password.iv);
|
|
52
|
-
return crypt(cipher, data);
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
debug('crypt error: %s', err);
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
sign(data, key) {
|
|
60
|
-
// default to the first key
|
|
61
|
-
key = key || this.#keys[0];
|
|
62
|
-
// url safe base64
|
|
63
|
-
return crypto
|
|
64
|
-
.createHmac(this.#hash, key)
|
|
65
|
-
.update(data)
|
|
66
|
-
.digest('base64')
|
|
67
|
-
.replace(/\/|\+|=/g, (x) => {
|
|
68
|
-
return replacer[x];
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
verify(data, digest) {
|
|
72
|
-
const keys = this.#keys;
|
|
73
|
-
for (let i = 0; i < keys.length; i++) {
|
|
74
|
-
const key = keys[i];
|
|
75
|
-
if (constantTimeCompare(Buffer.from(digest), Buffer.from(this.sign(data, key)))) {
|
|
76
|
-
debug('data %s match key %s, index: %d', data, key, i);
|
|
77
|
-
return i;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return -1;
|
|
81
|
-
}
|
|
16
|
+
if (a.length !== b.length) return false;
|
|
17
|
+
return crypto.timingSafeEqual(a, b);
|
|
82
18
|
}
|
|
19
|
+
var Keygrip = class {
|
|
20
|
+
#keys;
|
|
21
|
+
#hash = "sha256";
|
|
22
|
+
#cipher = "aes-256-cbc";
|
|
23
|
+
constructor(keys) {
|
|
24
|
+
assert(Array.isArray(keys) && keys.length > 0, "keys must be provided and should be an array");
|
|
25
|
+
this.#keys = keys;
|
|
26
|
+
}
|
|
27
|
+
encrypt(data, key) {
|
|
28
|
+
key = key || this.#keys[0];
|
|
29
|
+
const password = keyToPassword(key);
|
|
30
|
+
return crypt(crypto.createCipheriv(this.#cipher, password.key, password.iv), data);
|
|
31
|
+
}
|
|
32
|
+
decrypt(data) {
|
|
33
|
+
const keys = this.#keys;
|
|
34
|
+
for (let i = 0; i < keys.length; i++) {
|
|
35
|
+
const value = this.#decryptByKey(data, keys[i]);
|
|
36
|
+
if (value !== false) return {
|
|
37
|
+
value,
|
|
38
|
+
index: i
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
#decryptByKey(data, key) {
|
|
44
|
+
try {
|
|
45
|
+
const password = keyToPassword(key);
|
|
46
|
+
return crypt(crypto.createDecipheriv(this.#cipher, password.key, password.iv), data);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
debug("crypt error: %s", err);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
sign(data, key) {
|
|
53
|
+
key = key || this.#keys[0];
|
|
54
|
+
return crypto.createHmac(this.#hash, key).update(data).digest("base64").replace(/\/|\+|=/g, (x) => {
|
|
55
|
+
return replacer[x];
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
verify(data, digest) {
|
|
59
|
+
const keys = this.#keys;
|
|
60
|
+
for (let i = 0; i < keys.length; i++) {
|
|
61
|
+
const key = keys[i];
|
|
62
|
+
if (constantTimeCompare(Buffer.from(digest), Buffer.from(this.sign(data, key)))) {
|
|
63
|
+
debug("data %s match key %s, index: %d", data, key, i);
|
|
64
|
+
return i;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return -1;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
83
70
|
function crypt(cipher, data) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
const text = Buffer.isBuffer(data) ? cipher.update(data) : cipher.update(data, "utf-8");
|
|
72
|
+
const pad = cipher.final();
|
|
73
|
+
return Buffer.concat([text, pad]);
|
|
87
74
|
}
|
|
88
75
|
function keyToPassword(key) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const password = {
|
|
107
|
-
key: bytes.subarray(0, KEY_LEN),
|
|
108
|
-
iv: bytes.subarray(KEY_LEN, bytes.length),
|
|
109
|
-
};
|
|
110
|
-
passwordCache.set(key, password);
|
|
111
|
-
return password;
|
|
76
|
+
if (passwordCache.has(key)) return passwordCache.get(key);
|
|
77
|
+
const bytes = Buffer.alloc(KEY_LEN + IV_SIZE);
|
|
78
|
+
let lastHash = null, nBytes = 0;
|
|
79
|
+
while (nBytes < bytes.length) {
|
|
80
|
+
const hash = crypto.createHash("md5");
|
|
81
|
+
if (lastHash) hash.update(lastHash);
|
|
82
|
+
hash.update(key);
|
|
83
|
+
lastHash = hash.digest();
|
|
84
|
+
lastHash.copy(bytes, nBytes);
|
|
85
|
+
nBytes += lastHash.length;
|
|
86
|
+
}
|
|
87
|
+
const password = {
|
|
88
|
+
key: bytes.subarray(0, KEY_LEN),
|
|
89
|
+
iv: bytes.subarray(KEY_LEN, bytes.length)
|
|
90
|
+
};
|
|
91
|
+
passwordCache.set(key, password);
|
|
92
|
+
return password;
|
|
112
93
|
}
|
|
113
|
-
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
export { Keygrip };
|
package/package.json
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/cookies",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
4
|
-
"
|
|
5
|
-
|
|
3
|
+
"version": "4.0.0-beta.36",
|
|
4
|
+
"description": "cookies module for egg",
|
|
5
|
+
"homepage": "https://github.com/eggjs/egg/tree/next/packages/cookies",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "fengmk2 <fengmk2@gmail.com> (https://github.com/fengmk2)",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/eggjs/egg.git",
|
|
11
|
+
"directory": "packages/cookies"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./dist/index.js",
|
|
22
|
+
"./package.json": "./package.json"
|
|
6
23
|
},
|
|
7
24
|
"publishConfig": {
|
|
8
25
|
"access": "public"
|
|
9
26
|
},
|
|
10
|
-
"description": "cookies module for egg",
|
|
11
27
|
"dependencies": {
|
|
12
28
|
"should-send-same-site-none": "^2.0.5",
|
|
13
29
|
"utility": "^2.5.0"
|
|
@@ -17,36 +33,13 @@
|
|
|
17
33
|
"benchmark": "^2.1.4",
|
|
18
34
|
"cookies": "^0.9.1",
|
|
19
35
|
"keygrip": "^1.0.2",
|
|
20
|
-
"oxlint": "^1.24.0",
|
|
21
36
|
"typescript": "^5.9.3",
|
|
22
|
-
"
|
|
23
|
-
"@eggjs/tsconfig": "3.1.0-beta.34"
|
|
24
|
-
},
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "git://github.com/eggjs/egg.git",
|
|
28
|
-
"directory": "packages/cookies"
|
|
37
|
+
"@eggjs/tsconfig": "3.1.0-beta.36"
|
|
29
38
|
},
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
"license": "MIT",
|
|
33
|
-
"type": "module",
|
|
34
|
-
"files": [
|
|
35
|
-
"dist"
|
|
36
|
-
],
|
|
37
|
-
"main": "./dist/index.js",
|
|
38
|
-
"module": "./dist/index.js",
|
|
39
|
-
"types": "./dist/index.d.ts",
|
|
40
|
-
"exports": {
|
|
41
|
-
".": "./dist/index.js",
|
|
42
|
-
"./package.json": "./package.json"
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22.18.0"
|
|
43
41
|
},
|
|
44
42
|
"scripts": {
|
|
45
|
-
"
|
|
46
|
-
"typecheck": "tsc --noEmit",
|
|
47
|
-
"lint": "oxlint --type-aware",
|
|
48
|
-
"lint:fix": "npm run lint -- --fix",
|
|
49
|
-
"test": "npm run lint:fix && vitest run",
|
|
50
|
-
"ci": "vitest run --coverage"
|
|
43
|
+
"typecheck": "tsgo --noEmit"
|
|
51
44
|
}
|
|
52
45
|
}
|