cipher-kit 2.0.0-beta.4 → 2.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.
Files changed (40) hide show
  1. package/README.md +362 -99
  2. package/dist/{chunk-UIV6DG54.cjs → chunk-3UX5MZ2P.cjs} +2 -2
  3. package/dist/chunk-3UX5MZ2P.cjs.map +1 -0
  4. package/dist/{chunk-LHB5NXYW.js → chunk-4MFF6V3R.js} +3 -3
  5. package/dist/chunk-4MFF6V3R.js.map +1 -0
  6. package/dist/{chunk-N5T4PNG7.js → chunk-ACFPMIXO.js} +3 -3
  7. package/dist/chunk-ACFPMIXO.js.map +1 -0
  8. package/dist/{chunk-XIWV7XVI.cjs → chunk-CVCDAHDW.cjs} +130 -130
  9. package/dist/chunk-CVCDAHDW.cjs.map +1 -0
  10. package/dist/{chunk-YMNOTRET.js → chunk-FKSYSPJR.js} +2 -2
  11. package/dist/chunk-FKSYSPJR.js.map +1 -0
  12. package/dist/{chunk-OL2AIXWK.cjs → chunk-N2EW2FDZ.cjs} +125 -125
  13. package/dist/chunk-N2EW2FDZ.cjs.map +1 -0
  14. package/dist/{export-Gd8hafl6.d.cts → export-55tHE0Bw.d.cts} +12 -12
  15. package/dist/{export-D1Vh79Qw.d.ts → export-BMvZq46v.d.ts} +12 -12
  16. package/dist/{export-DXRl-ncG.d.cts → export-CQNsJFh_.d.cts} +12 -12
  17. package/dist/{export-DGrELdz_.d.ts → export-llM6c7Do.d.ts} +12 -12
  18. package/dist/index.cjs +11 -11
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +3 -3
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +3 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/node.cjs +32 -32
  25. package/dist/node.d.cts +2 -2
  26. package/dist/node.d.ts +2 -2
  27. package/dist/node.js +2 -2
  28. package/dist/{validate-Cb7IOrPo.d.cts → validate-EHuJC5QQ.d.cts} +19 -8
  29. package/dist/{validate-Cb7IOrPo.d.ts → validate-EHuJC5QQ.d.ts} +19 -8
  30. package/dist/web-api.cjs +32 -32
  31. package/dist/web-api.d.cts +2 -2
  32. package/dist/web-api.d.ts +2 -2
  33. package/dist/web-api.js +2 -2
  34. package/package.json +4 -3
  35. package/dist/chunk-LHB5NXYW.js.map +0 -1
  36. package/dist/chunk-N5T4PNG7.js.map +0 -1
  37. package/dist/chunk-OL2AIXWK.cjs.map +0 -1
  38. package/dist/chunk-UIV6DG54.cjs.map +0 -1
  39. package/dist/chunk-XIWV7XVI.cjs.map +0 -1
  40. package/dist/chunk-YMNOTRET.js.map +0 -1
package/README.md CHANGED
@@ -4,158 +4,417 @@
4
4
  <h1 align="center" style="font-weight:900;">cipher-kit</h1>
5
5
 
6
6
  <p align="center">
7
- Secure, Lightweight, and Cross-Platform <br/>
8
- Encryption, Decryption, and Hashing <br/>
9
- for Web, Node.js, Deno, Bun, and Cloudflare Workers
7
+ Secure, Modern, and Cross-Platform <br/>
8
+ Cryptography Helpers for Web, Node.js, <br/>
9
+ Deno, Bun, and Cloudflare Workers
10
10
  </p>
11
11
 
12
12
  <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/WolfieLeader/npm?color=DC343B" alt="License"></a>
13
13
  <a href="https://www.npmjs.com/package/cipher-kit" rel="nofollow"><img src="https://img.shields.io/npm/v/cipher-kit?color=0078D4" alt="npm version"></a>
14
- <a href="https://www.npmjs.com/package/cipher-kit" rel="nofollow"><img src="https://img.shields.io/npm/dy/cipher-kit.svg?color=03C03C" alt="npm downloads"></a>
14
+ <a href="https://www.npmjs.com/package/cipher-kit" rel="nofollow"><img src="https://img.shields.io/npm/dt/cipher-kit.svg?color=03C03C" alt="npm downloads"></a>
15
15
  <a href="https://github.com/WolfieLeader/npm" rel="nofollow"><img src="https://img.shields.io/github/stars/WolfieLeader/npm" alt="stars"></a>
16
16
 
17
17
  </div>
18
18
 
19
- ## About 📖
19
+ ## Why `cipher-kit`? 🤔
20
20
 
21
- `cipher-kit` is a modern encryption toolkit designed to work seamlessly across **Web**, **Node.js**, **Deno**, and **Bun** environments.
22
- It provides a simple, secure, and dependency-free API for encrypting and decrypting data with **AES-GCM**, ensuring strong security, predictable behavior, and type safety.
23
-
24
- ## Features 🌟
25
-
26
- - 🛡️ **AES-GCM Encryption** – Secure and authenticated encryption with built-in integrity checks.
27
- - 🌐 **Cross-Platform** – Works in Web, Node.js, Deno, and Bun without code changes.
21
+ - 🛡️ **Secure and Flexible** - Uses best practices and modern cryptographic techniques, while providing a flexible and simple API.
22
+ - 📦 **All-in-One Toolkit** Combines encryption, hashing, encoding, serialization, and more into a single package.
23
+ - 🌐 **Cross-Platform** – Works seamlessly across Web, Node.js, Deno, Bun, and Cloudflare Workers.
24
+ - 💡 **Typed and Ergonomic** - Type-safe API with both throwing and non-throwing (`Result`) flavors.
25
+ - 🌳 **Tree-Shakable** - Import from the root or from platform-specific entry points to keep bundles lean.
28
26
  - 🚫 **Zero Dependencies** – Fully self-contained, no external libraries required.
29
- - 🔒 **SHA-256 Key Derivation** Derives strong encryption keys from passwords.
30
- - 🧪 **Strict Validation & `Result<T>` Typing** – Unified return type with robust input validation.
27
+ - 🍼 **Explain Like I'm Five** - Newbie-friendly explanations and documentation.
31
28
 
32
29
  ## Installation 🔥
33
30
 
34
31
  ```bash
35
32
  npm install cipher-kit@latest
33
+ # or
34
+ yarn add cipher-kit@latest
35
+ # or
36
+ pnpm install cipher-kit@latest
37
+ # or
38
+ bun add cipher-kit@latest
36
39
  ```
37
40
 
38
- > 💡 Works with `npm`, `pnpm`, `yarn`, `bun`, and `deno`. You can use it in dev dependencies since it's typically used only for local HTTPS.
41
+ ## Quick Start 🚀
42
+
43
+ ```typescript
44
+ // Node.js Quick Start
45
+ import { createSecretKey, encrypt, decrypt } from "cipher-kit/node";
46
+
47
+ const nodeSecretKey = createSecretKey("my-passphrase");
48
+ const encrypted = encrypt("Hello World!", nodeSecretKey);
49
+ const decrypted = decrypt(encrypted, nodeSecretKey);
50
+ console.log(decrypted); // "Hello World!"
51
+
52
+ // Web Quick Start
53
+ import { createSecretKey, encrypt, decrypt } from "cipher-kit/web-api";
54
+
55
+ const webSecretKey = await createSecretKey("my-passphrase");
56
+ const encrypted = await encrypt("Hello World!", webSecretKey);
57
+ const decrypted = await decrypt(encrypted, webSecretKey);
58
+ console.log(decrypted); // "Hello World!"
59
+ ```
39
60
 
40
61
  ## Usage 🪛
41
62
 
42
- Pick the runtime you’re targeting, or import from the root:
63
+ Table of Contents:
64
+
65
+ - [webKit and nodeKit](#webkit-and-nodekit-objects-)
66
+ - [The try Prefix](#the-try-prefix-non-throwing-result-api-)
67
+ - [Encryption & Decryption](#encryption--decryption-)
68
+ - [Secret Key Creation](#secret-key-creation-)
69
+ - [Encrypting Data](#encrypting-data-)
70
+ - [Decrypting Data](#decrypting-data-)
71
+ - [Encrypting & Decrypting Objects](#encrypting--decrypting-objects-)
72
+ - [Hashing](#hashing-)
73
+ - [UUID Generation](#uuid-generation-)
74
+ - [Password Hashing & Verification](#password-hashing--verification-)
75
+ - [Encoding & Decoding](#encoding--decoding-)
76
+ - [Object Serialization & Deserialization](#object-serialization--deserialization-)
77
+ - [Regex Utilities](#regex-utilities-)
78
+
79
+ ### `webKit` and `nodeKit` Objects 📦
80
+
81
+ The `webKit` and `nodeKit` objects provide platform-specific implementations for Web (including Deno, Bun, and Cloudflare Workers) and Node.js environments, respectively.
82
+
83
+ You can also import them directly from `cipher-kit/web-api` and `cipher-kit/node` for smaller bundle sizes.
43
84
 
44
85
  ```typescript
45
- // For Node.js
46
- import { encrypt, decrypt } from 'cipher-kit/node';
86
+ // Option A: import helpers directly
87
+ import { isNodeSecretKey } from "cipher-kit/node";
88
+ import { isWebSecretKey } from "cipher-kit/web-api";
89
+
90
+ function isSecretKey(key: unknown): boolean {
91
+ return isNodeSecretKey(key) || isWebSecretKey(key);
92
+ }
47
93
 
48
- // For Web API, Deno, Bun, Cloudflare Workers
49
- import { encrypt, decrypt } from 'cipher-kit/web-api';
94
+ // Option B: via kits from the root export
95
+ import { webKit, nodeKit } from "cipher-kit";
50
96
 
51
- // Or import everything from the root
52
- // Functions that, for example encrypt and decrypt will use Node.js implementation.
53
- // You can also access web and node object kits directly.
54
- import { encrypt, decrypt, nodeKit, webKit } from 'cipher-kit';
97
+ function isSecretKey(key: unknown): boolean {
98
+ return nodeKit.isNodeSecretKey(key) || webKit.isWebSecretKey(key);
99
+ }
55
100
  ```
56
101
 
57
- Functions that throw error will show that in their JSDoc comments.
102
+ ### The `try` Prefix (Non-Throwing `Result` API) 🤔
58
103
 
59
- If you would like to avoid using `try/catch`, you can use the functions that prefixed with `try`, e.g., `tryEncrypt`, `tryDecrypt`, `tryEncryptObj`, `tryDecryptObj`. You need to check if the `error` is `undefined` or the `success` is `true` to ensure the operation was successful.
104
+ The `try` prefix functions return a `Result<T>` object that indicates success or failure without throwing exceptions.
60
105
 
61
- ### Node.js Example:
106
+ This is useful in scenarios where you want to handle errors gracefully without using `try/catch` blocks.
62
107
 
63
108
  ```typescript
64
- import {
65
- generateUuid,
66
- hash,
67
- createSecretKey,
68
- encrypt,
69
- decrypt,
70
- encryptObj,
71
- decryptObj,
72
- tryEncrypt,
73
- tryDecrypt,
74
- } from 'cipher-kit/node';
109
+ // Throwing version - simpler but requires try/catch
110
+ const msg = encrypt("Secret message", secretKey);
111
+ console.log(`Encrypted message: ${msg}`);
75
112
 
76
- const str = 'The brown fox 🦊 jumps over the lazy dog 🐶.';
113
+ // Non-throwing version - returns a Result<T> object
114
+ const msg = tryEncrypt("Secret message", secretKey);
77
115
 
78
- function nodeExample() {
79
- console.log(`New UUID: ${generateUuid()}`);
116
+ // Either check for success status
117
+ if (msg.success) console.log(`Encrypted message: ${msg.result}`);
118
+ else console.error(`${msg.error.message} - ${msg.error.description}`);
119
+
120
+ // Or Check that there is no error
121
+ if (!msg.error) console.log(`Encrypted message: ${msg.result}`);
122
+ else console.error(`${msg.error.message} - ${msg.error.description}`);
123
+ ```
80
124
 
81
- console.log(`SHA-256 Hash (ABCDEFG): ${hash('ABCDEFG')}`);
125
+ ### Encryption & Decryption 🤫
82
126
 
83
- const secretKey = createSecretKey('my secure passphrase');
127
+ Encryption is the process of converting readable plaintext into unreadable ciphertext using an algorithm and a secret key to protect its confidentiality. Decryption is the reverse process, using the same algorithm and the correct key to convert the ciphertext back into its original, readable plaintext form.
84
128
 
85
- const encrypted = encrypt(str, secretKey);
86
- console.log(`Encrypted Data: ${encrypted}`);
87
- console.log(`Decrypted Data: ${decrypt(encrypted, secretKey)}`);
129
+ #### _Secret Key Creation_ 🔑
88
130
 
89
- const encryptedObj = encryptObj({ message: 'Hello, World! 🌍', count: 42 }, secretKey);
90
- console.log(`Encrypted Object: ${encryptedObj}`);
91
- console.log(`Decrypted Object: ${JSON.stringify(decryptObj(encryptedObj, secretKey))}`);
131
+ Before encrypting or decrypting data, you need to create a secret key.
92
132
 
93
- const { result: tryEncrypted, error: tryEncryptError } = tryEncrypt(str, secretKey);
94
- if (tryEncryptError) {
95
- console.error(`Encryption Try failed: ${tryEncryptError.message} - ${tryEncryptError.description}`);
96
- return;
97
- }
98
- console.log(`Encrypted Try Data: ${tryEncrypted}`);
133
+ Each key is tied to a specific platform (Web or Node.js) and cannot be used interchangeably.
99
134
 
100
- const decryptedTry = tryDecrypt(tryEncrypted, secretKey);
101
- if (decryptedTry.success === false) {
102
- console.error(`Decryption Try failed: ${decryptedTry.error.message} - ${decryptedTry.error.description}`);
103
- return;
104
- }
105
- console.log(`Try Decrypted Data: ${decryptedTry.result}`);
135
+ ```typescript
136
+ // Node.js example
137
+ import { createSecretKey } from "cipher-kit/node";
138
+
139
+ const nodeSecretKey = createSecretKey("my-passphrase");
140
+
141
+ // Web example
142
+ import { createSecretKey } from "cipher-kit/web-api";
143
+
144
+ const webSecretKey = await createSecretKey("my-passphrase");
145
+ ```
146
+
147
+ The function accepts an optional `options` as well, which allows you to customize the key derivation process.
148
+
149
+ ```typescript
150
+ interface CreateSecretKeyOptions {
151
+ // Which encryption algorithm to use (default: "aes256gcm")
152
+ algorithm?: "aes256gcm" | "aes192gcm" | "aes128gcm";
153
+
154
+ // Digest algorithm for HKDF (key derivation) (default: "sha256")
155
+ digest?: "sha256" | "sha384" | "sha512";
156
+
157
+ // Optional salt for HKDF (key derivation), if you provide a random one it will return a different key each time (default: "cipher-kit-salt", must be >= 8 characters).
158
+ salt?: string;
159
+
160
+ // Optional context info for HKDF (default: "cipher-kit").
161
+ info?: string;
106
162
  }
163
+ ```
164
+
165
+ #### _Encrypting Data_ 🔐
166
+
167
+ Ciphertext formats differ between Web and Node.js platforms.
168
+
169
+ - Node.js - `iv.cipher.tag.` (3 parts)
170
+ - Web - `iv.cipherWithTag.` (2 parts)
171
+
172
+ ```typescript
173
+ // Node.js example
174
+ import { encrypt } from "cipher-kit/node";
175
+
176
+ const encrypted = encrypt("Hello, World!", nodeSecretKey);
177
+ console.log(`Encrypted: ${encrypted}`);
178
+
179
+ // Web example
180
+ import { encrypt } from "cipher-kit/web-api";
107
181
 
108
- nodeExample();
182
+ const encrypted = await encrypt("Hello, World!", webSecretKey);
183
+ console.log(`Encrypted: ${encrypted}`);
109
184
  ```
110
185
 
111
- ### Web API Example:
186
+ The function accepts an optional `options` parameter to customize the output encoding.
112
187
 
113
188
  ```typescript
114
- import {
115
- generateUuid,
116
- hash,
117
- createSecretKey,
118
- encrypt,
119
- decrypt,
120
- encryptObj,
121
- decryptObj,
122
- tryEncrypt,
123
- tryDecrypt,
124
- } from 'cipher-kit/web-api';
189
+ interface EncryptOptions {
190
+ // Output ciphertext encoding(default: "base64url")
191
+ encoding?: "base64url" | "base64" | "hex";
192
+ }
193
+ ```
125
194
 
126
- const str = 'The brown fox 🦊 jumps over the lazy dog 🐶.';
195
+ #### _Decrypting Data_ 🔓
127
196
 
128
- async function webApiExample() {
129
- console.log(`New UUID: ${generateUuid()}`);
197
+ Since ciphertext formats differ between Web and Node.js platforms, make sure to use the correct `decrypt` function for the platform where the data was encrypted.
130
198
 
131
- console.log(`SHA-256 Hash (ABCDEFG): ${await hash('ABCDEFG')}`);
199
+ ```typescript
200
+ // Node.js example
201
+ import { decrypt } from "cipher-kit/node";
202
+
203
+ const decrypted = decrypt(encrypted, nodeSecretKey);
204
+ console.log(`Decrypted: ${decrypted}`);
132
205
 
133
- const secretKey = await createSecretKey('my secure passphrase');
206
+ // Web example
207
+ import { decrypt } from "cipher-kit/web-api";
134
208
 
135
- const encrypted = await encrypt(str, secretKey);
136
- console.log(`Encrypted Data: ${encrypted}`);
137
- console.log(`Decrypted Data: ${await decrypt(encrypted, secretKey)}`);
209
+ const decrypted = await decrypt(encrypted, webSecretKey);
210
+ console.log(`Decrypted: ${decrypted}`);
211
+ ```
138
212
 
139
- const encryptedObj = await encryptObj({ message: 'Hello, World! 🌍', count: 42 }, secretKey);
140
- console.log(`Encrypted Object: ${encryptedObj}`);
141
- console.log(`Decrypted Object: ${JSON.stringify(await decryptObj(encryptedObj, secretKey))}`);
213
+ The function accepts an optional `options` parameter to specify the input encoding.
142
214
 
143
- const { result: tryEncrypted, error: tryEncryptError } = await tryEncrypt(str, secretKey);
144
- if (tryEncryptError) {
145
- console.error(`Encryption Try failed: ${tryEncryptError.message} - ${tryEncryptError.description}`);
146
- return;
147
- }
148
- console.log(`Encrypted Try Data: ${tryEncrypted}`);
215
+ Make sure to use the same encoding that was used during encryption.
149
216
 
150
- const decryptedTry = await tryDecrypt(tryEncrypted, secretKey);
151
- if (decryptedTry.success === false) {
152
- console.error(`Decryption Try failed: ${decryptedTry.error.message} - ${decryptedTry.error.description}`);
153
- return;
154
- }
155
- console.log(`Try Decrypted Data: ${decryptedTry.result}`);
217
+ ```typescript
218
+ interface DecryptOptions {
219
+ // Input ciphertext encoding (default: "base64url")
220
+ encoding?: "base64url" | "base64" | "hex";
156
221
  }
222
+ ```
223
+
224
+ #### _Encrypting & Decrypting Objects_ 🧬
225
+
226
+ ```typescript
227
+ // Node.js example
228
+ import { encryptObj, decryptObj } from "cipher-kit/node";
229
+
230
+ const obj = { name: "Alice", age: 30, city: "Wonderland" };
231
+
232
+ const encryptedObj = encryptObj(obj, nodeSecretKey);
233
+
234
+ const decryptedObj = decryptObj<typeof obj>(encryptedObj, nodeSecretKey);
235
+ console.log(`Decrypted Object:`, decryptedObj);
236
+
237
+ // Web example
238
+ import { encryptObj, decryptObj } from "cipher-kit/web-api";
157
239
 
158
- webApiExample();
240
+ const obj = { name: "Alice", age: 30, city: "Wonderland" };
241
+
242
+ const encryptedObj = await encryptObj(obj, webSecretKey);
243
+
244
+ const decryptedObj = await decryptObj<typeof obj>(encryptedObj, webSecretKey);
245
+ console.log(`Decrypted Object:`, decryptedObj);
246
+ ```
247
+
248
+ The `encryptObj` and `decryptObj` functions accept the same `options` parameters as `encrypt` and `decrypt`, respectively.
249
+
250
+ ### Hashing 🪄
251
+
252
+ Hashing is a one-way process that uses an algorithm to transform data of any size into a fixed-length string of characters, called a hash value or digest. It serves as a digital fingerprint for the data, enabling quick data retrieval in hash tables, password storage, and file integrity checks. Key features include its irreversibility (you can't get the original data back from the hash).
253
+
254
+ Not suitable for storing passwords - use `hashPassword` instead.
255
+
256
+ ```typescript
257
+ // Node.js example
258
+ import { hash } from "cipher-kit/node";
259
+
260
+ const hashed = hash("Hello, World!");
261
+ console.log(`Hashed: ${hashed}`);
262
+
263
+ // Web example
264
+ import { hash } from "cipher-kit/web-api";
265
+
266
+ const hashed = await hash("Hello, World!");
267
+ console.log(`Hashed: ${hashed}`);
268
+ ```
269
+
270
+ The function accepts an optional `options` parameter to customize the hashing process.
271
+
272
+ ```typescript
273
+ interface HashOptions {
274
+ // Digest algorithm to use (default: "sha256").
275
+ digest?: "sha256" | "sha384" | "sha512";
276
+
277
+ // Output encoding (default: "base64url").
278
+ encoding?: "base64url" | "base64" | "hex";
279
+ }
280
+ ```
281
+
282
+ ### UUID Generation 🪪
283
+
284
+ UUID (Universally Unique Identifier) is a 128-bit identifier used to uniquely identify information in computer systems. It is designed to be globally unique, meaning that no two UUIDs should be the same, even if generated on different systems or at different times. UUIDs are commonly used in databases, distributed systems, and applications where unique identification is crucial.
285
+
286
+ ```typescript
287
+ // Node.js example
288
+ import { generateUuid } from "cipher-kit/node";
289
+
290
+ const uuid = generateUuid();
291
+ console.log(`Generated UUID: ${uuid}`);
292
+
293
+ // Web example
294
+ import { generateUuid } from "cipher-kit/web-api";
295
+
296
+ const uuid = generateUuid();
297
+ console.log(`Generated UUID: ${uuid}`);
298
+ ```
299
+
300
+ ### Password Hashing & Verification 💎
301
+
302
+ Password hashing is a one-way process that transforms a plaintext password into a fixed-length hash. Password hashing is crucial for securely storing passwords in databases, as it protects user credentials from being exposed in case of a data breach.
303
+
304
+ Password hashing is different from general-purpose hashing because it often involves additional techniques like salting and key stretching to enhance security against brute-force attacks, and it's usually slower to compute to make rainbow table attacks less feasible.
305
+
306
+ To verify a password, the same hashing process is applied to the input password, and the resulting hash is compared to the stored hash, in a constant-time comparison to prevent timing attacks.
307
+
308
+ ```typescript
309
+ // Node.js example
310
+ import { hashPassword, verifyPassword } from "cipher-kit/node";
311
+
312
+ const { hash, salt } = hashPassword("some-secure-password");
313
+ console.log(`Hashed Password: ${hash}`);
314
+
315
+ const isMatch = verifyPassword("some-secure-password", hash, salt);
316
+ console.log(`Password match: ${isMatch}`);
317
+
318
+ // Web example
319
+ import { hashPassword, verifyPassword } from "cipher-kit/web-api";
320
+
321
+ const { hash, salt } = await hashPassword("some-secure-password");
322
+ console.log(`Hashed Password: ${hash}`);
323
+
324
+ const isMatch = await verifyPassword("some-secure-password", hash, salt);
325
+ console.log(`Password match: ${isMatch}`);
326
+ ```
327
+
328
+ The `hashPassword` and `verifyPassword` functions accept an optional `options` parameter to customize the hashing process.
329
+
330
+ ```typescript
331
+ interface HashPasswordOptions {
332
+ // Digest algorithm to use (default: "sha512").
333
+ digest?: "sha256" | "sha384" | "sha512";
334
+
335
+ // Encoding format for the output hash (default: "base64url").
336
+ encoding?: "base64url" | "base64" | "hex";
337
+
338
+ // Length of the salt in bytes (default: 16 bytes, min: 8 bytes).
339
+ saltLength?: number;
340
+
341
+ // Number of iterations for key derivation (default: 320000, min: 1000).
342
+ iterations?: number;
343
+
344
+ // Length of the derived key in bytes (default: 64 bytes, min: 16 bytes).
345
+ keyLength?: number;
346
+ }
347
+
348
+ interface VerifyPasswordOptions {
349
+ // Digest algorithm used during the original hashing (default: `'sha512'`).
350
+ digest?: "sha256" | "sha384" | "sha512";
351
+
352
+ // Encoding format used during the original hashing (default: `'base64url'`).
353
+ encoding?: "base64url" | "base64" | "hex";
354
+
355
+ // Number of iterations used during the original hashing (default: `320000`).
356
+ iterations?: number;
357
+
358
+ // Length of the key used during the original hashing (default: `64`).
359
+ keyLength?: number;
360
+ }
361
+ ```
362
+
363
+ ### Encoding & Decoding 🧩
364
+
365
+ Encoding and decoding are processes used to convert data into a specific format for efficient transmission, storage, or representation. Encoding transforms data into a different format using a specific scheme, while decoding reverses this process to retrieve the original data. Common encoding schemes include Base64, Base64URL, and Hexadecimal (Hex).
366
+
367
+ ```typescript
368
+ // Node.js and Web example - works the same in both
369
+ import { convertStrToBytes, convertBytesToStr, convertEncoding } from "cipher-kit/node"; // or "cipher-kit/web-api"
370
+
371
+ // Encoding
372
+ const buffer = convertStrToBytes("Hello World!", "utf8"); // the input encoding
373
+ console.log(`Encoded: ${buffer}`);
374
+
375
+ // Decoding
376
+ const str = convertBytesToStr(buffer, "utf8"); // the output encoding
377
+ console.log(`Decoded: ${str}`);
378
+
379
+ // Convert between encodings
380
+ const base64 = convertEncoding("Hello World!", "utf8", "base64");
381
+ console.log(`Base64: ${base64}`);
382
+ ```
383
+
384
+ ### Object Serialization & Deserialization 🧬
385
+
386
+ Object serialization in JavaScript is the process of converting objects or arrays into a JSON string representation, that can be easily stored or transmitted. Deserialization is the reverse process, where the JSON string is parsed back into its original object or array structure.
387
+
388
+ ```typescript
389
+ import { stringifyObj, parseToObj } from "cipher-kit"; // works in both "cipher-kit/web-api" and "cipher-kit/node"
390
+
391
+ const obj = { name: "Alice", age: 30, city: "Wonderland" };
392
+
393
+ const jsonString = stringifyObj(obj);
394
+ console.log(`Serialized: ${jsonString}`);
395
+
396
+ const parsedObj = parseToObj<typeof obj>(jsonString);
397
+ console.log(`Deserialized:`, parsedObj);
398
+ ```
399
+
400
+ ### Regex Utilities 🔍
401
+
402
+ Regular expressions (regex) are sequences of characters that form search patterns, used for pattern matching within strings.
403
+
404
+ Before decrypting, you can validate the format (decryption functions already validate internally).
405
+
406
+ ```typescript
407
+ import { ENCRYPTED_REGEX, matchPattern } from "cipher-kit"; // works in both "cipher-kit/web-api" and "cipher-kit/node"
408
+
409
+ function isEncryptedFormat(message: string): boolean {
410
+ return matchPattern(message, "general"); // or "node" or "web"
411
+ }
412
+
413
+ // or
414
+
415
+ function isEncryptedFormat(message: string): boolean {
416
+ return ENCRYPTED_REGEX.general.test(message); // or "node" or "web"
417
+ }
159
418
  ```
160
419
 
161
420
  ## Contributions 🤝
@@ -170,4 +429,8 @@ Want to contribute or suggest a feature?
170
429
 
171
430
  This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
172
431
 
173
- Thank you!
432
+ <div align="center">
433
+ <br/>
434
+ <div style="font-size: 14px; font-weight:bold;"> ⚒️ Crafted carefully by <a href="https://github.com/WolfieLeader" target="_blank" rel="nofollow">WolfieLeader</a></div>
435
+ <div style="font-size: 12px; font-style: italic;">Thank you!</div>
436
+ </div>
@@ -154,5 +154,5 @@ exports.stringifyObj = stringifyObj;
154
154
  exports.title = title;
155
155
  exports.tryParseToObj = tryParseToObj;
156
156
  exports.tryStringifyObj = tryStringifyObj;
157
- //# sourceMappingURL=chunk-UIV6DG54.cjs.map
158
- //# sourceMappingURL=chunk-UIV6DG54.cjs.map
157
+ //# sourceMappingURL=chunk-3UX5MZ2P.cjs.map
158
+ //# sourceMappingURL=chunk-3UX5MZ2P.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helpers/consts.ts","../src/helpers/validate.ts","../src/helpers/error.ts","../src/helpers/object.ts"],"names":["nodeCrypto","title"],"mappings":"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","file":"chunk-3UX5MZ2P.cjs","sourcesContent":["export const ENCODING = Object.freeze([\"base64\", \"base64url\", \"hex\", \"utf8\", \"latin1\"] as const);\r\n\r\nexport const CIPHER_ENCODING = Object.freeze([\"base64\", \"base64url\", \"hex\"] as const);\r\n\r\nexport const DIGEST_ALGORITHMS = Object.freeze({\r\n sha256: { node: \"sha256\", web: \"SHA-256\" },\r\n sha384: { node: \"sha384\", web: \"SHA-384\" },\r\n sha512: { node: \"sha512\", web: \"SHA-512\" },\r\n} as const);\r\n\r\nexport const ENCRYPTION_ALGORITHMS = Object.freeze({\r\n aes256gcm: { keyBytes: 32, ivLength: 12, node: \"aes-256-gcm\", web: \"AES-GCM\" },\r\n aes192gcm: { keyBytes: 24, ivLength: 12, node: \"aes-192-gcm\", web: \"AES-GCM\" },\r\n aes128gcm: { keyBytes: 16, ivLength: 12, node: \"aes-128-gcm\", web: \"AES-GCM\" },\r\n} as const);\r\n","import nodeCrypto from \"node:crypto\";\r\nimport type { SecretKey } from \"~/helpers/types\";\r\nimport { DIGEST_ALGORITHMS, ENCRYPTION_ALGORITHMS } from \"./consts\";\r\n\r\nexport function $isStr(x: unknown, min = 1): x is string {\r\n return x !== null && x !== undefined && typeof x === \"string\" && x.trim().length >= min;\r\n}\r\n\r\nexport function $isObj(x: unknown): x is Record<string, unknown> {\r\n if (typeof x !== \"object\" || x === null || x === undefined) return false;\r\n const proto = Object.getPrototypeOf(x);\r\n return proto === Object.prototype || proto === null;\r\n}\r\n\r\nexport function $isLooseObj(x: unknown): x is Record<string, unknown> {\r\n return typeof x === \"object\" && x !== null && x !== undefined;\r\n}\r\n\r\ntype InjectedSecretKey<Platform extends \"web\" | \"node\"> = SecretKey<Platform> & {\r\n readonly injected: (typeof ENCRYPTION_ALGORITHMS)[keyof typeof ENCRYPTION_ALGORITHMS];\r\n};\r\n\r\nconst expectedKeys = new Set([\"platform\", \"digest\", \"algorithm\", \"key\"]);\r\n\r\nexport function $isSecretKey<Platform extends \"node\" | \"web\">(\r\n x: unknown,\r\n platform: Platform,\r\n): InjectedSecretKey<Platform> | null {\r\n if (!$isLooseObj(x) || (platform !== \"node\" && platform !== \"web\") || x.platform !== platform) return null;\r\n\r\n const keys = Object.keys(x);\r\n if (keys.length !== expectedKeys.size) return null;\r\n for (const key of keys) if (!expectedKeys.has(key)) return null;\r\n for (const key of expectedKeys) if (!Object.hasOwn(x, key)) return null;\r\n\r\n if (\r\n typeof x.digest !== \"string\" ||\r\n !(x.digest in DIGEST_ALGORITHMS) ||\r\n typeof x.algorithm !== \"string\" ||\r\n !(x.algorithm in ENCRYPTION_ALGORITHMS) ||\r\n !$isLooseObj(x.key) ||\r\n x.key.type !== \"secret\"\r\n ) {\r\n return null;\r\n }\r\n\r\n const algorithm = ENCRYPTION_ALGORITHMS[x.algorithm as keyof typeof ENCRYPTION_ALGORITHMS];\r\n\r\n if (platform === \"node\") {\r\n if (\r\n !(x.key instanceof nodeCrypto.KeyObject) ||\r\n (typeof x.key.symmetricKeySize === \"number\" && x.key.symmetricKeySize !== algorithm.keyBytes)\r\n ) {\r\n return null;\r\n }\r\n return Object.freeze({ ...x, injected: algorithm }) as InjectedSecretKey<Platform>;\r\n }\r\n\r\n if (\r\n !$isLooseObj(x.key.algorithm) ||\r\n x.key.algorithm.name !== algorithm.web ||\r\n (typeof x.key.algorithm.length === \"number\" && x.key.algorithm.length !== algorithm.keyBytes * 8) ||\r\n typeof x.key.extractable !== \"boolean\" ||\r\n !Array.isArray(x.key.usages) ||\r\n x.key.usages.length !== 2 ||\r\n !(x.key.usages.includes(\"encrypt\") && x.key.usages.includes(\"decrypt\"))\r\n ) {\r\n return null;\r\n }\r\n return Object.freeze({ ...x, injected: algorithm }) as InjectedSecretKey<Platform>;\r\n}\r\n\r\n/**\r\n * Regular expressions for encrypted data patterns.\r\n *\r\n * - **node**: `\"iv.cipher.tag.\"` (three dot-separated parts plus a trailing dot)\r\n * - **web**: `\"iv.cipherWithTag.\"` (two parts plus a trailing dot)\r\n * - **general**: accepts both shapes (2 or 3 parts) with a trailing dot\r\n *\r\n * Each part is any non-empty string without dots.\r\n *\r\n * ### 🍼 Explain Like I'm Five\r\n * You have a secret code you want to check. Before you check it,\r\n * you make sure it looks how a secret code should look.\r\n */\r\nexport const ENCRYPTED_REGEX = Object.freeze({\r\n node: /^([^.]+)\\.([^.]+)\\.([^.]+)\\.$/,\r\n web: /^([^.]+)\\.([^.]+)\\.$/,\r\n general: /^([^.]+)\\.([^.]+)(?:\\.([^.]+))?\\.$/,\r\n});\r\n\r\n/**\r\n * Checks if a string matches an expected encrypted payload shape.\r\n *\r\n * - **node**: `\"iv.cipher.tag.\"` (three dot-separated parts plus a trailing dot)\r\n * - **web**: `\"iv.cipherWithTag.\"` (two parts plus a trailing dot)\r\n * - **general**: accepts both shapes (2 or 3 parts) with a trailing dot\r\n *\r\n * Each part is any non-empty string without dots.\r\n *\r\n * This validates only the **shape**, not whether content is valid base64/hex, etc.\r\n *\r\n * ### 🍼 Explain Like I'm Five\r\n * You have a secret code you want to check. Before you check it,\r\n * you make sure it looks how a secret code should look.\r\n *\r\n * @param data - The string to test.\r\n * @param format - Which layout to check: `'node'`, `'web'`, or `'general'`.\r\n * @returns `true` if the string matches the pattern; otherwise `false`.\r\n * @throws {Error} If an unknown `format` is provided.\r\n *\r\n * @example\r\n * ```ts\r\n * matchPattern(\"abc.def.ghi.\", \"node\"); // true\r\n * matchPattern(\"abc.def.\", \"web\"); // true\r\n * matchPattern(\"abc.def.\", \"node\"); // false\r\n * matchPattern(\"abc.def.ghi.\", \"general\"); // true\r\n * ```\r\n */\r\nexport function matchPattern(data: string, format: \"general\" | \"node\" | \"web\"): boolean {\r\n if (typeof data !== \"string\") return false;\r\n if (!(format in ENCRYPTED_REGEX)) throw new Error(`Unknown format: ${format}`);\r\n return ENCRYPTED_REGEX[format].test(data);\r\n}\r\n","import { $isObj } from \"./validate\";\r\n\r\n/**\r\n * Standardized error object for the `Result` type.\r\n * Always has a brief `message` and a more detailed `description`.\r\n */\r\nexport interface ResultErr {\r\n readonly message: string;\r\n readonly description: string;\r\n}\r\n\r\n/**\r\n * Discriminated union for functions that can succeed or fail.\r\n *\r\n * - On **success**:\r\n * - If `T` is an object - properties of `T` are **spread** into the result\r\n * along with `success: true`.\r\n * - Otherwise - `{ success: true, result: T }`.\r\n * - On **failure**: `{ success: false, error: E }`.\r\n *\r\n * @example\r\n * ```ts\r\n * // Primitive result\r\n * function getNum(): Result<number> {\r\n * return $ok(42);\r\n * }\r\n * const r1 = getNum();\r\n * if (r1.success) console.log(r1.result); // 42\r\n *\r\n * // Object result (spread)\r\n * function getObject(): Result<{ name: string; age: number }> {\r\n * return $ok({ name: 'Alice', age: 30 });\r\n * }\r\n * const r2 = getObject();\r\n * if (r2.success) console.log(r2.name, r2.age); // 'Alice' 30\r\n * ```\r\n */\r\nexport type Result<T, E = ResultErr> = T extends object\r\n ?\r\n | ({ readonly [K in keyof T]: T[K] } & { readonly success: true; readonly error?: undefined })\r\n | ({ readonly [K in keyof T]?: undefined } & { readonly success: false; readonly error: E })\r\n :\r\n | { readonly success: true; readonly result: T; readonly error?: undefined }\r\n | { readonly success: false; readonly error: E; readonly result?: undefined };\r\n\r\nexport function $ok<T>(result?: T): Result<T> {\r\n if ($isObj(result)) return { success: true, ...(result as T & object) } as Result<T>;\r\n return { success: true, result } as Result<T>;\r\n}\r\n\r\nexport function $err(err: { msg: string; desc: string }): Result<never, ResultErr>;\r\nexport function $err(err: ResultErr): Result<never, ResultErr>;\r\nexport function $err(err: { msg: string; desc: string } | ResultErr): Result<never, ResultErr> {\r\n return {\r\n success: false,\r\n error: {\r\n message: \"msg\" in err ? err.msg : err.message,\r\n description: \"desc\" in err ? err.desc : err.description,\r\n },\r\n } as Result<never, ResultErr>;\r\n}\r\n\r\nexport function $fmtError(error: unknown): string {\r\n if (typeof error === \"string\") return error;\r\n if (error instanceof Error) return error.message;\r\n return String(error);\r\n}\r\n\r\nexport function $fmtResultErr(err: ResultErr | undefined): string {\r\n if (!err) return \"Unknown error\";\r\n return `${err.message} - ${err.description}`;\r\n}\r\n\r\nexport function title(platform: \"web\" | \"node\", title: string): string {\r\n return `${platform === \"web\" ? \"Crypto Web API\" : \"Crypto NodeJS API\"} - ${title}`;\r\n}\r\n","import { $err, $fmtError, $fmtResultErr, $ok, type Result } from \"./error\";\r\nimport { $isObj, $isStr } from \"./validate\";\r\n\r\nexport function $stringifyObj<T extends object = Record<string, unknown>>(obj: T): Result<string> {\r\n try {\r\n if (!$isObj(obj)) return $err({ msg: \"Invalid object\", desc: \"Input is not a plain object\" });\r\n return $ok(JSON.stringify(obj));\r\n } catch (error) {\r\n return $err({ msg: \"Utility: Stringify error\", desc: $fmtError(error) });\r\n }\r\n}\r\n\r\n/**\r\n * Safely serializes a plain object to JSON without throwing.\r\n *\r\n * Wraps `JSON.stringify` and returns a `Result` containing the JSON string or an error.\r\n * Only plain objects (POJOs) are accepted. Class instances, Maps, Sets, etc. are rejected.\r\n *\r\n * ### 🍼 Explain Like I'm Five\r\n * You have a box of toys (your object) and take a photo of it (a JSON string)\r\n * so you can send it to a friend.\r\n *\r\n * @template T - Plain object type to serialize.\r\n * @param obj - The object to stringify (must be a plain object).\r\n * @returns A `Result` with the JSON string on success, or an error.\r\n *\r\n * @example\r\n * ```ts\r\n * const res = tryStringifyObj({ a: 1 });\r\n * if (res.success) {\r\n * console.log(res.result); // {\"a\":1}\r\n * } else {\r\n * console.error(res.error.message, res.error.description);\r\n * }\r\n * ```\r\n */\r\nexport function tryStringifyObj<T extends object = Record<string, unknown>>(obj: T): Result<string> {\r\n return $stringifyObj(obj);\r\n}\r\n\r\n/**\r\n * Serializes a plain object to JSON (throwing).\r\n *\r\n * Wraps `JSON.stringify` and returns the result or throws an error.\r\n * Only plain objects (POJOs) are accepted. Class instances, Maps, Sets, etc. are rejected.\r\n *\r\n * ### 🍼 Explain Like I'm Five\r\n * You have a box of toys (your object) and take a photo of it (a JSON string)\r\n * so you can send it to a friend.\r\n *\r\n * @template T - Plain object type to serialize.\r\n * @param obj - The object to stringify (must be a plain object).\r\n * @returns JSON string representation of the object.\r\n * @throws {Error} If `obj` is not a plain object or serialization fails.\r\n *\r\n * @example\r\n * ```ts\r\n * try {\r\n * const json = stringifyObj({ a: 1 }); // {\"a\":1}\r\n * } catch (error: unknown) {\r\n * console.error(error);\r\n * }\r\n * ```\r\n */\r\nexport function stringifyObj<T extends object = Record<string, unknown>>(obj: T): string {\r\n const { result, error } = $stringifyObj(obj);\r\n if (error) throw new Error($fmtResultErr(error));\r\n return result;\r\n}\r\n\r\nexport function $parseToObj<T extends object = Record<string, unknown>>(str: string): Result<{ result: T }> {\r\n try {\r\n if (!$isStr(str)) return $err({ msg: \"Utility: Invalid input\", desc: \"Input is not a valid string\" });\r\n const obj = JSON.parse(str);\r\n\r\n if (!$isObj(obj)) return $err({ msg: \"Utility: Invalid object format\", desc: \"Parsed data is not a plain object\" });\r\n return $ok({ result: obj as T });\r\n } catch (error) {\r\n return $err({ msg: \"Utility: Invalid format\", desc: $fmtError(error) });\r\n }\r\n}\r\n\r\n/**\r\n * Safely parses a JSON string to a plain object (non-throwing).\r\n *\r\n * Wraps `JSON.parse` and returns a `Result` containing the parsed object, or an error.\r\n *\r\n * ### 🍼 Explain Like I'm Five\r\n * You rebuild your toy box (an object) from a photo you took (a JSON string).\r\n *\r\n * @template T - The expected object type.\r\n * @param str - The JSON string to parse.\r\n * @returns A `Result` with the parsed object on success, or an error.\r\n *\r\n * @example\r\n * ```ts\r\n * const res = tryParseToObj<{ a: number }>('{\"a\":1}');\r\n * if (res.success) {\r\n * console.log(res.result.a); // 1\r\n * } else {\r\n * console.error(res.error.message, res.error.description);\r\n * }\r\n * ```\r\n */\r\nexport function tryParseToObj<T extends object = Record<string, unknown>>(str: string): Result<{ result: T }> {\r\n return $parseToObj<T>(str);\r\n}\r\n\r\n/**\r\n * Parses a JSON string to a plain object (throwing).\r\n *\r\n * Wraps `JSON.parse` and returns the parsed object, or throws on failure.\r\n *\r\n * ### 🍼 Explain Like I'm Five\r\n * You rebuild your toy box (an object) from a photo you took (a JSON string).\r\n *\r\n * @template T - The expected object type.\r\n * @param str - The JSON string to parse.\r\n * @returns The parsed plain object.\r\n * @throws {Error} If the string can’t be parsed or doesn’t represent a plain object.\r\n *\r\n * @example\r\n * ```ts\r\n * try {\r\n * const obj = parseToObj<{ a: number }>('{\"a\":1}'); // obj.a === 1\r\n * } catch (error: unknown) {\r\n * console.error(error);\r\n * }\r\n * ```\r\n */\r\nexport function parseToObj<T extends object = Record<string, unknown>>(str: string): T {\r\n const { result, error } = $parseToObj<T>(str);\r\n if (error) throw new Error($fmtResultErr(error));\r\n return result;\r\n}\r\n"]}
@@ -1,4 +1,4 @@
1
- import { __export, $isSecretKey, $fmtResultErr, $ok, $err, $fmtError, title, $isStr, ENCRYPTION_ALGORITHMS, DIGEST_ALGORITHMS, CIPHER_ENCODING, matchPattern, $stringifyObj, $parseToObj, ENCODING } from './chunk-YMNOTRET.js';
1
+ import { __export, $isSecretKey, $fmtResultErr, $ok, $err, $fmtError, title, $isStr, ENCRYPTION_ALGORITHMS, DIGEST_ALGORITHMS, CIPHER_ENCODING, matchPattern, $stringifyObj, $parseToObj, ENCODING } from './chunk-FKSYSPJR.js';
2
2
 
3
3
  // src/web/kit.ts
4
4
  var kit_exports = {};
@@ -563,5 +563,5 @@ function convertEncoding(data, from, to) {
563
563
  }
564
564
 
565
565
  export { convertBytesToStr, convertEncoding, convertStrToBytes, createSecretKey, decrypt, decryptObj, encrypt, encryptObj, generateUuid, hash, hashPassword, isWebSecretKey, kit_exports, tryConvertBytesToStr, tryConvertEncoding, tryConvertStrToBytes, tryCreateSecretKey, tryDecrypt, tryDecryptObj, tryEncrypt, tryEncryptObj, tryGenerateUuid, tryHash, tryHashPassword, verifyPassword };
566
- //# sourceMappingURL=chunk-LHB5NXYW.js.map
567
- //# sourceMappingURL=chunk-LHB5NXYW.js.map
566
+ //# sourceMappingURL=chunk-4MFF6V3R.js.map
567
+ //# sourceMappingURL=chunk-4MFF6V3R.js.map