cipher-kit 2.1.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +324 -434
- package/dist/chunk-3A4RTUKO.cjs +509 -0
- package/dist/chunk-3A4RTUKO.cjs.map +1 -0
- package/dist/chunk-7254PEID.cjs +502 -0
- package/dist/chunk-7254PEID.cjs.map +1 -0
- package/dist/chunk-GL32EZRA.js +475 -0
- package/dist/chunk-GL32EZRA.js.map +1 -0
- package/dist/chunk-IY6XGUYO.js +494 -0
- package/dist/chunk-IY6XGUYO.js.map +1 -0
- package/dist/chunk-VCBHSRCS.cjs +523 -0
- package/dist/chunk-VCBHSRCS.cjs.map +1 -0
- package/dist/chunk-X6MX4NDE.js +478 -0
- package/dist/chunk-X6MX4NDE.js.map +1 -0
- package/dist/export-B-3CCZIO.d.cts +389 -0
- package/dist/export-BPo6yPV-.d.ts +389 -0
- package/dist/export-C0_UEEg8.d.ts +396 -0
- package/dist/export-DPuocAr3.d.cts +396 -0
- package/dist/index.cjs +11 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -40
- package/dist/index.d.ts +11 -40
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +39 -35
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +2 -2
- package/dist/validate-vDTesb-X.d.cts +195 -0
- package/dist/validate-vDTesb-X.d.ts +195 -0
- package/dist/web-api.cjs +39 -35
- package/dist/web-api.d.cts +2 -3
- package/dist/web-api.d.ts +2 -3
- package/dist/web-api.js +2 -2
- package/package.json +82 -92
- package/dist/chunk-BMX42IZM.cjs +0 -623
- package/dist/chunk-BMX42IZM.cjs.map +0 -1
- package/dist/chunk-HTRGOBZF.cjs +0 -169
- package/dist/chunk-HTRGOBZF.cjs.map +0 -1
- package/dist/chunk-LU7QOSQH.js +0 -141
- package/dist/chunk-LU7QOSQH.js.map +0 -1
- package/dist/chunk-S6SNCTU6.js +0 -485
- package/dist/chunk-S6SNCTU6.js.map +0 -1
- package/dist/chunk-T36BEDPY.js +0 -598
- package/dist/chunk-T36BEDPY.js.map +0 -1
- package/dist/chunk-ZNM5M6RD.cjs +0 -514
- package/dist/chunk-ZNM5M6RD.cjs.map +0 -1
- package/dist/export-BaM_OTFk.d.ts +0 -573
- package/dist/export-CCTGAosO.d.ts +0 -572
- package/dist/export-FYHgb-8E.d.cts +0 -572
- package/dist/export-KFT0YyMg.d.cts +0 -573
- package/dist/validate-lkJAHCeJ.d.cts +0 -399
- package/dist/validate-lkJAHCeJ.d.ts +0 -399
package/dist/chunk-BMX42IZM.cjs
DELETED
|
@@ -1,623 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkHTRGOBZF_cjs = require('./chunk-HTRGOBZF.cjs');
|
|
4
|
-
|
|
5
|
-
// src/web/kit.ts
|
|
6
|
-
var kit_exports = {};
|
|
7
|
-
chunkHTRGOBZF_cjs.__export(kit_exports, {
|
|
8
|
-
convertBytesToStr: () => convertBytesToStr,
|
|
9
|
-
convertEncoding: () => convertEncoding,
|
|
10
|
-
convertStrToBytes: () => convertStrToBytes,
|
|
11
|
-
createSecretKey: () => createSecretKey,
|
|
12
|
-
decrypt: () => decrypt,
|
|
13
|
-
decryptObj: () => decryptObj,
|
|
14
|
-
encrypt: () => encrypt,
|
|
15
|
-
encryptObj: () => encryptObj,
|
|
16
|
-
generateUuid: () => generateUuid,
|
|
17
|
-
hash: () => hash,
|
|
18
|
-
hashPassword: () => hashPassword,
|
|
19
|
-
tryConvertBytesToStr: () => tryConvertBytesToStr,
|
|
20
|
-
tryConvertEncoding: () => tryConvertEncoding,
|
|
21
|
-
tryConvertStrToBytes: () => tryConvertStrToBytes,
|
|
22
|
-
tryCreateSecretKey: () => tryCreateSecretKey,
|
|
23
|
-
tryDecrypt: () => tryDecrypt,
|
|
24
|
-
tryDecryptObj: () => tryDecryptObj,
|
|
25
|
-
tryEncrypt: () => tryEncrypt,
|
|
26
|
-
tryEncryptObj: () => tryEncryptObj,
|
|
27
|
-
tryGenerateUuid: () => tryGenerateUuid,
|
|
28
|
-
tryHash: () => tryHash,
|
|
29
|
-
tryHashPassword: () => tryHashPassword,
|
|
30
|
-
verifyPassword: () => verifyPassword
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// src/web/web-encode.ts
|
|
34
|
-
var textEncoder = new TextEncoder();
|
|
35
|
-
var textDecoder = new TextDecoder();
|
|
36
|
-
function $convertStrToBytes(data, inputEncoding = "utf8") {
|
|
37
|
-
if (!chunkHTRGOBZF_cjs.$isStr(data)) {
|
|
38
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
39
|
-
msg: "Crypto Web API - String to Bytes: Empty data",
|
|
40
|
-
desc: "Data must be a non-empty string"
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
if (!chunkHTRGOBZF_cjs.ENCODING.includes(inputEncoding)) {
|
|
44
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
45
|
-
msg: `Crypto Web API - String to Bytes: Unsupported encoding: ${inputEncoding}`,
|
|
46
|
-
desc: "Use base64, base64url, hex, utf8, or latin1"
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
const bytes = strToBytes[inputEncoding](data);
|
|
51
|
-
return chunkHTRGOBZF_cjs.$ok({ result: bytes });
|
|
52
|
-
} catch (error) {
|
|
53
|
-
return chunkHTRGOBZF_cjs.$err({ msg: "Crypto Web API - String to Bytes: Failed to convert data", desc: chunkHTRGOBZF_cjs.$fmtError(error) });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function $convertBytesToStr(data, outputEncoding = "utf8") {
|
|
57
|
-
if (!(data instanceof ArrayBuffer || data instanceof Uint8Array)) {
|
|
58
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
59
|
-
msg: "Crypto Web API - Bytes to String: Invalid data type",
|
|
60
|
-
desc: "Data must be an ArrayBuffer or Uint8Array"
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
if (!chunkHTRGOBZF_cjs.ENCODING.includes(outputEncoding)) {
|
|
64
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
65
|
-
msg: `Crypto Web API - Bytes to String: Unsupported encoding: ${outputEncoding}`,
|
|
66
|
-
desc: "Use base64, base64url, hex, utf8, or latin1"
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
71
|
-
const str = bytesToStr[outputEncoding](bytes);
|
|
72
|
-
return chunkHTRGOBZF_cjs.$ok(str);
|
|
73
|
-
} catch (error) {
|
|
74
|
-
return chunkHTRGOBZF_cjs.$err({ msg: "Crypto Web API - Bytes to String: Failed to convert data", desc: chunkHTRGOBZF_cjs.$fmtError(error) });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
function $convertEncoding(data, from, to) {
|
|
78
|
-
if (!chunkHTRGOBZF_cjs.$isStr(data)) {
|
|
79
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
80
|
-
msg: "Crypto Web API - Convert Format: Empty data",
|
|
81
|
-
desc: "Data must be a non-empty string"
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
if (!chunkHTRGOBZF_cjs.ENCODING.includes(from) || !chunkHTRGOBZF_cjs.ENCODING.includes(to)) {
|
|
85
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
86
|
-
msg: `Crypto Web API - Convert Format: Unsupported encoding: from ${from} to ${to}`,
|
|
87
|
-
desc: "Use base64, base64url, hex, utf8, or latin1"
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
const bytes = $convertStrToBytes(data, from);
|
|
91
|
-
if (bytes.error) return chunkHTRGOBZF_cjs.$err({ msg: bytes.error.message, desc: bytes.error.description });
|
|
92
|
-
const str = $convertBytesToStr(bytes.result, to);
|
|
93
|
-
if (str.error) return chunkHTRGOBZF_cjs.$err({ msg: str.error.message, desc: str.error.description });
|
|
94
|
-
return chunkHTRGOBZF_cjs.$ok({ result: str.result });
|
|
95
|
-
}
|
|
96
|
-
var strToBytes = {
|
|
97
|
-
base64: $fromBase64,
|
|
98
|
-
base64url: $fromBase64Url,
|
|
99
|
-
hex: $fromHex,
|
|
100
|
-
latin1: $fromLatin1,
|
|
101
|
-
utf8: (data) => textEncoder.encode(data)
|
|
102
|
-
};
|
|
103
|
-
var bytesToStr = {
|
|
104
|
-
base64: $toBase64,
|
|
105
|
-
base64url: $toBase64Url,
|
|
106
|
-
hex: $toHex,
|
|
107
|
-
latin1: $toLatin1,
|
|
108
|
-
utf8: (data) => textDecoder.decode(data)
|
|
109
|
-
};
|
|
110
|
-
function $toLatin1(bytes) {
|
|
111
|
-
let out = "";
|
|
112
|
-
const chunk = 1 << 15;
|
|
113
|
-
for (let i = 0; i < bytes.length; i += chunk) {
|
|
114
|
-
out += String.fromCharCode(...bytes.subarray(i, i + chunk));
|
|
115
|
-
}
|
|
116
|
-
return out;
|
|
117
|
-
}
|
|
118
|
-
function $fromLatin1(data) {
|
|
119
|
-
const out = new Uint8Array(data.length);
|
|
120
|
-
for (let i = 0; i < data.length; i++) {
|
|
121
|
-
const charCode = data.charCodeAt(i);
|
|
122
|
-
if (charCode > 255) throw new Error("Invalid latin1 string");
|
|
123
|
-
out[i] = charCode;
|
|
124
|
-
}
|
|
125
|
-
return out;
|
|
126
|
-
}
|
|
127
|
-
function $toBase64(bytes) {
|
|
128
|
-
return btoa($toLatin1(bytes));
|
|
129
|
-
}
|
|
130
|
-
function $fromBase64(data) {
|
|
131
|
-
return $fromLatin1(atob(data));
|
|
132
|
-
}
|
|
133
|
-
function $toBase64Url(bytes) {
|
|
134
|
-
return $toBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
135
|
-
}
|
|
136
|
-
function $fromBase64Url(data) {
|
|
137
|
-
let base64 = data.replace(/-/g, "+").replace(/_/g, "/");
|
|
138
|
-
const padLen = (4 - base64.length % 4) % 4;
|
|
139
|
-
base64 += "=".repeat(padLen);
|
|
140
|
-
return $fromBase64(base64);
|
|
141
|
-
}
|
|
142
|
-
function $toHex(bytes) {
|
|
143
|
-
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
144
|
-
}
|
|
145
|
-
function $fromHex(data) {
|
|
146
|
-
const clean = data.startsWith("0x") ? data.slice(2) : data;
|
|
147
|
-
if (clean.length % 2 !== 0) throw new Error("Invalid hex string");
|
|
148
|
-
const out = new Uint8Array(clean.length / 2);
|
|
149
|
-
for (let i = 0; i < out.length; i++) {
|
|
150
|
-
const byte = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
151
|
-
if (Number.isNaN(byte)) throw new Error("Invalid hex string");
|
|
152
|
-
out[i] = byte;
|
|
153
|
-
}
|
|
154
|
-
return out;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// src/web/web-encrypt.ts
|
|
158
|
-
function $generateUuid() {
|
|
159
|
-
try {
|
|
160
|
-
return chunkHTRGOBZF_cjs.$ok(crypto.randomUUID());
|
|
161
|
-
} catch (error) {
|
|
162
|
-
return chunkHTRGOBZF_cjs.$err({ msg: `${chunkHTRGOBZF_cjs.title("web", "UUID Generation")}: Failed to generate UUID`, desc: chunkHTRGOBZF_cjs.$fmtError(error) });
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
async function $createSecretKey(secret, options) {
|
|
166
|
-
if (!chunkHTRGOBZF_cjs.$isStr(secret, 8)) {
|
|
167
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
168
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Empty Secret`,
|
|
169
|
-
desc: "Secret must be a non-empty string with at least 8 characters"
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
if (!chunkHTRGOBZF_cjs.$isPlainObj(options)) {
|
|
173
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
174
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Invalid options`,
|
|
175
|
-
desc: "Options must be an object"
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
const algorithm = options.algorithm ?? "aes256gcm";
|
|
179
|
-
if (!(algorithm in chunkHTRGOBZF_cjs.ENCRYPTION_ALGORITHMS)) {
|
|
180
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
181
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Unsupported algorithm: ${algorithm}`,
|
|
182
|
-
desc: `Supported algorithms are: ${Object.keys(chunkHTRGOBZF_cjs.ENCRYPTION_ALGORITHMS).join(", ")}`
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
const digest = options.digest ?? "sha256";
|
|
186
|
-
if (!(digest in chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS)) {
|
|
187
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
188
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Unsupported digest: ${digest}`,
|
|
189
|
-
desc: `Supported digests are: ${Object.keys(chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS).join(", ")}`
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
const salt = options.salt ?? "cipher-kit-salt";
|
|
193
|
-
if (!chunkHTRGOBZF_cjs.$isStr(salt, 8)) {
|
|
194
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
195
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Weak salt`,
|
|
196
|
-
desc: "Salt must be a non-empty string with at least 8 characters"
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
const info = options.info ?? "cipher-kit";
|
|
200
|
-
if (!chunkHTRGOBZF_cjs.$isStr(info)) {
|
|
201
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
202
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Invalid info`,
|
|
203
|
-
desc: "Info must be a non-empty string"
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
const encryptAlgo = chunkHTRGOBZF_cjs.ENCRYPTION_ALGORITHMS[algorithm];
|
|
207
|
-
const digestAlgo = chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS[digest];
|
|
208
|
-
try {
|
|
209
|
-
const ikm = await crypto.subtle.importKey("raw", textEncoder.encode(secret.normalize("NFKC")), "HKDF", false, [
|
|
210
|
-
"deriveKey"
|
|
211
|
-
]);
|
|
212
|
-
const key = await crypto.subtle.deriveKey(
|
|
213
|
-
{
|
|
214
|
-
name: "HKDF",
|
|
215
|
-
hash: digestAlgo.web,
|
|
216
|
-
salt: textEncoder.encode(salt.normalize("NFKC")),
|
|
217
|
-
info: textEncoder.encode(info.normalize("NFKC"))
|
|
218
|
-
},
|
|
219
|
-
ikm,
|
|
220
|
-
{ name: encryptAlgo.web, length: encryptAlgo.keyBytes * 8 },
|
|
221
|
-
true,
|
|
222
|
-
["encrypt", "decrypt"]
|
|
223
|
-
);
|
|
224
|
-
const secretKey = Object.freeze({
|
|
225
|
-
platform: "web",
|
|
226
|
-
digest,
|
|
227
|
-
algorithm,
|
|
228
|
-
key
|
|
229
|
-
});
|
|
230
|
-
return chunkHTRGOBZF_cjs.$ok({ result: secretKey });
|
|
231
|
-
} catch (error) {
|
|
232
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
233
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Key Generation")}: Failed to create secret key`,
|
|
234
|
-
desc: chunkHTRGOBZF_cjs.$fmtError(error)
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
async function $encrypt(data, secretKey, options) {
|
|
239
|
-
if (!chunkHTRGOBZF_cjs.$isStr(data)) {
|
|
240
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
241
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Encryption")}: Empty data for encryption`,
|
|
242
|
-
desc: "Data must be a non-empty string"
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
if (!chunkHTRGOBZF_cjs.$isPlainObj(options)) {
|
|
246
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
247
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Encryption")}: Invalid options`,
|
|
248
|
-
desc: "Options must be an object"
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
const outputEncoding = options.outputEncoding ?? "base64url";
|
|
252
|
-
if (!chunkHTRGOBZF_cjs.CIPHER_ENCODING.includes(outputEncoding)) {
|
|
253
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
254
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Encryption")}: Unsupported output encoding: ${outputEncoding}`,
|
|
255
|
-
desc: "Use base64, base64url, or hex"
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
const injectedKey = chunkHTRGOBZF_cjs.$isSecretKey(secretKey, "web");
|
|
259
|
-
if (!injectedKey) {
|
|
260
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
261
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Encryption")}: Invalid Secret Key`,
|
|
262
|
-
desc: "Expected a Web SecretKey"
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
const { result, error } = $convertStrToBytes(data, "utf8");
|
|
266
|
-
if (error) return chunkHTRGOBZF_cjs.$err(error);
|
|
267
|
-
try {
|
|
268
|
-
const iv = crypto.getRandomValues(new Uint8Array(injectedKey.injected.ivLength));
|
|
269
|
-
const cipherWithTag = await crypto.subtle.encrypt(
|
|
270
|
-
{ name: injectedKey.injected.web, iv },
|
|
271
|
-
injectedKey.key,
|
|
272
|
-
result
|
|
273
|
-
);
|
|
274
|
-
const ivStr = $convertBytesToStr(iv, outputEncoding);
|
|
275
|
-
const cipherStr = $convertBytesToStr(cipherWithTag, outputEncoding);
|
|
276
|
-
if (ivStr.error || cipherStr.error) {
|
|
277
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
278
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Encryption")}: Failed to convert IV or encrypted data`,
|
|
279
|
-
desc: `Conversion error: ${chunkHTRGOBZF_cjs.$fmtResultErr(ivStr.error || cipherStr.error)}`
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
return chunkHTRGOBZF_cjs.$ok(`${ivStr.result}.${cipherStr.result}.`);
|
|
283
|
-
} catch (error2) {
|
|
284
|
-
return chunkHTRGOBZF_cjs.$err({ msg: `${chunkHTRGOBZF_cjs.title("web", "Encryption")}: Failed to encrypt data`, desc: chunkHTRGOBZF_cjs.$fmtError(error2) });
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
async function $decrypt(encrypted, secretKey, options) {
|
|
288
|
-
if (!chunkHTRGOBZF_cjs.matchEncryptedPattern(encrypted, "web")) {
|
|
289
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
290
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Invalid encrypted data format`,
|
|
291
|
-
desc: 'Encrypted data must be in the format "iv.cipherWithTag."'
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
if (!chunkHTRGOBZF_cjs.$isPlainObj(options)) {
|
|
295
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
296
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Invalid options`,
|
|
297
|
-
desc: "Options must be an object"
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
const inputEncoding = options.inputEncoding ?? "base64url";
|
|
301
|
-
if (!chunkHTRGOBZF_cjs.CIPHER_ENCODING.includes(inputEncoding)) {
|
|
302
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
303
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Unsupported input encoding: ${inputEncoding}`,
|
|
304
|
-
desc: "Use base64, base64url, or hex"
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
const [iv, encryptedWithTag] = encrypted.split(".", 3);
|
|
308
|
-
if (!chunkHTRGOBZF_cjs.$isStr(iv) || !chunkHTRGOBZF_cjs.$isStr(encryptedWithTag)) {
|
|
309
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
310
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Invalid encrypted data`,
|
|
311
|
-
desc: "Encrypted data must contain valid IV, encrypted and tag components"
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
const injectedKey = chunkHTRGOBZF_cjs.$isSecretKey(secretKey, "web");
|
|
315
|
-
if (!injectedKey) {
|
|
316
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
317
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Invalid Secret Key`,
|
|
318
|
-
desc: "Expected a Web SecretKey"
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
const ivBytes = $convertStrToBytes(iv, inputEncoding);
|
|
322
|
-
const cipherWithTagBytes = $convertStrToBytes(encryptedWithTag, inputEncoding);
|
|
323
|
-
if (ivBytes.error || cipherWithTagBytes.error) {
|
|
324
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
325
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Failed to convert IV or encrypted data`,
|
|
326
|
-
desc: `Conversion error: ${chunkHTRGOBZF_cjs.$fmtResultErr(ivBytes.error || cipherWithTagBytes.error)}`
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
try {
|
|
330
|
-
const decrypted = await crypto.subtle.decrypt(
|
|
331
|
-
{ name: injectedKey.injected.web, iv: ivBytes.result },
|
|
332
|
-
injectedKey.key,
|
|
333
|
-
cipherWithTagBytes.result
|
|
334
|
-
);
|
|
335
|
-
return $convertBytesToStr(decrypted, "utf8");
|
|
336
|
-
} catch (error) {
|
|
337
|
-
return chunkHTRGOBZF_cjs.$err({ msg: `${chunkHTRGOBZF_cjs.title("web", "Decryption")}: Failed to decrypt data`, desc: chunkHTRGOBZF_cjs.$fmtError(error) });
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
async function $encryptObj(data, secretKey, options) {
|
|
341
|
-
const { result, error } = chunkHTRGOBZF_cjs.$stringifyObj(data);
|
|
342
|
-
if (error) return chunkHTRGOBZF_cjs.$err(error);
|
|
343
|
-
return await $encrypt(result, secretKey, options);
|
|
344
|
-
}
|
|
345
|
-
async function $decryptObj(encrypted, secretKey, options) {
|
|
346
|
-
const { result, error } = await $decrypt(encrypted, secretKey, options);
|
|
347
|
-
if (error) return chunkHTRGOBZF_cjs.$err(error);
|
|
348
|
-
return chunkHTRGOBZF_cjs.$parseToObj(result);
|
|
349
|
-
}
|
|
350
|
-
async function $hash(data, options) {
|
|
351
|
-
if (!chunkHTRGOBZF_cjs.$isStr(data)) {
|
|
352
|
-
return chunkHTRGOBZF_cjs.$err({ msg: `${chunkHTRGOBZF_cjs.title("web", "Hashing")}: Empty data for hashing`, desc: "Data must be a non-empty string" });
|
|
353
|
-
}
|
|
354
|
-
if (!chunkHTRGOBZF_cjs.$isPlainObj(options)) {
|
|
355
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
356
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Hashing")}: Invalid options`,
|
|
357
|
-
desc: "Options must be an object"
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
const outputEncoding = options.outputEncoding ?? "base64url";
|
|
361
|
-
if (!chunkHTRGOBZF_cjs.CIPHER_ENCODING.includes(outputEncoding)) {
|
|
362
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
363
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Hashing")}: Unsupported output encoding: ${outputEncoding}`,
|
|
364
|
-
desc: "Use base64, base64url, or hex"
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
const digest = options.digest ?? "sha256";
|
|
368
|
-
if (!(digest in chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS)) {
|
|
369
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
370
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Hashing")}: Unsupported digest: ${digest}`,
|
|
371
|
-
desc: `Supported digests are: ${Object.keys(chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS).join(", ")}`
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
const digestAlgo = chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS[digest];
|
|
375
|
-
const { result, error } = $convertStrToBytes(data, "utf8");
|
|
376
|
-
if (error) return chunkHTRGOBZF_cjs.$err(error);
|
|
377
|
-
try {
|
|
378
|
-
const hashed = await crypto.subtle.digest(digestAlgo.web, result);
|
|
379
|
-
return $convertBytesToStr(hashed, outputEncoding);
|
|
380
|
-
} catch (error2) {
|
|
381
|
-
return chunkHTRGOBZF_cjs.$err({ msg: `${chunkHTRGOBZF_cjs.title("web", "Hashing")}: Failed to hash data`, desc: chunkHTRGOBZF_cjs.$fmtError(error2) });
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
async function $hashPassword(password, options) {
|
|
385
|
-
if (!chunkHTRGOBZF_cjs.$isStr(password)) {
|
|
386
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
387
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Empty password`,
|
|
388
|
-
desc: "Password must be a non-empty string"
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
if (!chunkHTRGOBZF_cjs.$isPlainObj(options)) {
|
|
392
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
393
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Invalid options`,
|
|
394
|
-
desc: "Options must be an object"
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
const digest = options.digest ?? "sha512";
|
|
398
|
-
if (!(digest in chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS)) {
|
|
399
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
400
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Unsupported digest: ${digest}`,
|
|
401
|
-
desc: `Supported digests are: ${Object.keys(chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS).join(", ")}`
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
const digestAlgo = chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS[digest];
|
|
405
|
-
const outputEncoding = options.outputEncoding ?? "base64url";
|
|
406
|
-
if (!chunkHTRGOBZF_cjs.CIPHER_ENCODING.includes(outputEncoding)) {
|
|
407
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
408
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Unsupported output encoding: ${outputEncoding}`,
|
|
409
|
-
desc: "Use base64, base64url, or hex"
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
const saltLength = options.saltLength ?? 16;
|
|
413
|
-
if (typeof saltLength !== "number" || saltLength < 8) {
|
|
414
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
415
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Weak salt length`,
|
|
416
|
-
desc: "Salt length must be a number and at least 8 bytes (recommended 16)"
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
const iterations = options.iterations ?? 32e4;
|
|
420
|
-
if (typeof iterations !== "number" || iterations < 1e3) {
|
|
421
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
422
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Weak iteration count`,
|
|
423
|
-
desc: "Iterations must be a number and at least 1000 (recommended 320,000 or more)"
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
const keyLength = options.keyLength ?? 64;
|
|
427
|
-
if (typeof keyLength !== "number" || keyLength < 16) {
|
|
428
|
-
return chunkHTRGOBZF_cjs.$err({
|
|
429
|
-
msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Weak key length`,
|
|
430
|
-
desc: "Key length must be a number and at least 16 bytes (recommended 64)"
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
try {
|
|
434
|
-
const salt = crypto.getRandomValues(new Uint8Array(saltLength));
|
|
435
|
-
const baseKey = await crypto.subtle.importKey(
|
|
436
|
-
"raw",
|
|
437
|
-
textEncoder.encode(password.normalize("NFKC")),
|
|
438
|
-
"PBKDF2",
|
|
439
|
-
false,
|
|
440
|
-
["deriveBits"]
|
|
441
|
-
);
|
|
442
|
-
const bits = await crypto.subtle.deriveBits(
|
|
443
|
-
{ name: "PBKDF2", salt, iterations, hash: digestAlgo.web },
|
|
444
|
-
baseKey,
|
|
445
|
-
keyLength * 8
|
|
446
|
-
);
|
|
447
|
-
const saltStr = $convertBytesToStr(salt, outputEncoding);
|
|
448
|
-
if (saltStr.error) return chunkHTRGOBZF_cjs.$err(saltStr.error);
|
|
449
|
-
const hashedPasswordStr = $convertBytesToStr(bits, outputEncoding);
|
|
450
|
-
if (hashedPasswordStr.error) return chunkHTRGOBZF_cjs.$err(hashedPasswordStr.error);
|
|
451
|
-
return chunkHTRGOBZF_cjs.$ok({ result: hashedPasswordStr.result, salt: saltStr.result });
|
|
452
|
-
} catch (error) {
|
|
453
|
-
return chunkHTRGOBZF_cjs.$err({ msg: `${chunkHTRGOBZF_cjs.title("web", "Password Hashing")}: Failed to hash password`, desc: chunkHTRGOBZF_cjs.$fmtError(error) });
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
async function $verifyPassword(password, hashedPassword, salt, options) {
|
|
457
|
-
if (!chunkHTRGOBZF_cjs.$isStr(password) || !chunkHTRGOBZF_cjs.$isStr(hashedPassword) || !chunkHTRGOBZF_cjs.$isStr(salt) || !chunkHTRGOBZF_cjs.$isPlainObj(options)) {
|
|
458
|
-
return false;
|
|
459
|
-
}
|
|
460
|
-
const digest = options.digest ?? "sha512";
|
|
461
|
-
if (!(digest in chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS)) return false;
|
|
462
|
-
const digestAlgo = chunkHTRGOBZF_cjs.DIGEST_ALGORITHMS[digest];
|
|
463
|
-
const inputEncoding = options.inputEncoding ?? "base64url";
|
|
464
|
-
if (!chunkHTRGOBZF_cjs.CIPHER_ENCODING.includes(inputEncoding)) return false;
|
|
465
|
-
const iterations = options.iterations ?? 32e4;
|
|
466
|
-
if (typeof iterations !== "number" || iterations < 1e3) return false;
|
|
467
|
-
const keyLength = options.keyLength ?? 64;
|
|
468
|
-
if (typeof keyLength !== "number" || keyLength < 16) return false;
|
|
469
|
-
const saltBytes = $convertStrToBytes(salt, inputEncoding);
|
|
470
|
-
if (saltBytes.error) return false;
|
|
471
|
-
const hashedPasswordBytes = $convertStrToBytes(hashedPassword, inputEncoding);
|
|
472
|
-
if (hashedPasswordBytes.error) return false;
|
|
473
|
-
try {
|
|
474
|
-
const baseKey = await crypto.subtle.importKey(
|
|
475
|
-
"raw",
|
|
476
|
-
textEncoder.encode(password.normalize("NFKC")),
|
|
477
|
-
"PBKDF2",
|
|
478
|
-
false,
|
|
479
|
-
["deriveBits"]
|
|
480
|
-
);
|
|
481
|
-
const bits = new Uint8Array(
|
|
482
|
-
await crypto.subtle.deriveBits(
|
|
483
|
-
{
|
|
484
|
-
name: "PBKDF2",
|
|
485
|
-
salt: saltBytes.result,
|
|
486
|
-
iterations,
|
|
487
|
-
hash: digestAlgo.web
|
|
488
|
-
},
|
|
489
|
-
baseKey,
|
|
490
|
-
keyLength * 8
|
|
491
|
-
)
|
|
492
|
-
);
|
|
493
|
-
if (bits === void 0 || hashedPasswordBytes.result === void 0) return false;
|
|
494
|
-
if (bits.length !== hashedPasswordBytes.result.length) return false;
|
|
495
|
-
let diff = 0;
|
|
496
|
-
for (let i = 0; i < bits.length; i++) {
|
|
497
|
-
diff |= bits[i] ^ hashedPasswordBytes.result[i];
|
|
498
|
-
}
|
|
499
|
-
return diff === 0;
|
|
500
|
-
} catch {
|
|
501
|
-
return false;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// src/web/kit.ts
|
|
506
|
-
function tryGenerateUuid() {
|
|
507
|
-
return $generateUuid();
|
|
508
|
-
}
|
|
509
|
-
function generateUuid() {
|
|
510
|
-
const { result, error } = $generateUuid();
|
|
511
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
512
|
-
return result;
|
|
513
|
-
}
|
|
514
|
-
async function tryCreateSecretKey(secret, options = {}) {
|
|
515
|
-
return await $createSecretKey(secret, options);
|
|
516
|
-
}
|
|
517
|
-
async function createSecretKey(secret, options = {}) {
|
|
518
|
-
const { result, error } = await $createSecretKey(secret, options);
|
|
519
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
520
|
-
return result;
|
|
521
|
-
}
|
|
522
|
-
async function tryEncrypt(data, secretKey, options = {}) {
|
|
523
|
-
return await $encrypt(data, secretKey, options);
|
|
524
|
-
}
|
|
525
|
-
async function encrypt(data, secretKey, options = {}) {
|
|
526
|
-
const { result, error } = await $encrypt(data, secretKey, options);
|
|
527
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
528
|
-
return result;
|
|
529
|
-
}
|
|
530
|
-
async function tryDecrypt(encrypted, secretKey, options = {}) {
|
|
531
|
-
return await $decrypt(encrypted, secretKey, options);
|
|
532
|
-
}
|
|
533
|
-
async function decrypt(encrypted, secretKey, options = {}) {
|
|
534
|
-
const { result, error } = await $decrypt(encrypted, secretKey, options);
|
|
535
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
536
|
-
return result;
|
|
537
|
-
}
|
|
538
|
-
async function tryEncryptObj(obj, secretKey, options = {}) {
|
|
539
|
-
return await $encryptObj(obj, secretKey, options);
|
|
540
|
-
}
|
|
541
|
-
async function encryptObj(obj, secretKey, options = {}) {
|
|
542
|
-
const { result, error } = await $encryptObj(obj, secretKey, options);
|
|
543
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
544
|
-
return result;
|
|
545
|
-
}
|
|
546
|
-
async function tryDecryptObj(encrypted, secretKey, options = {}) {
|
|
547
|
-
return await $decryptObj(encrypted, secretKey, options);
|
|
548
|
-
}
|
|
549
|
-
async function decryptObj(encrypted, secretKey, options = {}) {
|
|
550
|
-
const { result, error } = await $decryptObj(encrypted, secretKey, options);
|
|
551
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
552
|
-
return result;
|
|
553
|
-
}
|
|
554
|
-
async function tryHash(data, options = {}) {
|
|
555
|
-
return await $hash(data, options);
|
|
556
|
-
}
|
|
557
|
-
async function hash(data, options = {}) {
|
|
558
|
-
const { result, error } = await $hash(data, options);
|
|
559
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
560
|
-
return result;
|
|
561
|
-
}
|
|
562
|
-
async function tryHashPassword(password, options = {}) {
|
|
563
|
-
return await $hashPassword(password, options);
|
|
564
|
-
}
|
|
565
|
-
async function hashPassword(password, options = {}) {
|
|
566
|
-
const { result, salt, error } = await $hashPassword(password, options);
|
|
567
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
568
|
-
return { result, salt };
|
|
569
|
-
}
|
|
570
|
-
async function verifyPassword(password, hashedPassword, salt, options = {}) {
|
|
571
|
-
return await $verifyPassword(password, hashedPassword, salt, options);
|
|
572
|
-
}
|
|
573
|
-
function tryConvertStrToBytes(data, inputEncoding = "utf8") {
|
|
574
|
-
return $convertStrToBytes(data, inputEncoding);
|
|
575
|
-
}
|
|
576
|
-
function convertStrToBytes(data, inputEncoding = "utf8") {
|
|
577
|
-
const { result, error } = $convertStrToBytes(data, inputEncoding);
|
|
578
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
579
|
-
return result;
|
|
580
|
-
}
|
|
581
|
-
function tryConvertBytesToStr(data, outputEncoding = "utf8") {
|
|
582
|
-
return $convertBytesToStr(data, outputEncoding);
|
|
583
|
-
}
|
|
584
|
-
function convertBytesToStr(data, outputEncoding = "utf8") {
|
|
585
|
-
const { result, error } = $convertBytesToStr(data, outputEncoding);
|
|
586
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
587
|
-
return result;
|
|
588
|
-
}
|
|
589
|
-
function tryConvertEncoding(data, from, to) {
|
|
590
|
-
return $convertEncoding(data, from, to);
|
|
591
|
-
}
|
|
592
|
-
function convertEncoding(data, from, to) {
|
|
593
|
-
const { result, error } = $convertEncoding(data, from, to);
|
|
594
|
-
if (error) throw new Error(chunkHTRGOBZF_cjs.$fmtResultErr(error));
|
|
595
|
-
return result;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
exports.convertBytesToStr = convertBytesToStr;
|
|
599
|
-
exports.convertEncoding = convertEncoding;
|
|
600
|
-
exports.convertStrToBytes = convertStrToBytes;
|
|
601
|
-
exports.createSecretKey = createSecretKey;
|
|
602
|
-
exports.decrypt = decrypt;
|
|
603
|
-
exports.decryptObj = decryptObj;
|
|
604
|
-
exports.encrypt = encrypt;
|
|
605
|
-
exports.encryptObj = encryptObj;
|
|
606
|
-
exports.generateUuid = generateUuid;
|
|
607
|
-
exports.hash = hash;
|
|
608
|
-
exports.hashPassword = hashPassword;
|
|
609
|
-
exports.kit_exports = kit_exports;
|
|
610
|
-
exports.tryConvertBytesToStr = tryConvertBytesToStr;
|
|
611
|
-
exports.tryConvertEncoding = tryConvertEncoding;
|
|
612
|
-
exports.tryConvertStrToBytes = tryConvertStrToBytes;
|
|
613
|
-
exports.tryCreateSecretKey = tryCreateSecretKey;
|
|
614
|
-
exports.tryDecrypt = tryDecrypt;
|
|
615
|
-
exports.tryDecryptObj = tryDecryptObj;
|
|
616
|
-
exports.tryEncrypt = tryEncrypt;
|
|
617
|
-
exports.tryEncryptObj = tryEncryptObj;
|
|
618
|
-
exports.tryGenerateUuid = tryGenerateUuid;
|
|
619
|
-
exports.tryHash = tryHash;
|
|
620
|
-
exports.tryHashPassword = tryHashPassword;
|
|
621
|
-
exports.verifyPassword = verifyPassword;
|
|
622
|
-
//# sourceMappingURL=chunk-BMX42IZM.cjs.map
|
|
623
|
-
//# sourceMappingURL=chunk-BMX42IZM.cjs.map
|