cipher-kit 2.1.2 → 3.0.0-beta.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 (52) hide show
  1. package/README.md +322 -434
  2. package/dist/chunk-3NFJMV33.js +478 -0
  3. package/dist/chunk-3NFJMV33.js.map +1 -0
  4. package/dist/chunk-4YR2SBOH.js +488 -0
  5. package/dist/chunk-4YR2SBOH.js.map +1 -0
  6. package/dist/chunk-LC5HP75W.cjs +502 -0
  7. package/dist/chunk-LC5HP75W.cjs.map +1 -0
  8. package/dist/chunk-X7IPAA7B.cjs +517 -0
  9. package/dist/chunk-X7IPAA7B.cjs.map +1 -0
  10. package/dist/chunk-ZN7EFZ7Z.js +475 -0
  11. package/dist/chunk-ZN7EFZ7Z.js.map +1 -0
  12. package/dist/chunk-ZYX6MYHS.cjs +509 -0
  13. package/dist/chunk-ZYX6MYHS.cjs.map +1 -0
  14. package/dist/export-BEp4DFEB.d.cts +388 -0
  15. package/dist/export-Cxfev8fi.d.ts +395 -0
  16. package/dist/export-DAIDJRX3.d.ts +388 -0
  17. package/dist/export-e7IN_bU5.d.cts +395 -0
  18. package/dist/index.cjs +11 -19
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +11 -40
  21. package/dist/index.d.ts +11 -40
  22. package/dist/index.js +3 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/node.cjs +39 -35
  25. package/dist/node.d.cts +3 -3
  26. package/dist/node.d.ts +3 -3
  27. package/dist/node.js +2 -2
  28. package/dist/validate-DN59A2-Y.d.cts +192 -0
  29. package/dist/validate-DN59A2-Y.d.ts +192 -0
  30. package/dist/web-api.cjs +39 -35
  31. package/dist/web-api.d.cts +2 -3
  32. package/dist/web-api.d.ts +2 -3
  33. package/dist/web-api.js +2 -2
  34. package/package.json +82 -92
  35. package/dist/chunk-66WIL32E.cjs +0 -623
  36. package/dist/chunk-66WIL32E.cjs.map +0 -1
  37. package/dist/chunk-HTRGOBZF.cjs +0 -169
  38. package/dist/chunk-HTRGOBZF.cjs.map +0 -1
  39. package/dist/chunk-JLFVTZY4.js +0 -598
  40. package/dist/chunk-JLFVTZY4.js.map +0 -1
  41. package/dist/chunk-LU7QOSQH.js +0 -141
  42. package/dist/chunk-LU7QOSQH.js.map +0 -1
  43. package/dist/chunk-S6SNCTU6.js +0 -485
  44. package/dist/chunk-S6SNCTU6.js.map +0 -1
  45. package/dist/chunk-ZNM5M6RD.cjs +0 -514
  46. package/dist/chunk-ZNM5M6RD.cjs.map +0 -1
  47. package/dist/export-BaM_OTFk.d.ts +0 -573
  48. package/dist/export-CCTGAosO.d.ts +0 -572
  49. package/dist/export-FYHgb-8E.d.cts +0 -572
  50. package/dist/export-KFT0YyMg.d.cts +0 -573
  51. package/dist/validate-lkJAHCeJ.d.cts +0 -399
  52. package/dist/validate-lkJAHCeJ.d.ts +0 -399
package/README.md CHANGED
@@ -1,434 +1,322 @@
1
- <div align="center">
2
- <img src="https://github.com/WolfieLeader/npm/blob/main/assets/cipher-kit-banner.svg" align="center" alt="banner" />
3
-
4
- <h1 align="center" style="font-weight:900;">cipher-kit</h1>
5
-
6
- <p align="center">
7
- Secure, Modern, and Cross-Platform <br/>
8
- Cryptography Helpers for Web, Node.js, <br/>
9
- Deno, Bun, and Cloudflare Workers
10
- </p>
11
-
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
- <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/dt/cipher-kit.svg?color=03C03C" alt="npm downloads"></a>
15
- <a href="https://github.com/WolfieLeader/npm" rel="nofollow"><img src="https://img.shields.io/github/stars/WolfieLeader/npm" alt="stars"></a>
16
-
17
- </div>
18
-
19
- ## Why `cipher-kit`? 🤔
20
-
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.
26
- - 🚫 **Zero Dependencies** – Fully self-contained, no external libraries required.
27
- - 🍼 **Explain Like I'm Five** - Newbie-friendly explanations and documentation.
28
-
29
- ## Installation 🔥
30
-
31
- ```bash
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
39
- ```
40
-
41
- ## Quick Start 🚀
42
-
43
- ```typescript
44
- // Node.js
45
- import { createSecretKey, encrypt, decrypt } from "cipher-kit/node";
46
-
47
- const secretKey = createSecretKey("my-passphrase");
48
- const encrypted = encrypt("Hello World!", secretKey);
49
- const decrypted = decrypt(encrypted, secretKey);
50
- console.log(decrypted); // "Hello World!"
51
-
52
- // Web - including Deno, Bun, Cloudflare Workers
53
- import { createSecretKey, encrypt, decrypt } from "cipher-kit/web-api";
54
-
55
- const secretKey = await createSecretKey("my-passphrase");
56
- const encrypted = await encrypt("Hello World!", secretKey);
57
- const decrypted = await decrypt(encrypted, secretKey);
58
- console.log(decrypted); // "Hello World!"
59
- ```
60
-
61
- ## API Reference 📚
62
-
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.
84
-
85
- ```typescript
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
- }
93
-
94
- // Option B: via kits from the root export
95
- import { webKit, nodeKit } from "cipher-kit";
96
-
97
- function isSecretKey(key: unknown): boolean {
98
- return nodeKit.isNodeSecretKey(key) || webKit.isWebSecretKey(key);
99
- }
100
- ```
101
-
102
- ### The `try` Prefix (Non-Throwing `Result` API) 🤔
103
-
104
- The `try` prefix functions return a `Result<T>` object that indicates success or failure without throwing exceptions.
105
-
106
- This is useful in scenarios where you want to handle errors gracefully without using `try/catch` blocks.
107
-
108
- ```typescript
109
- // Throwing version - simpler but requires try/catch
110
- const msg = encrypt("Secret message", secretKey);
111
- console.log(`Encrypted message: ${msg}`);
112
-
113
- // Non-throwing version - returns a Result<T> object
114
- const msg = tryEncrypt("Secret message", secretKey);
115
-
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
- ```
124
-
125
- ### Encryption & Decryption 🤫
126
-
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.
128
-
129
- #### _Secret Key Creation_ 🔑
130
-
131
- Before encrypting or decrypting data, you need to create a secret key.
132
- The key must be at least 8 characters long.
133
-
134
- Each key is tied to a specific platform (Web or Node.js) and cannot be used interchangeably.
135
-
136
- ```typescript
137
- // Node.js example
138
- import { createSecretKey } from "cipher-kit/node";
139
-
140
- const nodeSecretKey = createSecretKey("my-passphrase");
141
-
142
- // Web example
143
- import { createSecretKey } from "cipher-kit/web-api";
144
-
145
- const webSecretKey = await createSecretKey("my-passphrase");
146
- ```
147
-
148
- The function accepts an optional `options` as well, which allows you to customize the key derivation process.
149
-
150
- ```typescript
151
- interface CreateSecretKeyOptions {
152
- // Which encryption algorithm to use (default: "aes256gcm")
153
- algorithm?: "aes256gcm" | "aes192gcm" | "aes128gcm";
154
-
155
- // Digest algorithm for HKDF (key derivation) (default: "sha256")
156
- digest?: "sha256" | "sha384" | "sha512";
157
-
158
- // 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).
159
- salt?: string;
160
-
161
- // Optional context info for HKDF (default: "cipher-kit").
162
- info?: string;
163
- }
164
- ```
165
-
166
- #### _Encrypting Data_ 🔐
167
-
168
- Ciphertext formats differ between Web and Node.js platforms.
169
-
170
- - Node.js - `iv.cipher.tag.` (3 parts)
171
- - Web - `iv.cipherWithTag.` (2 parts)
172
-
173
- ```typescript
174
- // Node.js example
175
- import { encrypt } from "cipher-kit/node";
176
-
177
- const encrypted = encrypt("Hello, World!", nodeSecretKey);
178
- console.log(`Encrypted: ${encrypted}`);
179
-
180
- // Web example
181
- import { encrypt } from "cipher-kit/web-api";
182
-
183
- const encrypted = await encrypt("Hello, World!", webSecretKey);
184
- console.log(`Encrypted: ${encrypted}`);
185
- ```
186
-
187
- The function accepts an optional `options` parameter to customize the output encoding.
188
-
189
- ```typescript
190
- interface EncryptOptions {
191
- // Output ciphertext encoding(default: "base64url")
192
- outputEncoding?: "base64url" | "base64" | "hex";
193
- }
194
- ```
195
-
196
- #### _Decrypting Data_ 🔓
197
-
198
- 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.
199
-
200
- ```typescript
201
- // Node.js example
202
- import { decrypt } from "cipher-kit/node";
203
-
204
- const decrypted = decrypt(encrypted, nodeSecretKey);
205
- console.log(`Decrypted: ${decrypted}`);
206
-
207
- // Web example
208
- import { decrypt } from "cipher-kit/web-api";
209
-
210
- const decrypted = await decrypt(encrypted, webSecretKey);
211
- console.log(`Decrypted: ${decrypted}`);
212
- ```
213
-
214
- The function accepts an optional `options` parameter to specify the input encoding.
215
-
216
- Make sure to use the same encoding that was used during encryption.
217
-
218
- ```typescript
219
- interface DecryptOptions {
220
- // Input ciphertext encoding (default: "base64url")
221
- inputEncoding?: "base64url" | "base64" | "hex";
222
- }
223
- ```
224
-
225
- #### _Encrypting & Decrypting Objects_ 🧬
226
-
227
- ```typescript
228
- // Node.js example
229
- import { encryptObj, decryptObj } from "cipher-kit/node";
230
-
231
- const obj = { name: "Alice", age: 30, city: "Wonderland" };
232
-
233
- const encryptedObj = encryptObj(obj, nodeSecretKey);
234
-
235
- const decryptedObj = decryptObj<typeof obj>(encryptedObj, nodeSecretKey);
236
- console.log(`Decrypted Object:`, decryptedObj);
237
-
238
- // Web example
239
- import { encryptObj, decryptObj } from "cipher-kit/web-api";
240
-
241
- const obj = { name: "Alice", age: 30, city: "Wonderland" };
242
-
243
- const encryptedObj = await encryptObj(obj, webSecretKey);
244
-
245
- const decryptedObj = await decryptObj<typeof obj>(encryptedObj, webSecretKey);
246
- console.log(`Decrypted Object:`, decryptedObj);
247
- ```
248
-
249
- The `encryptObj` and `decryptObj` functions accept the same `options` parameters as `encrypt` and `decrypt`, respectively.
250
-
251
- ### Hashing 🪄
252
-
253
- 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).
254
-
255
- Not suitable for storing passwords - use `hashPassword` instead.
256
-
257
- ```typescript
258
- // Node.js example
259
- import { hash } from "cipher-kit/node";
260
-
261
- const hashed = hash("Hello, World!");
262
- console.log(`Hashed: ${hashed}`);
263
-
264
- // Web example
265
- import { hash } from "cipher-kit/web-api";
266
-
267
- const hashed = await hash("Hello, World!");
268
- console.log(`Hashed: ${hashed}`);
269
- ```
270
-
271
- The function accepts an optional `options` parameter to customize the hashing process.
272
-
273
- ```typescript
274
- interface HashOptions {
275
- // Digest algorithm to use (default: "sha256").
276
- digest?: "sha256" | "sha384" | "sha512";
277
-
278
- // Output encoding (default: "base64url").
279
- outputEncoding?: "base64url" | "base64" | "hex";
280
- }
281
- ```
282
-
283
- ### UUID Generation 🪪
284
-
285
- 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.
286
-
287
- ```typescript
288
- // Node.js example
289
- import { generateUuid } from "cipher-kit/node";
290
-
291
- const uuid = generateUuid();
292
- console.log(`Generated UUID: ${uuid}`);
293
-
294
- // Web example
295
- import { generateUuid } from "cipher-kit/web-api";
296
-
297
- const uuid = generateUuid();
298
- console.log(`Generated UUID: ${uuid}`);
299
- ```
300
-
301
- ### Password Hashing & Verification 💎
302
-
303
- 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.
304
-
305
- 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.
306
-
307
- 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.
308
-
309
- ```typescript
310
- // Node.js example
311
- import { hashPassword, verifyPassword } from "cipher-kit/node";
312
-
313
- const { result, salt } = hashPassword("some-secure-password");
314
- console.log(`Hashed Password: ${result}`);
315
-
316
- const isMatch = verifyPassword("some-secure-password", result, salt);
317
- console.log(`Password match: ${isMatch}`);
318
-
319
- // Web example
320
- import { hashPassword, verifyPassword } from "cipher-kit/web-api";
321
-
322
- const { result, salt } = await hashPassword("some-secure-password");
323
- console.log(`Hashed Password: ${result}`);
324
-
325
- const isMatch = await verifyPassword("some-secure-password", result, salt);
326
- console.log(`Password match: ${isMatch}`);
327
- ```
328
-
329
- The `hashPassword` and `verifyPassword` functions accept an optional `options` parameter to customize the hashing process.
330
-
331
- ```typescript
332
- interface HashPasswordOptions {
333
- // Digest algorithm to use (default: "sha512").
334
- digest?: "sha256" | "sha384" | "sha512";
335
-
336
- // Encoding format for the output hash (default: "base64url").
337
- outputEncoding?: "base64url" | "base64" | "hex";
338
-
339
- // Length of the salt in bytes (default: 16 bytes, min: 8 bytes).
340
- saltLength?: number;
341
-
342
- // Number of iterations for key derivation (default: 320000, min: 1000).
343
- iterations?: number;
344
-
345
- // Length of the derived key in bytes (default: 64 bytes, min: 16 bytes).
346
- keyLength?: number;
347
- }
348
-
349
- interface VerifyPasswordOptions {
350
- // Digest algorithm used during the original hashing (default: `'sha512'`).
351
- digest?: "sha256" | "sha384" | "sha512";
352
-
353
- // Encoding format used during the original hashing (default: `'base64url'`).
354
- inputEncoding?: "base64url" | "base64" | "hex";
355
-
356
- // Number of iterations used during the original hashing (default: `320000`).
357
- iterations?: number;
358
-
359
- // Length of the key used during the original hashing (default: `64`).
360
- keyLength?: number;
361
- }
362
- ```
363
-
364
- ### Encoding & Decoding 🧩
365
-
366
- 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).
367
-
368
- ```typescript
369
- // Node.js and Web example - works the same in both
370
- import { convertStrToBytes, convertBytesToStr, convertEncoding } from "cipher-kit/node"; // or "cipher-kit/web-api"
371
-
372
- // Encoding
373
- const buffer = convertStrToBytes("Hello World!", "utf8"); // the input encoding
374
- console.log(`Encoded: ${buffer}`);
375
-
376
- // Decoding
377
- const str = convertBytesToStr(buffer, "utf8"); // the output encoding
378
- console.log(`Decoded: ${str}`);
379
-
380
- // Convert between encodings
381
- const base64 = convertEncoding("Hello World!", "utf8", "base64");
382
- console.log(`Base64: ${base64}`);
383
- ```
384
-
385
- ### Object Serialization & Deserialization 🧬
386
-
387
- 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.
388
-
389
- ```typescript
390
- import { stringifyObj, parseToObj } from "cipher-kit"; // works in both "cipher-kit/web-api" and "cipher-kit/node"
391
-
392
- const obj = { name: "Alice", age: 30, city: "Wonderland" };
393
-
394
- const jsonString = stringifyObj(obj);
395
- console.log(`Serialized: ${jsonString}`);
396
-
397
- const parsedObj = parseToObj<typeof obj>(jsonString);
398
- console.log(`Deserialized:`, parsedObj);
399
- ```
400
-
401
- ### Regex Utilities 🔍
402
-
403
- Regular expressions (regex) are sequences of characters that form search patterns, used for pattern matching within strings.
404
-
405
- Before decrypting, you can validate the format (decryption functions already validate internally).
406
-
407
- ```typescript
408
- import { ENCRYPTED_REGEX, matchEncryptedPattern } from "cipher-kit"; // works in both "cipher-kit/web-api" and "cipher-kit/node"
409
-
410
- function isEncryptedFormat(message: string): boolean {
411
- return matchEncryptedPattern(message, "general"); // or "node" or "web"
412
- }
413
-
414
- // or
415
-
416
- function isEncryptedFormat(message: string): boolean {
417
- return ENCRYPTED_REGEX.general.test(message); // or "node" or "web"
418
- }
419
- ```
420
-
421
- ## Contributions 🤝
422
-
423
- Want to contribute or suggest a feature or improvement?
424
-
425
- - Open an issue or feature request
426
- - Submit a PR to improve the packages or add new ones
427
- - Star ⭐ the repo if you like what you see
428
-
429
- <div align="center">
430
- <br/>
431
- <div style="font-size: 14px; font-weight:bold;"> ⚒️ Crafted carefully by <a href="https://github.com/WolfieLeader" target="_blank" rel="nofollow">WolfieLeader</a></div>
432
- <p style="font-size: 12px; font-style: italic;">This project is licensed under the <a href="https://opensource.org/licenses/MIT" target="_blank" rel="nofollow">MIT License</a>.</p>
433
- <div style="font-size: 12px; font-style: italic; font-weight: 600;">Thank you!</div>
434
- </div>
1
+ <div align="center">
2
+ <img src="https://github.com/WolfieLeader/npm/blob/main/assets/cipher-kit-banner.svg" align="center" alt="banner" />
3
+
4
+ <h1 align="center">cipher-kit</h1>
5
+
6
+ <p align="center">
7
+ Cross-platform cryptography for Node.js,<br/>
8
+ browsers, Deno, Bun, and Cloudflare Workers.
9
+ </p>
10
+
11
+ <a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/WolfieLeader/npm?color=DC343B" alt="License"></a>
12
+ <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>
13
+ <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>
14
+ <a href="https://github.com/WolfieLeader/npm" rel="nofollow"><img src="https://img.shields.io/github/stars/WolfieLeader/npm" alt="stars"></a>
15
+
16
+ </div>
17
+
18
+ ## Highlights ✨
19
+
20
+ - **Zero runtime dependencies** — fully self-contained
21
+ - **AES-256-GCM encryption** with HKDF key derivation
22
+ - **PBKDF2 password hashing** with 320K iterations and constant-time verification
23
+ - **Type-safe API** with throwing and `Result<T>` variants for every operation
24
+ - **Tree-shakable** import from `cipher-kit/node` or `cipher-kit/web-api`
25
+ - **Cross-platform** Node.js, Deno, Bun, Cloudflare Workers, and all modern browsers
26
+
27
+ ## Installation 📦
28
+
29
+ Requires Node.js >= 18.
30
+
31
+ ```bash
32
+ npm install cipher-kit
33
+ # or
34
+ pnpm add cipher-kit
35
+ ```
36
+
37
+ ## Quick Start 🚀
38
+
39
+ ```typescript
40
+ // Node.js (synchronous)
41
+ import { createSecretKey, encrypt, decrypt } from "cipher-kit/node";
42
+
43
+ const secretKey = createSecretKey("my-32-char-high-entropy-secret!!");
44
+ const encrypted = encrypt("Hello, World!", secretKey);
45
+ const decrypted = decrypt(encrypted, secretKey); // "Hello, World!"
46
+ ```
47
+
48
+ ```typescript
49
+ // Web / Deno / Bun / Cloudflare Workers (async)
50
+ import { createSecretKey, encrypt, decrypt } from "cipher-kit/web-api";
51
+
52
+ const secretKey = await createSecretKey("my-32-char-high-entropy-secret!!");
53
+ const encrypted = await encrypt("Hello, World!", secretKey);
54
+ const decrypted = await decrypt(encrypted, secretKey); // "Hello, World!"
55
+ ```
56
+
57
+ ## Imports 📥
58
+
59
+ Three import patterns are available:
60
+
61
+ ```typescript
62
+ // 1. Root export — both kits via namespace objects
63
+ import { nodeKit, webKit } from "cipher-kit";
64
+ nodeKit.encrypt("data", key);
65
+ await webKit.encrypt("data", key);
66
+
67
+ // 2. Direct Node.js import (synchronous API)
68
+ import { createSecretKey, encrypt, decrypt } from "cipher-kit/node";
69
+
70
+ // 3. Direct Web Crypto import (async API)
71
+ import { createSecretKey, encrypt, decrypt } from "cipher-kit/web-api";
72
+ ```
73
+
74
+ The root export also re-exports shared utilities: `stringifyObj`, `tryStringifyObj`, `parseToObj`, `tryParseToObj`, `ENCRYPTED_REGEX`, `matchEncryptedPattern`, and all types. All entry points expose the same utilities.
75
+
76
+ ## API Reference 📖
77
+
78
+ ### `createSecretKey` / `tryCreateSecretKey`
79
+
80
+ Derives a secret key from a high-entropy secret using HKDF.
81
+
82
+ ```typescript
83
+ import { createSecretKey, tryCreateSecretKey } from "cipher-kit/node";
84
+
85
+ // Default — AES-256-GCM with SHA-256 HKDF
86
+ const secretKey = createSecretKey("my-32-char-high-entropy-secret!!");
87
+
88
+ // Custom options
89
+ const customKey = createSecretKey("my-32-char-high-entropy-secret!!", {
90
+ algorithm: "aes128gcm",
91
+ digest: "sha512",
92
+ salt: "my-unique-app-salt",
93
+ });
94
+
95
+ // Safe variant returns Result<T> instead of throwing
96
+ const result = tryCreateSecretKey("my-32-char-high-entropy-secret!!");
97
+ if (result.success) {
98
+ console.log(result.result); // the derived NodeSecretKey / WebSecretKey
99
+ }
100
+ ```
101
+
102
+ **Options:**
103
+
104
+ | Option | Type | Default | Description |
105
+ | ------------- | ----------------------------------------------- | -------------- | -------------------------------------------------- |
106
+ | `algorithm` | `"aes256gcm"` \| `"aes192gcm"` \| `"aes128gcm"` | `"aes256gcm"` | Encryption algorithm |
107
+ | `digest` | `"sha256"` \| `"sha384"` \| `"sha512"` | `"sha256"` | HKDF digest algorithm |
108
+ | `salt` | `string` | `"cipher-kit"` | HKDF salt (min 8 chars) |
109
+ | `info` | `string` | `"cipher-kit"` | HKDF context info |
110
+ | `extractable` | `boolean` | `false` | Web CryptoKey extractable flag (no effect on Node) |
111
+
112
+ > **Security:** HKDF is a key _expansion_ function — it does not provide brute-force resistance. The `secret` must be high-entropy (e.g., a 256-bit random key). For human-chosen passwords, use `hashPassword` instead.
113
+ >
114
+ > The default `salt` is `"cipher-kit"`. Two deployments using the same secret and default salt will derive identical keys. For isolation between environments, provide a unique `salt` per deployment (e.g., `salt: "prod-us-east-1"`).
115
+
116
+ ### `encrypt` / `decrypt` / `tryEncrypt` / `tryDecrypt`
117
+
118
+ Encrypts and decrypts UTF-8 strings using the provided secret key. Output encoding defaults to `base64url`; pass `{ outputEncoding: "hex" }` or `"base64"` to change it.
119
+
120
+ ```typescript
121
+ import { createSecretKey, encrypt, decrypt, tryEncrypt } from "cipher-kit/node";
122
+
123
+ const secretKey = createSecretKey("my-32-char-high-entropy-secret!!");
124
+
125
+ const encrypted = encrypt("Hello, World!", secretKey);
126
+ const decrypted = decrypt(encrypted, secretKey); // "Hello, World!"
127
+
128
+ // Hex encoding
129
+ const hex = encrypt("Hello, World!", secretKey, { outputEncoding: "hex" });
130
+ decrypt(hex, secretKey, { inputEncoding: "hex" }); // "Hello, World!"
131
+
132
+ // Safe variant
133
+ const result = tryEncrypt("Hello, World!", secretKey);
134
+ if (result.success) {
135
+ console.log(result.result); // encrypted string
136
+ }
137
+ ```
138
+
139
+ > **Wire format:** Both platforms output `iv.cipher.tag.` (3 dot-separated segments with trailing dot). The format is **cross-platform compatible** — data encrypted on Node can be decrypted on Web and vice versa.
140
+
141
+ ### `encryptObj` / `decryptObj` / `tryEncryptObj` / `tryDecryptObj`
142
+
143
+ Encrypts and decrypts plain objects (POJOs). Class instances, Maps, Sets, etc. are rejected.
144
+
145
+ ```typescript
146
+ import { createSecretKey, encryptObj, decryptObj } from "cipher-kit/node";
147
+
148
+ const key = createSecretKey("my-32-char-high-entropy-secret!!");
149
+
150
+ const encrypted = encryptObj({ user: "Alice", role: "admin" }, key);
151
+ const obj = decryptObj<{ user: string; role: string }>(encrypted, key);
152
+ console.log(obj.user); // "Alice"
153
+ ```
154
+
155
+ ### `hash` / `tryHash`
156
+
157
+ Hashes a UTF-8 string using the specified digest algorithm. Not suitable for passwords — use `hashPassword` instead.
158
+
159
+ ```typescript
160
+ import { hash } from "cipher-kit/node";
161
+
162
+ const hashed = hash("Hello, World!"); // SHA-256, base64url
163
+
164
+ const hexHash = hash("Hello, World!", { digest: "sha512", outputEncoding: "hex" });
165
+ ```
166
+
167
+ **Options:** `digest` (`"sha256"` | `"sha384"` | `"sha512"`, default `"sha256"`), `outputEncoding` (`"base64url"` | `"base64"` | `"hex"`, default `"base64url"`).
168
+
169
+ ### `hashPassword` / `tryHashPassword` / `verifyPassword` / `tryVerifyPassword`
170
+
171
+ Hashes passwords using PBKDF2 (320K iterations by default) with constant-time verification.
172
+
173
+ ```typescript
174
+ import { hashPassword, verifyPassword } from "cipher-kit/node";
175
+
176
+ const { result, salt } = hashPassword("user-password");
177
+ // Store result and salt in your database
178
+
179
+ verifyPassword("user-password", result, salt); // true
180
+ verifyPassword("wrong-password", result, salt); // false
181
+
182
+ // Custom options
183
+ const custom = hashPassword("user-password", {
184
+ digest: "sha256",
185
+ iterations: 500_000,
186
+ saltLength: 32,
187
+ });
188
+ ```
189
+
190
+ **`hashPassword` options:** `digest` (default `"sha512"`), `outputEncoding` (default `"base64url"`), `saltLength` (default `16`, min `8`), `iterations` (default `320000`, min `100000`), `keyLength` (default `64`, min `16`).
191
+
192
+ **`verifyPassword` options:** `digest` (default `"sha512"`), `inputEncoding` (default `"base64url"`), `iterations` (default `320000`), `keyLength` (default `64`). Must match the values used during hashing.
193
+
194
+ > **Note:** Node uses `crypto.timingSafeEqual` for constant-time comparison. The Web implementation uses a best-effort full-loop XOR pattern since the Web Crypto API does not expose a `timingSafeEqual` equivalent.
195
+ >
196
+ > **Unicode normalization:** All secret and password inputs are NFKC-normalized before processing. This means that equivalent Unicode representations (e.g., `"café"` composed vs. decomposed) produce identical keys and hashes. This is the recommended approach per NIST SP 800-63B.
197
+
198
+ ### `generateUuid` / `tryGenerateUuid`
199
+
200
+ Generates a cryptographically random UUID (v4). Synchronous on both platforms.
201
+
202
+ ```typescript
203
+ import { generateUuid } from "cipher-kit/node";
204
+
205
+ const id = generateUuid(); // "550e8400-e29b-41d4-a716-446655440000"
206
+ ```
207
+
208
+ ### Encoding Utilities
209
+
210
+ Convert between strings and bytes, or re-encode between formats. Synchronous on both platforms.
211
+
212
+ ```typescript
213
+ import { convertStrToBytes, convertBytesToStr, convertEncoding } from "cipher-kit/node";
214
+
215
+ const bytes = convertStrToBytes("Hello", "utf8");
216
+ const str = convertBytesToStr(bytes, "base64url"); // "SGVsbG8"
217
+ const hex = convertEncoding("SGVsbG8", "base64url", "hex"); // "48656c6c6f"
218
+ ```
219
+
220
+ Supported encodings: `"utf8"`, `"base64"`, `"base64url"`, `"hex"`, `"latin1"`. Each function has a `try*` variant returning `Result<T>`.
221
+
222
+ ### Object Utilities
223
+
224
+ Serialize and parse plain objects with strict validation. Available from the root export and both platform entry points.
225
+
226
+ ```typescript
227
+ import { stringifyObj, parseToObj } from "cipher-kit";
228
+
229
+ const json = stringifyObj({ name: "Alice", role: "admin" });
230
+ const obj = parseToObj<{ name: string; role: string }>(json);
231
+ console.log(obj.name); // "Alice"
232
+ ```
233
+
234
+ Each function has a `try*` variant (`tryStringifyObj`, `tryParseToObj`).
235
+
236
+ ### Type Guards
237
+
238
+ ```typescript
239
+ import { isNodeSecretKey } from "cipher-kit/node";
240
+ import { isWebSecretKey } from "cipher-kit/web-api";
241
+
242
+ isNodeSecretKey(key); // true if key is NodeSecretKey
243
+ isWebSecretKey(key); // true if key is WebSecretKey
244
+ ```
245
+
246
+ ### Regex Utilities
247
+
248
+ Validate the structural shape of encrypted payloads before decryption.
249
+
250
+ ```typescript
251
+ import { ENCRYPTED_REGEX, matchEncryptedPattern } from "cipher-kit";
252
+
253
+ matchEncryptedPattern("abc.def.ghi."); // true — iv.cipher.tag.
254
+ matchEncryptedPattern("abc.def."); // false — missing tag segment
255
+ ```
256
+
257
+ `ENCRYPTED_REGEX` exposes the underlying regex: `/^([A-Za-z0-9+/_-][A-Za-z0-9+/=_-]*)\.([A-Za-z0-9+/_-][A-Za-z0-9+/=_-]*)\.([A-Za-z0-9+/_-][A-Za-z0-9+/=_-]*)\.$/`.
258
+
259
+ ## The Result Pattern 🎯
260
+
261
+ Every throwing function has a `try*` variant that returns `Result<T>` instead of throwing.
262
+
263
+ ```typescript
264
+ type Result<T> =
265
+ | ({ success: true; error?: undefined } & T) // success — value fields spread in
266
+ | { success: false; error: ErrorStruct }; // failure — error details
267
+
268
+ interface ErrorStruct {
269
+ readonly message: string;
270
+ readonly description: string;
271
+ }
272
+ ```
273
+
274
+ ```typescript
275
+ import { tryEncrypt } from "cipher-kit/node";
276
+
277
+ const result = tryEncrypt("Hello", secretKey);
278
+
279
+ if (result.success) {
280
+ console.log(result.result); // encrypted string
281
+ } else {
282
+ console.error(result.error.message, result.error.description);
283
+ }
284
+ ```
285
+
286
+ ## Type Exports 🏷️
287
+
288
+ All types are importable from any entry point:
289
+
290
+ ```typescript
291
+ import type {
292
+ NodeSecretKey,
293
+ WebSecretKey,
294
+ CreateSecretKeyOptions,
295
+ EncryptOptions,
296
+ DecryptOptions,
297
+ HashOptions,
298
+ HashPasswordOptions,
299
+ VerifyPasswordOptions,
300
+ CipherEncoding,
301
+ Encoding,
302
+ EncryptionAlgorithm,
303
+ DigestAlgorithm,
304
+ Result,
305
+ ErrorStruct,
306
+ } from "cipher-kit";
307
+ ```
308
+
309
+ ## Contributions 🤝
310
+
311
+ - Open an [issue](https://github.com/WolfieLeader/npm/issues) or feature request
312
+ - Submit a PR to improve the package
313
+ - Star the repo if you find it useful
314
+
315
+ <div align="center">
316
+ <br/>
317
+
318
+ Crafted carefully by [WolfieLeader](https://github.com/WolfieLeader)
319
+
320
+ This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
321
+
322
+ </div>