securequ 1.1.19 → 1.1.21
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/client/Base.cjs +146 -146
- package/client/Base.cjs.map +1 -1
- package/client/Base.d.ts +18 -18
- package/client/Base.js +146 -146
- package/client/Base.js.map +1 -1
- package/client/index.cjs +155 -138
- package/client/index.cjs.map +1 -1
- package/client/index.d.ts +10 -10
- package/client/index.js +156 -139
- package/client/index.js.map +1 -1
- package/client/types.d.ts +39 -35
- package/include/compress.cjs +31 -31
- package/include/compress.cjs.map +1 -1
- package/include/compress.d.ts +9 -9
- package/include/compress.js +33 -33
- package/include/compress.js.map +1 -1
- package/include/crypto.cjs +132 -132
- package/include/crypto.cjs.map +1 -1
- package/include/crypto.d.ts +21 -21
- package/include/crypto.js +132 -132
- package/include/crypto.js.map +1 -1
- package/include/file-scaner.cjs +77 -95
- package/include/file-scaner.cjs.map +1 -1
- package/include/file-scaner.d.ts +11 -11
- package/include/file-scaner.js +74 -95
- package/include/file-scaner.js.map +1 -1
- package/include/file.cjs +78 -60
- package/include/file.cjs.map +1 -1
- package/include/file.js +78 -61
- package/include/file.js.map +1 -1
- package/index.cjs +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/readme.md +312 -312
- package/server/Base.cjs +105 -105
- package/server/Base.cjs.map +1 -1
- package/server/Base.d.ts +20 -20
- package/server/Base.js +105 -105
- package/server/Base.js.map +1 -1
- package/server/Router.cjs +29 -29
- package/server/Router.cjs.map +1 -1
- package/server/Router.d.ts +7 -7
- package/server/Router.js +29 -29
- package/server/Router.js.map +1 -1
- package/server/index.cjs +185 -187
- package/server/index.cjs.map +1 -1
- package/server/index.d.ts +5 -5
- package/server/index.js +186 -188
- package/server/index.js.map +1 -1
- package/server/types.d.ts +72 -72
package/include/compress.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compress.js","sources":["../../src/include/compress.ts"],"sourcesContent":["import sodium from \"libsodium-wrappers\";\
|
|
1
|
+
{"version":3,"file":"compress.js","sources":["../../src/include/compress.ts"],"sourcesContent":["import sodium from \"libsodium-wrappers\";\nimport { compressSync, decompressSync } from \"fflate\";\nimport { unpack, pack } from \"msgpackr\";\nimport crypto from \"./crypto\";\n\n/* ================================\n Buffer-level\n================================ */\nasync function compressBuffer(input: any): Promise<Uint8Array> {\n await crypto.init();\n const encoded = pack(input);\n return compressSync(encoded);\n}\n\nasync function decompressBuffer(input: Uint8Array): Promise<any> {\n await crypto.init();\n const decompressed = decompressSync(input);\n return unpack(decompressed);\n}\n\n/* ================================\n String-level\n================================ */\nasync function compress(input: any): Promise<string> {\n await crypto.init();\n const compressed = await compressBuffer(input);\n return sodium.to_base64(\n compressed,\n sodium.base64_variants.ORIGINAL\n );\n}\n\nasync function decompress(base64Str: string): Promise<any> {\n await crypto.init();\n const compressed = sodium.from_base64(\n base64Str,\n sodium.base64_variants.ORIGINAL\n );\n return decompressBuffer(compressed);\n}\n\nconst compresor = {\n compressBuffer,\n decompressBuffer,\n compress,\n decompress\n}\n\nexport default compresor"],"names":[],"mappings":";;;;;AAKA;;AAEmC;AACnC,eAAe,cAAc,CAAC,KAAU,EAAA;AACrC,IAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,IAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;AAC3B,IAAA,OAAO,YAAY,CAAC,OAAO,CAAC;AAC/B;AAEA,eAAe,gBAAgB,CAAC,KAAiB,EAAA;AAC9C,IAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,IAAA,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC;AAC1C,IAAA,OAAO,MAAM,CAAC,YAAY,CAAC;AAC9B;AAEA;;AAEmC;AACnC,eAAe,QAAQ,CAAC,KAAU,EAAA;AAC/B,IAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,IAAA,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC;AAC9C,IAAA,OAAO,MAAM,CAAC,SAAS,CACpB,UAAU,EACV,MAAM,CAAC,eAAe,CAAC,QAAQ,CACjC;AACJ;AAEA,eAAe,UAAU,CAAC,SAAiB,EAAA;AACxC,IAAA,MAAM,MAAM,CAAC,IAAI,EAAE;AACnB,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAClC,SAAS,EACT,MAAM,CAAC,eAAe,CAAC,QAAQ,CACjC;AACD,IAAA,OAAO,gBAAgB,CAAC,UAAU,CAAC;AACtC;AAEA,MAAM,SAAS,GAAG;IACf,cAAc;IACd,gBAAgB;IAChB,QAAQ;IACR;;;;;"}
|
package/include/crypto.cjs
CHANGED
|
@@ -3,138 +3,138 @@
|
|
|
3
3
|
var sodium = require('libsodium-wrappers');
|
|
4
4
|
var compress = require('./compress.cjs');
|
|
5
5
|
|
|
6
|
-
/* ================================
|
|
7
|
-
Sodium Init (SAFE & IDP)
|
|
8
|
-
================================ */
|
|
9
|
-
let initPromise = null;
|
|
10
|
-
async function init() {
|
|
11
|
-
if (!initPromise) {
|
|
12
|
-
initPromise = sodium.ready.then(() => void 0);
|
|
13
|
-
}
|
|
14
|
-
return initPromise;
|
|
15
|
-
}
|
|
16
|
-
/* ================================
|
|
17
|
-
Key Derivation
|
|
18
|
-
(Stable & deterministic)
|
|
19
|
-
================================ */
|
|
20
|
-
function deriveKey(secret) {
|
|
21
|
-
return sodium.crypto_generichash(sodium.crypto_secretbox_KEYBYTES, sodium.from_string(secret), null);
|
|
22
|
-
}
|
|
23
|
-
/* ================================
|
|
24
|
-
Encrypt (string)
|
|
25
|
-
================================ */
|
|
26
|
-
async function encrypt(input, secret) {
|
|
27
|
-
const buf = await encryptBuffer(input, secret);
|
|
28
|
-
return sodium.to_base64(buf, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
29
|
-
}
|
|
30
|
-
/* ================================
|
|
31
|
-
Decrypt (string)
|
|
32
|
-
================================ */
|
|
33
|
-
async function decrypt(base64, secret) {
|
|
34
|
-
await init();
|
|
35
|
-
const box = sodium.from_base64(base64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
36
|
-
return decryptBuffer(box, secret);
|
|
37
|
-
}
|
|
38
|
-
/* ================================
|
|
39
|
-
Encrypt (buffer)
|
|
40
|
-
================================ */
|
|
41
|
-
async function encryptBuffer(input, secret) {
|
|
42
|
-
await init();
|
|
43
|
-
const key = deriveKey(secret);
|
|
44
|
-
const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
|
|
45
|
-
const compressed = await compress.compressBuffer(input);
|
|
46
|
-
const cipher = sodium.crypto_secretbox_easy(compressed, nonce, key);
|
|
47
|
-
const out = new Uint8Array(nonce.length + cipher.length);
|
|
48
|
-
out.set(nonce);
|
|
49
|
-
out.set(cipher, nonce.length);
|
|
50
|
-
return out;
|
|
51
|
-
}
|
|
52
|
-
/* ================================
|
|
53
|
-
Decrypt (buffer)
|
|
54
|
-
================================ */
|
|
55
|
-
async function decryptBuffer(box, secret) {
|
|
56
|
-
await init();
|
|
57
|
-
const key = deriveKey(secret);
|
|
58
|
-
const nonceSize = sodium.crypto_secretbox_NONCEBYTES;
|
|
59
|
-
if (box.length <= nonceSize)
|
|
60
|
-
return null;
|
|
61
|
-
const nonce = box.subarray(0, nonceSize);
|
|
62
|
-
const cipher = box.subarray(nonceSize);
|
|
63
|
-
const opened = sodium.crypto_secretbox_open_easy(cipher, nonce, key);
|
|
64
|
-
if (!opened)
|
|
65
|
-
return null;
|
|
66
|
-
return compress.decompressBuffer(opened);
|
|
67
|
-
}
|
|
68
|
-
/* ================================
|
|
69
|
-
Hash (URL-safe, short)
|
|
70
|
-
================================ */
|
|
71
|
-
async function hash(str) {
|
|
72
|
-
await init();
|
|
73
|
-
const digest = sodium.crypto_generichash(32, sodium.from_string(str), null);
|
|
74
|
-
return sodium
|
|
75
|
-
.to_base64(digest, sodium.base64_variants.URLSAFE_NO_PADDING)
|
|
76
|
-
.replace(/[^a-zA-Z0-9]/g, "");
|
|
77
|
-
}
|
|
78
|
-
/* ================================
|
|
79
|
-
Canonical JSON
|
|
80
|
-
================================ */
|
|
81
|
-
function canonicalJSON(value) {
|
|
82
|
-
if (value === null || typeof value !== "object") {
|
|
83
|
-
return JSON.stringify(value);
|
|
84
|
-
}
|
|
85
|
-
if (Array.isArray(value)) {
|
|
86
|
-
return JSON.stringify(value.map(canonicalJSON));
|
|
87
|
-
}
|
|
88
|
-
const keys = Object.keys(value).sort();
|
|
89
|
-
const obj = {};
|
|
90
|
-
for (const k of keys) {
|
|
91
|
-
obj[k] = value[k];
|
|
92
|
-
}
|
|
93
|
-
return JSON.stringify(obj);
|
|
94
|
-
}
|
|
95
|
-
/* ================================
|
|
96
|
-
Create Token
|
|
97
|
-
================================ */
|
|
98
|
-
async function createToken(payload, secret) {
|
|
99
|
-
await init();
|
|
100
|
-
const key = deriveKey(secret);
|
|
101
|
-
const json = canonicalJSON(payload);
|
|
102
|
-
const encryptedPayload = await encrypt(payload, secret);
|
|
103
|
-
const mac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
104
|
-
const macBase64 = sodium.to_base64(mac, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
105
|
-
return `${encryptedPayload}.${macBase64}`;
|
|
106
|
-
}
|
|
107
|
-
/* ================================
|
|
108
|
-
Verify Token
|
|
109
|
-
================================ */
|
|
110
|
-
async function verifyToken(token, secret) {
|
|
111
|
-
await init();
|
|
112
|
-
const parts = token.split(".");
|
|
113
|
-
if (parts.length !== 2)
|
|
114
|
-
return { valid: false };
|
|
115
|
-
const [payloadBase64, macBase64] = parts;
|
|
116
|
-
const payload = await decrypt(payloadBase64, secret);
|
|
117
|
-
if (payload === null)
|
|
118
|
-
return { valid: false };
|
|
119
|
-
const json = canonicalJSON(payload);
|
|
120
|
-
const key = deriveKey(secret);
|
|
121
|
-
const expectedMac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
122
|
-
const mac = sodium.from_base64(macBase64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
123
|
-
if (mac.length !== expectedMac.length ||
|
|
124
|
-
!sodium.memcmp(expectedMac, mac)) {
|
|
125
|
-
return { valid: false };
|
|
126
|
-
}
|
|
127
|
-
return { valid: true, payload };
|
|
128
|
-
}
|
|
129
|
-
const crypto = {
|
|
130
|
-
init,
|
|
131
|
-
encrypt,
|
|
132
|
-
decrypt,
|
|
133
|
-
encryptBuffer,
|
|
134
|
-
decryptBuffer,
|
|
135
|
-
hash,
|
|
136
|
-
createToken,
|
|
137
|
-
verifyToken,
|
|
6
|
+
/* ================================
|
|
7
|
+
Sodium Init (SAFE & IDP)
|
|
8
|
+
================================ */
|
|
9
|
+
let initPromise = null;
|
|
10
|
+
async function init() {
|
|
11
|
+
if (!initPromise) {
|
|
12
|
+
initPromise = sodium.ready.then(() => void 0);
|
|
13
|
+
}
|
|
14
|
+
return initPromise;
|
|
15
|
+
}
|
|
16
|
+
/* ================================
|
|
17
|
+
Key Derivation
|
|
18
|
+
(Stable & deterministic)
|
|
19
|
+
================================ */
|
|
20
|
+
function deriveKey(secret) {
|
|
21
|
+
return sodium.crypto_generichash(sodium.crypto_secretbox_KEYBYTES, sodium.from_string(secret), null);
|
|
22
|
+
}
|
|
23
|
+
/* ================================
|
|
24
|
+
Encrypt (string)
|
|
25
|
+
================================ */
|
|
26
|
+
async function encrypt(input, secret) {
|
|
27
|
+
const buf = await encryptBuffer(input, secret);
|
|
28
|
+
return sodium.to_base64(buf, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
29
|
+
}
|
|
30
|
+
/* ================================
|
|
31
|
+
Decrypt (string)
|
|
32
|
+
================================ */
|
|
33
|
+
async function decrypt(base64, secret) {
|
|
34
|
+
await init();
|
|
35
|
+
const box = sodium.from_base64(base64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
36
|
+
return decryptBuffer(box, secret);
|
|
37
|
+
}
|
|
38
|
+
/* ================================
|
|
39
|
+
Encrypt (buffer)
|
|
40
|
+
================================ */
|
|
41
|
+
async function encryptBuffer(input, secret) {
|
|
42
|
+
await init();
|
|
43
|
+
const key = deriveKey(secret);
|
|
44
|
+
const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
|
|
45
|
+
const compressed = await compress.compressBuffer(input);
|
|
46
|
+
const cipher = sodium.crypto_secretbox_easy(compressed, nonce, key);
|
|
47
|
+
const out = new Uint8Array(nonce.length + cipher.length);
|
|
48
|
+
out.set(nonce);
|
|
49
|
+
out.set(cipher, nonce.length);
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/* ================================
|
|
53
|
+
Decrypt (buffer)
|
|
54
|
+
================================ */
|
|
55
|
+
async function decryptBuffer(box, secret) {
|
|
56
|
+
await init();
|
|
57
|
+
const key = deriveKey(secret);
|
|
58
|
+
const nonceSize = sodium.crypto_secretbox_NONCEBYTES;
|
|
59
|
+
if (box.length <= nonceSize)
|
|
60
|
+
return null;
|
|
61
|
+
const nonce = box.subarray(0, nonceSize);
|
|
62
|
+
const cipher = box.subarray(nonceSize);
|
|
63
|
+
const opened = sodium.crypto_secretbox_open_easy(cipher, nonce, key);
|
|
64
|
+
if (!opened)
|
|
65
|
+
return null;
|
|
66
|
+
return compress.decompressBuffer(opened);
|
|
67
|
+
}
|
|
68
|
+
/* ================================
|
|
69
|
+
Hash (URL-safe, short)
|
|
70
|
+
================================ */
|
|
71
|
+
async function hash(str) {
|
|
72
|
+
await init();
|
|
73
|
+
const digest = sodium.crypto_generichash(32, sodium.from_string(str), null);
|
|
74
|
+
return sodium
|
|
75
|
+
.to_base64(digest, sodium.base64_variants.URLSAFE_NO_PADDING)
|
|
76
|
+
.replace(/[^a-zA-Z0-9]/g, "");
|
|
77
|
+
}
|
|
78
|
+
/* ================================
|
|
79
|
+
Canonical JSON
|
|
80
|
+
================================ */
|
|
81
|
+
function canonicalJSON(value) {
|
|
82
|
+
if (value === null || typeof value !== "object") {
|
|
83
|
+
return JSON.stringify(value);
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
return JSON.stringify(value.map(canonicalJSON));
|
|
87
|
+
}
|
|
88
|
+
const keys = Object.keys(value).sort();
|
|
89
|
+
const obj = {};
|
|
90
|
+
for (const k of keys) {
|
|
91
|
+
obj[k] = value[k];
|
|
92
|
+
}
|
|
93
|
+
return JSON.stringify(obj);
|
|
94
|
+
}
|
|
95
|
+
/* ================================
|
|
96
|
+
Create Token
|
|
97
|
+
================================ */
|
|
98
|
+
async function createToken(payload, secret) {
|
|
99
|
+
await init();
|
|
100
|
+
const key = deriveKey(secret);
|
|
101
|
+
const json = canonicalJSON(payload);
|
|
102
|
+
const encryptedPayload = await encrypt(payload, secret);
|
|
103
|
+
const mac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
104
|
+
const macBase64 = sodium.to_base64(mac, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
105
|
+
return `${encryptedPayload}.${macBase64}`;
|
|
106
|
+
}
|
|
107
|
+
/* ================================
|
|
108
|
+
Verify Token
|
|
109
|
+
================================ */
|
|
110
|
+
async function verifyToken(token, secret) {
|
|
111
|
+
await init();
|
|
112
|
+
const parts = token.split(".");
|
|
113
|
+
if (parts.length !== 2)
|
|
114
|
+
return { valid: false };
|
|
115
|
+
const [payloadBase64, macBase64] = parts;
|
|
116
|
+
const payload = await decrypt(payloadBase64, secret);
|
|
117
|
+
if (payload === null)
|
|
118
|
+
return { valid: false };
|
|
119
|
+
const json = canonicalJSON(payload);
|
|
120
|
+
const key = deriveKey(secret);
|
|
121
|
+
const expectedMac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
122
|
+
const mac = sodium.from_base64(macBase64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
123
|
+
if (mac.length !== expectedMac.length ||
|
|
124
|
+
!sodium.memcmp(expectedMac, mac)) {
|
|
125
|
+
return { valid: false };
|
|
126
|
+
}
|
|
127
|
+
return { valid: true, payload };
|
|
128
|
+
}
|
|
129
|
+
const crypto = {
|
|
130
|
+
init,
|
|
131
|
+
encrypt,
|
|
132
|
+
decrypt,
|
|
133
|
+
encryptBuffer,
|
|
134
|
+
decryptBuffer,
|
|
135
|
+
hash,
|
|
136
|
+
createToken,
|
|
137
|
+
verifyToken,
|
|
138
138
|
};
|
|
139
139
|
|
|
140
140
|
module.exports = crypto;
|
package/include/crypto.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.cjs","sources":["../../src/include/crypto.ts"],"sourcesContent":["import sodium from \"libsodium-wrappers\";\r\nimport compresor from \"./compress\";\r\n\r\n/* ================================\r\n Types\r\n================================ */\r\nexport type EncryptInput = string | object | any[];\r\n\r\n/* ================================\r\n Sodium Init (SAFE & IDP)\r\n================================ */\r\nlet initPromise: Promise<void> | null = null;\r\n\r\nasync function init(): Promise<void> {\r\n if (!initPromise) {\r\n initPromise = sodium.ready.then(() => void 0);\r\n }\r\n return initPromise;\r\n}\r\n\r\n/* ================================\r\n Key Derivation\r\n (Stable & deterministic)\r\n================================ */\r\nfunction deriveKey(secret: string): Uint8Array {\r\n return sodium.crypto_generichash(\r\n sodium.crypto_secretbox_KEYBYTES,\r\n sodium.from_string(secret),\r\n null\r\n ) as Uint8Array\r\n}\r\n\r\n/* ================================\r\n Encrypt (string)\r\n================================ */\r\nasync function encrypt(\r\n input: EncryptInput,\r\n secret: string\r\n): Promise<string> {\r\n const buf = await encryptBuffer(input, secret);\r\n return sodium.to_base64(\r\n buf,\r\n sodium.base64_variants.URLSAFE_NO_PADDING\r\n );\r\n}\r\n\r\n/* ================================\r\n Decrypt (string)\r\n================================ */\r\nasync function decrypt(\r\n base64: string,\r\n secret: string\r\n): Promise<any | null> {\r\n await init();\r\n\r\n const box = sodium.from_base64(\r\n base64,\r\n sodium.base64_variants.URLSAFE_NO_PADDING\r\n );\r\n\r\n return decryptBuffer(box, secret);\r\n}\r\n\r\n/* ================================\r\n Encrypt (buffer)\r\n================================ */\r\nasync function encryptBuffer(\r\n input: EncryptInput,\r\n secret: string\r\n): Promise<Uint8Array> {\r\n await init();\r\n\r\n const key = deriveKey(secret);\r\n const nonce = sodium.randombytes_buf(\r\n sodium.crypto_secretbox_NONCEBYTES\r\n ) as Uint8Array\r\n\r\n\r\n const compressed = await compresor.compressBuffer(input);\r\n\r\n const cipher = sodium.crypto_secretbox_easy(\r\n compressed,\r\n nonce,\r\n key\r\n ) as Uint8Array\r\n\r\n const out = new Uint8Array(nonce.length + cipher.length);\r\n out.set(nonce);\r\n out.set(cipher, nonce.length);\r\n\r\n return out;\r\n}\r\n\r\n/* ================================\r\n Decrypt (buffer)\r\n================================ */\r\nasync function decryptBuffer(\r\n box: Uint8Array,\r\n secret: string\r\n): Promise<any | null> {\r\n await init();\r\n\r\n const key = deriveKey(secret);\r\n const nonceSize = sodium.crypto_secretbox_NONCEBYTES;\r\n\r\n if (box.length <= nonceSize) return null;\r\n\r\n const nonce = box.subarray(0, nonceSize);\r\n const cipher = box.subarray(nonceSize);\r\n\r\n const opened = sodium.crypto_secretbox_open_easy(\r\n cipher,\r\n nonce,\r\n key\r\n ) as Uint8Array\r\n\r\n if (!opened) return null;\r\n\r\n return compresor.decompressBuffer(opened);\r\n}\r\n\r\n/* ================================\r\n Hash (URL-safe, short)\r\n================================ */\r\nasync function hash(str: string): Promise<string> {\r\n await init();\r\n\r\n const digest = sodium.crypto_generichash(\r\n 32,\r\n sodium.from_string(str),\r\n null\r\n );\r\n\r\n return sodium\r\n .to_base64(digest, sodium.base64_variants.URLSAFE_NO_PADDING)\r\n .replace(/[^a-zA-Z0-9]/g, \"\");\r\n}\r\n\r\n/* ================================\r\n Canonical JSON\r\n================================ */\r\nfunction canonicalJSON(value: any): string {\r\n if (value === null || typeof value !== \"object\") {\r\n return JSON.stringify(value);\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return JSON.stringify(value.map(canonicalJSON));\r\n }\r\n\r\n const keys = Object.keys(value).sort();\r\n const obj: any = {};\r\n\r\n for (const k of keys) {\r\n obj[k] = value[k];\r\n }\r\n\r\n return JSON.stringify(obj);\r\n}\r\n\r\n/* ================================\r\n Create Token\r\n================================ */\r\nasync function createToken(\r\n payload: Record<string, any>,\r\n secret: string\r\n): Promise<string> {\r\n await init();\r\n\r\n const key = deriveKey(secret);\r\n const json = canonicalJSON(payload);\r\n\r\n const encryptedPayload = await encrypt(payload, secret);\r\n\r\n const mac = sodium.crypto_generichash(\r\n 32,\r\n sodium.from_string(json),\r\n key\r\n );\r\n\r\n const macBase64 = sodium.to_base64(\r\n mac,\r\n sodium.base64_variants.URLSAFE_NO_PADDING\r\n );\r\n\r\n return `${encryptedPayload}.${macBase64}`;\r\n}\r\n\r\n/* ================================\r\n Verify Token\r\n================================ */\r\nasync function verifyToken(\r\n token: string,\r\n secret: string\r\n): Promise<{ valid: boolean; payload?: any }> {\r\n await init();\r\n\r\n const parts = token.split(\".\");\r\n if (parts.length !== 2) return { valid: false };\r\n\r\n const [payloadBase64, macBase64] = parts;\r\n\r\n const payload = await decrypt(payloadBase64, secret);\r\n if (payload === null) return { valid: false };\r\n\r\n const json = canonicalJSON(payload);\r\n const key = deriveKey(secret);\r\n\r\n const expectedMac = sodium.crypto_generichash(\r\n 32,\r\n sodium.from_string(json),\r\n key\r\n ) as Uint8Array\r\n\r\n const mac = sodium.from_base64(\r\n macBase64,\r\n sodium.base64_variants.URLSAFE_NO_PADDING\r\n );\r\n\r\n if (\r\n mac.length !== expectedMac.length ||\r\n !sodium.memcmp(expectedMac, mac)\r\n ) {\r\n return { valid: false };\r\n }\r\n\r\n return { valid: true, payload };\r\n}\r\n\r\n\r\n\r\nconst crypto = {\r\n init,\r\n encrypt,\r\n decrypt,\r\n encryptBuffer,\r\n decryptBuffer,\r\n hash,\r\n createToken,\r\n verifyToken,\r\n}\r\n\r\nexport default crypto"],"names":["compresor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crypto.cjs","sources":["../../src/include/crypto.ts"],"sourcesContent":["import sodium from \"libsodium-wrappers\";\nimport compresor from \"./compress\";\n\n/* ================================\n Types\n================================ */\nexport type EncryptInput = string | object | any[];\n\n/* ================================\n Sodium Init (SAFE & IDP)\n================================ */\nlet initPromise: Promise<void> | null = null;\n\nasync function init(): Promise<void> {\n if (!initPromise) {\n initPromise = sodium.ready.then(() => void 0);\n }\n return initPromise;\n}\n\n/* ================================\n Key Derivation\n (Stable & deterministic)\n================================ */\nfunction deriveKey(secret: string): Uint8Array {\n return sodium.crypto_generichash(\n sodium.crypto_secretbox_KEYBYTES,\n sodium.from_string(secret),\n null\n ) as Uint8Array\n}\n\n/* ================================\n Encrypt (string)\n================================ */\nasync function encrypt(\n input: EncryptInput,\n secret: string\n): Promise<string> {\n const buf = await encryptBuffer(input, secret);\n return sodium.to_base64(\n buf,\n sodium.base64_variants.URLSAFE_NO_PADDING\n );\n}\n\n/* ================================\n Decrypt (string)\n================================ */\nasync function decrypt(\n base64: string,\n secret: string\n): Promise<any | null> {\n await init();\n\n const box = sodium.from_base64(\n base64,\n sodium.base64_variants.URLSAFE_NO_PADDING\n );\n\n return decryptBuffer(box, secret);\n}\n\n/* ================================\n Encrypt (buffer)\n================================ */\nasync function encryptBuffer(\n input: EncryptInput,\n secret: string\n): Promise<Uint8Array> {\n await init();\n\n const key = deriveKey(secret);\n const nonce = sodium.randombytes_buf(\n sodium.crypto_secretbox_NONCEBYTES\n ) as Uint8Array\n\n\n const compressed = await compresor.compressBuffer(input);\n\n const cipher = sodium.crypto_secretbox_easy(\n compressed,\n nonce,\n key\n ) as Uint8Array\n\n const out = new Uint8Array(nonce.length + cipher.length);\n out.set(nonce);\n out.set(cipher, nonce.length);\n\n return out;\n}\n\n/* ================================\n Decrypt (buffer)\n================================ */\nasync function decryptBuffer(\n box: Uint8Array,\n secret: string\n): Promise<any | null> {\n await init();\n\n const key = deriveKey(secret);\n const nonceSize = sodium.crypto_secretbox_NONCEBYTES;\n\n if (box.length <= nonceSize) return null;\n\n const nonce = box.subarray(0, nonceSize);\n const cipher = box.subarray(nonceSize);\n\n const opened = sodium.crypto_secretbox_open_easy(\n cipher,\n nonce,\n key\n ) as Uint8Array\n\n if (!opened) return null;\n\n return compresor.decompressBuffer(opened);\n}\n\n/* ================================\n Hash (URL-safe, short)\n================================ */\nasync function hash(str: string): Promise<string> {\n await init();\n\n const digest = sodium.crypto_generichash(\n 32,\n sodium.from_string(str),\n null\n );\n\n return sodium\n .to_base64(digest, sodium.base64_variants.URLSAFE_NO_PADDING)\n .replace(/[^a-zA-Z0-9]/g, \"\");\n}\n\n/* ================================\n Canonical JSON\n================================ */\nfunction canonicalJSON(value: any): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return JSON.stringify(value.map(canonicalJSON));\n }\n\n const keys = Object.keys(value).sort();\n const obj: any = {};\n\n for (const k of keys) {\n obj[k] = value[k];\n }\n\n return JSON.stringify(obj);\n}\n\n/* ================================\n Create Token\n================================ */\nasync function createToken(\n payload: Record<string, any>,\n secret: string\n): Promise<string> {\n await init();\n\n const key = deriveKey(secret);\n const json = canonicalJSON(payload);\n\n const encryptedPayload = await encrypt(payload, secret);\n\n const mac = sodium.crypto_generichash(\n 32,\n sodium.from_string(json),\n key\n );\n\n const macBase64 = sodium.to_base64(\n mac,\n sodium.base64_variants.URLSAFE_NO_PADDING\n );\n\n return `${encryptedPayload}.${macBase64}`;\n}\n\n/* ================================\n Verify Token\n================================ */\nasync function verifyToken(\n token: string,\n secret: string\n): Promise<{ valid: boolean; payload?: any }> {\n await init();\n\n const parts = token.split(\".\");\n if (parts.length !== 2) return { valid: false };\n\n const [payloadBase64, macBase64] = parts;\n\n const payload = await decrypt(payloadBase64, secret);\n if (payload === null) return { valid: false };\n\n const json = canonicalJSON(payload);\n const key = deriveKey(secret);\n\n const expectedMac = sodium.crypto_generichash(\n 32,\n sodium.from_string(json),\n key\n ) as Uint8Array\n\n const mac = sodium.from_base64(\n macBase64,\n sodium.base64_variants.URLSAFE_NO_PADDING\n );\n\n if (\n mac.length !== expectedMac.length ||\n !sodium.memcmp(expectedMac, mac)\n ) {\n return { valid: false };\n }\n\n return { valid: true, payload };\n}\n\n\n\nconst crypto = {\n init,\n encrypt,\n decrypt,\n encryptBuffer,\n decryptBuffer,\n hash,\n createToken,\n verifyToken,\n}\n\nexport default crypto"],"names":["compresor"],"mappings":"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"}
|
package/include/crypto.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
type EncryptInput = string | object | any[];
|
|
2
|
-
declare function init(): Promise<void>;
|
|
3
|
-
declare function encrypt(input: EncryptInput, secret: string): Promise<string>;
|
|
4
|
-
declare function decrypt(base64: string, secret: string): Promise<any | null>;
|
|
5
|
-
declare function encryptBuffer(input: EncryptInput, secret: string): Promise<Uint8Array>;
|
|
6
|
-
declare function decryptBuffer(box: Uint8Array, secret: string): Promise<any | null>;
|
|
7
|
-
declare function hash(str: string): Promise<string>;
|
|
8
|
-
declare function createToken(payload: Record<string, any>, secret: string): Promise<string>;
|
|
9
|
-
declare function verifyToken(token: string, secret: string): Promise<{
|
|
10
|
-
valid: boolean;
|
|
11
|
-
payload?: any;
|
|
12
|
-
}>;
|
|
13
|
-
declare const crypto: {
|
|
14
|
-
init: typeof init;
|
|
15
|
-
encrypt: typeof encrypt;
|
|
16
|
-
decrypt: typeof decrypt;
|
|
17
|
-
encryptBuffer: typeof encryptBuffer;
|
|
18
|
-
decryptBuffer: typeof decryptBuffer;
|
|
19
|
-
hash: typeof hash;
|
|
20
|
-
createToken: typeof createToken;
|
|
21
|
-
verifyToken: typeof verifyToken;
|
|
1
|
+
type EncryptInput = string | object | any[];
|
|
2
|
+
declare function init(): Promise<void>;
|
|
3
|
+
declare function encrypt(input: EncryptInput, secret: string): Promise<string>;
|
|
4
|
+
declare function decrypt(base64: string, secret: string): Promise<any | null>;
|
|
5
|
+
declare function encryptBuffer(input: EncryptInput, secret: string): Promise<Uint8Array>;
|
|
6
|
+
declare function decryptBuffer(box: Uint8Array, secret: string): Promise<any | null>;
|
|
7
|
+
declare function hash(str: string): Promise<string>;
|
|
8
|
+
declare function createToken(payload: Record<string, any>, secret: string): Promise<string>;
|
|
9
|
+
declare function verifyToken(token: string, secret: string): Promise<{
|
|
10
|
+
valid: boolean;
|
|
11
|
+
payload?: any;
|
|
12
|
+
}>;
|
|
13
|
+
declare const crypto: {
|
|
14
|
+
init: typeof init;
|
|
15
|
+
encrypt: typeof encrypt;
|
|
16
|
+
decrypt: typeof decrypt;
|
|
17
|
+
encryptBuffer: typeof encryptBuffer;
|
|
18
|
+
decryptBuffer: typeof decryptBuffer;
|
|
19
|
+
hash: typeof hash;
|
|
20
|
+
createToken: typeof createToken;
|
|
21
|
+
verifyToken: typeof verifyToken;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export { crypto as default };
|
package/include/crypto.js
CHANGED
|
@@ -1,138 +1,138 @@
|
|
|
1
1
|
import sodium from 'libsodium-wrappers';
|
|
2
2
|
import compresor from './compress.js';
|
|
3
3
|
|
|
4
|
-
/* ================================
|
|
5
|
-
Sodium Init (SAFE & IDP)
|
|
6
|
-
================================ */
|
|
7
|
-
let initPromise = null;
|
|
8
|
-
async function init() {
|
|
9
|
-
if (!initPromise) {
|
|
10
|
-
initPromise = sodium.ready.then(() => void 0);
|
|
11
|
-
}
|
|
12
|
-
return initPromise;
|
|
13
|
-
}
|
|
14
|
-
/* ================================
|
|
15
|
-
Key Derivation
|
|
16
|
-
(Stable & deterministic)
|
|
17
|
-
================================ */
|
|
18
|
-
function deriveKey(secret) {
|
|
19
|
-
return sodium.crypto_generichash(sodium.crypto_secretbox_KEYBYTES, sodium.from_string(secret), null);
|
|
20
|
-
}
|
|
21
|
-
/* ================================
|
|
22
|
-
Encrypt (string)
|
|
23
|
-
================================ */
|
|
24
|
-
async function encrypt(input, secret) {
|
|
25
|
-
const buf = await encryptBuffer(input, secret);
|
|
26
|
-
return sodium.to_base64(buf, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
27
|
-
}
|
|
28
|
-
/* ================================
|
|
29
|
-
Decrypt (string)
|
|
30
|
-
================================ */
|
|
31
|
-
async function decrypt(base64, secret) {
|
|
32
|
-
await init();
|
|
33
|
-
const box = sodium.from_base64(base64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
34
|
-
return decryptBuffer(box, secret);
|
|
35
|
-
}
|
|
36
|
-
/* ================================
|
|
37
|
-
Encrypt (buffer)
|
|
38
|
-
================================ */
|
|
39
|
-
async function encryptBuffer(input, secret) {
|
|
40
|
-
await init();
|
|
41
|
-
const key = deriveKey(secret);
|
|
42
|
-
const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
|
|
43
|
-
const compressed = await compresor.compressBuffer(input);
|
|
44
|
-
const cipher = sodium.crypto_secretbox_easy(compressed, nonce, key);
|
|
45
|
-
const out = new Uint8Array(nonce.length + cipher.length);
|
|
46
|
-
out.set(nonce);
|
|
47
|
-
out.set(cipher, nonce.length);
|
|
48
|
-
return out;
|
|
49
|
-
}
|
|
50
|
-
/* ================================
|
|
51
|
-
Decrypt (buffer)
|
|
52
|
-
================================ */
|
|
53
|
-
async function decryptBuffer(box, secret) {
|
|
54
|
-
await init();
|
|
55
|
-
const key = deriveKey(secret);
|
|
56
|
-
const nonceSize = sodium.crypto_secretbox_NONCEBYTES;
|
|
57
|
-
if (box.length <= nonceSize)
|
|
58
|
-
return null;
|
|
59
|
-
const nonce = box.subarray(0, nonceSize);
|
|
60
|
-
const cipher = box.subarray(nonceSize);
|
|
61
|
-
const opened = sodium.crypto_secretbox_open_easy(cipher, nonce, key);
|
|
62
|
-
if (!opened)
|
|
63
|
-
return null;
|
|
64
|
-
return compresor.decompressBuffer(opened);
|
|
65
|
-
}
|
|
66
|
-
/* ================================
|
|
67
|
-
Hash (URL-safe, short)
|
|
68
|
-
================================ */
|
|
69
|
-
async function hash(str) {
|
|
70
|
-
await init();
|
|
71
|
-
const digest = sodium.crypto_generichash(32, sodium.from_string(str), null);
|
|
72
|
-
return sodium
|
|
73
|
-
.to_base64(digest, sodium.base64_variants.URLSAFE_NO_PADDING)
|
|
74
|
-
.replace(/[^a-zA-Z0-9]/g, "");
|
|
75
|
-
}
|
|
76
|
-
/* ================================
|
|
77
|
-
Canonical JSON
|
|
78
|
-
================================ */
|
|
79
|
-
function canonicalJSON(value) {
|
|
80
|
-
if (value === null || typeof value !== "object") {
|
|
81
|
-
return JSON.stringify(value);
|
|
82
|
-
}
|
|
83
|
-
if (Array.isArray(value)) {
|
|
84
|
-
return JSON.stringify(value.map(canonicalJSON));
|
|
85
|
-
}
|
|
86
|
-
const keys = Object.keys(value).sort();
|
|
87
|
-
const obj = {};
|
|
88
|
-
for (const k of keys) {
|
|
89
|
-
obj[k] = value[k];
|
|
90
|
-
}
|
|
91
|
-
return JSON.stringify(obj);
|
|
92
|
-
}
|
|
93
|
-
/* ================================
|
|
94
|
-
Create Token
|
|
95
|
-
================================ */
|
|
96
|
-
async function createToken(payload, secret) {
|
|
97
|
-
await init();
|
|
98
|
-
const key = deriveKey(secret);
|
|
99
|
-
const json = canonicalJSON(payload);
|
|
100
|
-
const encryptedPayload = await encrypt(payload, secret);
|
|
101
|
-
const mac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
102
|
-
const macBase64 = sodium.to_base64(mac, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
103
|
-
return `${encryptedPayload}.${macBase64}`;
|
|
104
|
-
}
|
|
105
|
-
/* ================================
|
|
106
|
-
Verify Token
|
|
107
|
-
================================ */
|
|
108
|
-
async function verifyToken(token, secret) {
|
|
109
|
-
await init();
|
|
110
|
-
const parts = token.split(".");
|
|
111
|
-
if (parts.length !== 2)
|
|
112
|
-
return { valid: false };
|
|
113
|
-
const [payloadBase64, macBase64] = parts;
|
|
114
|
-
const payload = await decrypt(payloadBase64, secret);
|
|
115
|
-
if (payload === null)
|
|
116
|
-
return { valid: false };
|
|
117
|
-
const json = canonicalJSON(payload);
|
|
118
|
-
const key = deriveKey(secret);
|
|
119
|
-
const expectedMac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
120
|
-
const mac = sodium.from_base64(macBase64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
121
|
-
if (mac.length !== expectedMac.length ||
|
|
122
|
-
!sodium.memcmp(expectedMac, mac)) {
|
|
123
|
-
return { valid: false };
|
|
124
|
-
}
|
|
125
|
-
return { valid: true, payload };
|
|
126
|
-
}
|
|
127
|
-
const crypto = {
|
|
128
|
-
init,
|
|
129
|
-
encrypt,
|
|
130
|
-
decrypt,
|
|
131
|
-
encryptBuffer,
|
|
132
|
-
decryptBuffer,
|
|
133
|
-
hash,
|
|
134
|
-
createToken,
|
|
135
|
-
verifyToken,
|
|
4
|
+
/* ================================
|
|
5
|
+
Sodium Init (SAFE & IDP)
|
|
6
|
+
================================ */
|
|
7
|
+
let initPromise = null;
|
|
8
|
+
async function init() {
|
|
9
|
+
if (!initPromise) {
|
|
10
|
+
initPromise = sodium.ready.then(() => void 0);
|
|
11
|
+
}
|
|
12
|
+
return initPromise;
|
|
13
|
+
}
|
|
14
|
+
/* ================================
|
|
15
|
+
Key Derivation
|
|
16
|
+
(Stable & deterministic)
|
|
17
|
+
================================ */
|
|
18
|
+
function deriveKey(secret) {
|
|
19
|
+
return sodium.crypto_generichash(sodium.crypto_secretbox_KEYBYTES, sodium.from_string(secret), null);
|
|
20
|
+
}
|
|
21
|
+
/* ================================
|
|
22
|
+
Encrypt (string)
|
|
23
|
+
================================ */
|
|
24
|
+
async function encrypt(input, secret) {
|
|
25
|
+
const buf = await encryptBuffer(input, secret);
|
|
26
|
+
return sodium.to_base64(buf, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
27
|
+
}
|
|
28
|
+
/* ================================
|
|
29
|
+
Decrypt (string)
|
|
30
|
+
================================ */
|
|
31
|
+
async function decrypt(base64, secret) {
|
|
32
|
+
await init();
|
|
33
|
+
const box = sodium.from_base64(base64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
34
|
+
return decryptBuffer(box, secret);
|
|
35
|
+
}
|
|
36
|
+
/* ================================
|
|
37
|
+
Encrypt (buffer)
|
|
38
|
+
================================ */
|
|
39
|
+
async function encryptBuffer(input, secret) {
|
|
40
|
+
await init();
|
|
41
|
+
const key = deriveKey(secret);
|
|
42
|
+
const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
|
|
43
|
+
const compressed = await compresor.compressBuffer(input);
|
|
44
|
+
const cipher = sodium.crypto_secretbox_easy(compressed, nonce, key);
|
|
45
|
+
const out = new Uint8Array(nonce.length + cipher.length);
|
|
46
|
+
out.set(nonce);
|
|
47
|
+
out.set(cipher, nonce.length);
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/* ================================
|
|
51
|
+
Decrypt (buffer)
|
|
52
|
+
================================ */
|
|
53
|
+
async function decryptBuffer(box, secret) {
|
|
54
|
+
await init();
|
|
55
|
+
const key = deriveKey(secret);
|
|
56
|
+
const nonceSize = sodium.crypto_secretbox_NONCEBYTES;
|
|
57
|
+
if (box.length <= nonceSize)
|
|
58
|
+
return null;
|
|
59
|
+
const nonce = box.subarray(0, nonceSize);
|
|
60
|
+
const cipher = box.subarray(nonceSize);
|
|
61
|
+
const opened = sodium.crypto_secretbox_open_easy(cipher, nonce, key);
|
|
62
|
+
if (!opened)
|
|
63
|
+
return null;
|
|
64
|
+
return compresor.decompressBuffer(opened);
|
|
65
|
+
}
|
|
66
|
+
/* ================================
|
|
67
|
+
Hash (URL-safe, short)
|
|
68
|
+
================================ */
|
|
69
|
+
async function hash(str) {
|
|
70
|
+
await init();
|
|
71
|
+
const digest = sodium.crypto_generichash(32, sodium.from_string(str), null);
|
|
72
|
+
return sodium
|
|
73
|
+
.to_base64(digest, sodium.base64_variants.URLSAFE_NO_PADDING)
|
|
74
|
+
.replace(/[^a-zA-Z0-9]/g, "");
|
|
75
|
+
}
|
|
76
|
+
/* ================================
|
|
77
|
+
Canonical JSON
|
|
78
|
+
================================ */
|
|
79
|
+
function canonicalJSON(value) {
|
|
80
|
+
if (value === null || typeof value !== "object") {
|
|
81
|
+
return JSON.stringify(value);
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
return JSON.stringify(value.map(canonicalJSON));
|
|
85
|
+
}
|
|
86
|
+
const keys = Object.keys(value).sort();
|
|
87
|
+
const obj = {};
|
|
88
|
+
for (const k of keys) {
|
|
89
|
+
obj[k] = value[k];
|
|
90
|
+
}
|
|
91
|
+
return JSON.stringify(obj);
|
|
92
|
+
}
|
|
93
|
+
/* ================================
|
|
94
|
+
Create Token
|
|
95
|
+
================================ */
|
|
96
|
+
async function createToken(payload, secret) {
|
|
97
|
+
await init();
|
|
98
|
+
const key = deriveKey(secret);
|
|
99
|
+
const json = canonicalJSON(payload);
|
|
100
|
+
const encryptedPayload = await encrypt(payload, secret);
|
|
101
|
+
const mac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
102
|
+
const macBase64 = sodium.to_base64(mac, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
103
|
+
return `${encryptedPayload}.${macBase64}`;
|
|
104
|
+
}
|
|
105
|
+
/* ================================
|
|
106
|
+
Verify Token
|
|
107
|
+
================================ */
|
|
108
|
+
async function verifyToken(token, secret) {
|
|
109
|
+
await init();
|
|
110
|
+
const parts = token.split(".");
|
|
111
|
+
if (parts.length !== 2)
|
|
112
|
+
return { valid: false };
|
|
113
|
+
const [payloadBase64, macBase64] = parts;
|
|
114
|
+
const payload = await decrypt(payloadBase64, secret);
|
|
115
|
+
if (payload === null)
|
|
116
|
+
return { valid: false };
|
|
117
|
+
const json = canonicalJSON(payload);
|
|
118
|
+
const key = deriveKey(secret);
|
|
119
|
+
const expectedMac = sodium.crypto_generichash(32, sodium.from_string(json), key);
|
|
120
|
+
const mac = sodium.from_base64(macBase64, sodium.base64_variants.URLSAFE_NO_PADDING);
|
|
121
|
+
if (mac.length !== expectedMac.length ||
|
|
122
|
+
!sodium.memcmp(expectedMac, mac)) {
|
|
123
|
+
return { valid: false };
|
|
124
|
+
}
|
|
125
|
+
return { valid: true, payload };
|
|
126
|
+
}
|
|
127
|
+
const crypto = {
|
|
128
|
+
init,
|
|
129
|
+
encrypt,
|
|
130
|
+
decrypt,
|
|
131
|
+
encryptBuffer,
|
|
132
|
+
decryptBuffer,
|
|
133
|
+
hash,
|
|
134
|
+
createToken,
|
|
135
|
+
verifyToken,
|
|
136
136
|
};
|
|
137
137
|
|
|
138
138
|
export { crypto as default };
|