cipher-kit 0.0.1
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 +58 -0
- package/dist/chunk-57CXI3PH.js +189 -0
- package/dist/chunk-57CXI3PH.js.map +1 -0
- package/dist/chunk-GYHEGPUY.cjs +30 -0
- package/dist/chunk-GYHEGPUY.cjs.map +1 -0
- package/dist/chunk-K5MLGTAJ.js +25 -0
- package/dist/chunk-K5MLGTAJ.js.map +1 -0
- package/dist/chunk-P6FZJODK.js +116 -0
- package/dist/chunk-P6FZJODK.js.map +1 -0
- package/dist/chunk-RKUUM2D6.cjs +130 -0
- package/dist/chunk-RKUUM2D6.cjs.map +1 -0
- package/dist/chunk-SD6QP3UT.cjs +199 -0
- package/dist/chunk-SD6QP3UT.cjs.map +1 -0
- package/dist/error-FGvKfjsn.d.cts +31 -0
- package/dist/error-FGvKfjsn.d.ts +31 -0
- package/dist/index.cjs +82 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/node.cjs +45 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +21 -0
- package/dist/node.d.ts +21 -0
- package/dist/node.js +4 -0
- package/dist/node.js.map +1 -0
- package/dist/web-api.cjs +45 -0
- package/dist/web-api.cjs.map +1 -0
- package/dist/web-api.d.cts +20 -0
- package/dist/web-api.d.ts +20 -0
- package/dist/web-api.js +4 -0
- package/dist/web-api.js.map +1 -0
- package/package.json +91 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
A Secure, Lightweight, and Cross-platform Package<br/>
|
|
8
|
+
for Encryption and Decryption<br/>
|
|
9
|
+
Built for Web, Node.js, Deno, and Bun environments
|
|
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/dy/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
|
+
## About ๐
|
|
20
|
+
|
|
21
|
+
`cipher-kit` is a versatile encryption toolkit designed to work seamlessly across multiple environments, including:
|
|
22
|
+
|
|
23
|
+
- **Web** (using the Web Crypto API)
|
|
24
|
+
- **Node.js**
|
|
25
|
+
- **Deno**
|
|
26
|
+
- **Bun**
|
|
27
|
+
|
|
28
|
+
It provides a simple and secure way to encrypt and decrypt data, ensuring that your sensitive information remains protected regardless of the platform you are using, with error handling and type safety in mind.
|
|
29
|
+
|
|
30
|
+
## Features ๐
|
|
31
|
+
|
|
32
|
+
- โ
**AES-GCM** โ Uses AES-GCM for secure and authenticated encryption and decryption.
|
|
33
|
+
- ๐ **Cross-Platform Support** โ Works seamlessly in Web, Node.js, Deno, and Bun environments.
|
|
34
|
+
- ๐ซ **No External Dependencies** โ Does not rely on any external libraries or modules.
|
|
35
|
+
- ๐ **Key Derivation via SHA256** โ Derives encryption keys from passwords using SHA256.
|
|
36
|
+
- ๐งช **Strict Input Validation and `Result` Typing** - Using unified `Result<T>` type and strict input validation to ensure type safety and prevent errors.
|
|
37
|
+
|
|
38
|
+
## Installation ๐ฅ
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install cipher-kit
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> ๐ก Works with `npm`, `pnpm`, `yarn`, `bun`, and `deno`. You can use it in dev dependencies since it's typically used only for local HTTPS.
|
|
45
|
+
|
|
46
|
+
## Contributions ๐ค
|
|
47
|
+
|
|
48
|
+
Want to contribute or suggest a feature?
|
|
49
|
+
|
|
50
|
+
- Open an issue or feature request
|
|
51
|
+
- Submit a PR to improve the packages or add new ones
|
|
52
|
+
- Star โญ the repo if you like what you see
|
|
53
|
+
|
|
54
|
+
## License ๐
|
|
55
|
+
|
|
56
|
+
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
|
57
|
+
|
|
58
|
+
Thank you!
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { $err, $ok, $stringifyError, $isStr } from './chunk-K5MLGTAJ.js';
|
|
2
|
+
|
|
3
|
+
// src/web/encode.ts
|
|
4
|
+
var textEncoder = new TextEncoder();
|
|
5
|
+
var textDecoder = new TextDecoder();
|
|
6
|
+
function encode(data, format = "utf8") {
|
|
7
|
+
try {
|
|
8
|
+
switch (format) {
|
|
9
|
+
case "base64":
|
|
10
|
+
return $ok({ bytes: $fromBase64(data) });
|
|
11
|
+
case "base64url":
|
|
12
|
+
return $ok({ bytes: $fromBase64Url(data) });
|
|
13
|
+
case "hex":
|
|
14
|
+
return $ok({ bytes: $fromHex(data) });
|
|
15
|
+
case "utf8":
|
|
16
|
+
return $ok({ bytes: textEncoder.encode(data) });
|
|
17
|
+
default:
|
|
18
|
+
return $err({
|
|
19
|
+
message: `Unsupported encode format: ${format}`,
|
|
20
|
+
description: "Use base64, base64url, hex, or utf8"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return $err({ message: "Failed to encode data", description: $stringifyError(error) });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function decode(data, format = "utf8") {
|
|
28
|
+
try {
|
|
29
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
30
|
+
switch (format) {
|
|
31
|
+
case "base64":
|
|
32
|
+
return $ok($toBase64(bytes));
|
|
33
|
+
case "base64url":
|
|
34
|
+
return $ok($toBase64Url(bytes));
|
|
35
|
+
case "hex":
|
|
36
|
+
return $ok($toHex(bytes));
|
|
37
|
+
case "utf8":
|
|
38
|
+
return $ok(textDecoder.decode(bytes));
|
|
39
|
+
default:
|
|
40
|
+
return $err({
|
|
41
|
+
message: `Unsupported decode format: ${format}`,
|
|
42
|
+
description: "Use base64, base64url, hex, or utf8"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
return $err({ message: "Failed to decode data", description: $stringifyError(error) });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function $toBase64(bytes) {
|
|
50
|
+
let binary = "";
|
|
51
|
+
const chunkSize = 32768;
|
|
52
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
53
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
54
|
+
}
|
|
55
|
+
return btoa(binary);
|
|
56
|
+
}
|
|
57
|
+
function $fromBase64(data) {
|
|
58
|
+
const binary = atob(data);
|
|
59
|
+
const len = binary.length;
|
|
60
|
+
const bytes = new Uint8Array(len);
|
|
61
|
+
for (let i = 0; i < len; i++) {
|
|
62
|
+
bytes[i] = binary.charCodeAt(i);
|
|
63
|
+
}
|
|
64
|
+
return bytes;
|
|
65
|
+
}
|
|
66
|
+
function $toBase64Url(bytes) {
|
|
67
|
+
return $toBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
68
|
+
}
|
|
69
|
+
function $fromBase64Url(data) {
|
|
70
|
+
let b64 = data.replace(/-/g, "+").replace(/_/g, "/");
|
|
71
|
+
const padLen = (4 - b64.length % 4) % 4;
|
|
72
|
+
b64 += "=".repeat(padLen);
|
|
73
|
+
return $fromBase64(b64);
|
|
74
|
+
}
|
|
75
|
+
function $toHex(bytes) {
|
|
76
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
77
|
+
}
|
|
78
|
+
function $fromHex(data) {
|
|
79
|
+
const clean = data.startsWith("0x") ? data.slice(2) : data;
|
|
80
|
+
if (clean.length % 2 !== 0) throw new Error("Invalid hex string");
|
|
81
|
+
const out = new Uint8Array(clean.length / 2);
|
|
82
|
+
for (let i = 0; i < out.length; i++) {
|
|
83
|
+
out[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/web/utils.ts
|
|
89
|
+
var ENCRYPTED_WEB_API_REGEX = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.$/;
|
|
90
|
+
function newUuid() {
|
|
91
|
+
try {
|
|
92
|
+
return $ok(crypto.randomUUID());
|
|
93
|
+
} catch (error) {
|
|
94
|
+
return $err({ message: "Failed to generate UUID with Crypto Web API", description: $stringifyError(error) });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function $isWebApiKey(key) {
|
|
98
|
+
return key !== null && key !== void 0 && typeof key === "object" && "type" in key && typeof key.type === "string" && "algorithm" in key && typeof key.algorithm === "object" && "extractable" in key && typeof key.extractable === "boolean" && "usages" in key && Array.isArray(key.usages) && key.usages.every((usage) => typeof usage === "string");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/web/encrypt.ts
|
|
102
|
+
var WEB_API_ALGORITHM = "AES-GCM";
|
|
103
|
+
async function hash(data) {
|
|
104
|
+
if (!$isStr(data)) {
|
|
105
|
+
return $err({ message: "Empty data for hashing", description: "Data must be a non-empty string" });
|
|
106
|
+
}
|
|
107
|
+
const { bytes, error } = encode(data, "utf8");
|
|
108
|
+
if (error) return $err(error);
|
|
109
|
+
try {
|
|
110
|
+
const hashed = await crypto.subtle.digest("SHA-256", bytes);
|
|
111
|
+
return decode(hashed, "base64url");
|
|
112
|
+
} catch (error2) {
|
|
113
|
+
return $err({ message: "Failed to hash data with Crypto Web API", description: $stringifyError(error2) });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function newSecretKey(key) {
|
|
117
|
+
if (typeof key === "string") {
|
|
118
|
+
if (!$isStr(key, 1)) return $err({ message: "Empty key for Crypto Web API", description: "Invalid secret key" });
|
|
119
|
+
const { bytes, error } = encode(key, "utf8");
|
|
120
|
+
if (error) return $err(error);
|
|
121
|
+
try {
|
|
122
|
+
const hashedKey = await crypto.subtle.digest("SHA-256", bytes);
|
|
123
|
+
const secretKey = await crypto.subtle.importKey("raw", hashedKey, { name: WEB_API_ALGORITHM }, true, [
|
|
124
|
+
"encrypt",
|
|
125
|
+
"decrypt"
|
|
126
|
+
]);
|
|
127
|
+
return $ok({ secretKey });
|
|
128
|
+
} catch (error2) {
|
|
129
|
+
return $err({ message: "Failed to create secret key with Crypto Web API", description: $stringifyError(error2) });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (!$isWebApiKey(key)) return $err({ message: "Invalid secret key", description: "Expected a webcrypto.CryptoKey" });
|
|
133
|
+
return $ok({ secretKey: key });
|
|
134
|
+
}
|
|
135
|
+
async function encrypt(data, secretKey) {
|
|
136
|
+
if (!$isStr(data)) {
|
|
137
|
+
return $err({ message: "Empty data for encryption", description: "Data must be a non-empty string" });
|
|
138
|
+
}
|
|
139
|
+
if (!$isWebApiKey(secretKey)) {
|
|
140
|
+
return $err({ message: "Invalid encryption key", description: "Expected a webcrypto.CryptoKey" });
|
|
141
|
+
}
|
|
142
|
+
const { bytes, error } = encode(data, "utf8");
|
|
143
|
+
if (error) return $err(error);
|
|
144
|
+
try {
|
|
145
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
146
|
+
const encrypted = await crypto.subtle.encrypt({ name: WEB_API_ALGORITHM, iv }, secretKey, bytes);
|
|
147
|
+
const { result: decodedIv, error: ivError } = decode(iv, "base64url");
|
|
148
|
+
const { result: decodedEncrypted, error: encryptedError } = decode(encrypted, "base64url");
|
|
149
|
+
if (ivError || encryptedError) {
|
|
150
|
+
return $err({ message: "Failed to encode IV or encrypted data", description: "Encoding error" });
|
|
151
|
+
}
|
|
152
|
+
return $ok(`${decodedIv}.${decodedEncrypted}.`);
|
|
153
|
+
} catch (error2) {
|
|
154
|
+
return $err({ message: "Failed to encrypt data with Crypto Web API", description: $stringifyError(error2) });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function decrypt(encrypted, secretKey) {
|
|
158
|
+
if (ENCRYPTED_WEB_API_REGEX.test(encrypted) === false) {
|
|
159
|
+
return $err({
|
|
160
|
+
message: "Invalid encrypted data format",
|
|
161
|
+
description: 'Data must be in the format "iv.encryptedWithTag."'
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const [iv, encryptedWithTag] = encrypted.split(".", 3);
|
|
165
|
+
if (!$isStr(iv, 1) || !$isStr(encryptedWithTag, 1)) {
|
|
166
|
+
return $err({
|
|
167
|
+
message: "Invalid parameters for decryption",
|
|
168
|
+
description: "IV and encrypted data must be non-empty strings"
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (!$isWebApiKey(secretKey)) {
|
|
172
|
+
return $err({ message: "Invalid decryption key", description: "Expected a webcrypto.CryptoKey" });
|
|
173
|
+
}
|
|
174
|
+
const { bytes: ivBytes, error: ivError } = encode(iv, "base64url");
|
|
175
|
+
const { bytes: encryptedBytes, error: encryptedError } = encode(encryptedWithTag, "base64url");
|
|
176
|
+
if (ivError || encryptedError) {
|
|
177
|
+
return $err({ message: "Failed to encode IV or encrypted data", description: "Encoding error" });
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const decrypted = await crypto.subtle.decrypt({ name: WEB_API_ALGORITHM, iv: ivBytes }, secretKey, encryptedBytes);
|
|
181
|
+
return decode(decrypted, "utf8");
|
|
182
|
+
} catch (error) {
|
|
183
|
+
return $err({ message: "Failed to decrypt data with Crypto Web API", description: $stringifyError(error) });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { ENCRYPTED_WEB_API_REGEX, WEB_API_ALGORITHM, decode, decrypt, encode, encrypt, hash, newSecretKey, newUuid };
|
|
188
|
+
//# sourceMappingURL=chunk-57CXI3PH.js.map
|
|
189
|
+
//# sourceMappingURL=chunk-57CXI3PH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web/encode.ts","../src/web/utils.ts","../src/web/encrypt.ts"],"names":["error"],"mappings":";;;AAGA,IAAM,WAAA,GAAc,IAAI,WAAA,EAAY;AACpC,IAAM,WAAA,GAAc,IAAI,WAAA,EAAY;AAE7B,SAAS,MAAA,CAAO,IAAA,EAAc,MAAA,GAAyB,MAAA,EAAuC;AACnG,EAAA,IAAI;AACF,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,QAAA;AACH,QAAA,OAAO,IAAI,EAAE,KAAA,EAAO,WAAA,CAAY,IAAI,GAAG,CAAA;AAAA,MACzC,KAAK,WAAA;AACH,QAAA,OAAO,IAAI,EAAE,KAAA,EAAO,cAAA,CAAe,IAAI,GAAG,CAAA;AAAA,MAC5C,KAAK,KAAA;AACH,QAAA,OAAO,IAAI,EAAE,KAAA,EAAO,QAAA,CAAS,IAAI,GAAG,CAAA;AAAA,MACtC,KAAK,MAAA;AACH,QAAA,OAAO,IAAI,EAAE,KAAA,EAAO,YAAY,MAAA,CAAO,IAAI,GAAG,CAAA;AAAA,MAChD;AACE,QAAA,OAAO,IAAA,CAAK;AAAA,UACV,OAAA,EAAS,8BAA8B,MAAM,CAAA,CAAA;AAAA,UAC7C,WAAA,EAAa;AAAA,SACd,CAAA;AAAA;AACL,EACF,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,uBAAA,EAAyB,aAAa,eAAA,CAAgB,KAAK,GAAG,CAAA;AAAA,EACvF;AACF;AAEO,SAAS,MAAA,CAAO,IAAA,EAAgC,MAAA,GAAyB,MAAA,EAAwB;AACtG,EAAA,IAAI;AACF,IAAA,MAAM,QAAQ,IAAA,YAAgB,UAAA,GAAa,IAAA,GAAO,IAAI,WAAW,IAAI,CAAA;AACrE,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,QAAA;AACH,QAAA,OAAO,GAAA,CAAI,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,MAC7B,KAAK,WAAA;AACH,QAAA,OAAO,GAAA,CAAI,YAAA,CAAa,KAAK,CAAC,CAAA;AAAA,MAChC,KAAK,KAAA;AACH,QAAA,OAAO,GAAA,CAAI,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,MAC1B,KAAK,MAAA;AACH,QAAA,OAAO,GAAA,CAAI,WAAA,CAAY,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,MACtC;AACE,QAAA,OAAO,IAAA,CAAK;AAAA,UACV,OAAA,EAAS,8BAA8B,MAAM,CAAA,CAAA;AAAA,UAC7C,WAAA,EAAa;AAAA,SACd,CAAA;AAAA;AACL,EACF,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,uBAAA,EAAyB,aAAa,eAAA,CAAgB,KAAK,GAAG,CAAA;AAAA,EACvF;AACF;AAEA,SAAS,UAAU,KAAA,EAA2B;AAC5C,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,MAAM,SAAA,GAAY,KAAA;AAClB,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,KAAK,SAAA,EAAW;AAChD,IAAA,MAAA,IAAU,MAAA,CAAO,aAAa,GAAG,KAAA,CAAM,SAAS,CAAA,EAAG,CAAA,GAAI,SAAS,CAAC,CAAA;AAAA,EACnE;AACA,EAAA,OAAO,KAAK,MAAM,CAAA;AACpB;AAEA,SAAS,YAAY,IAAA,EAA0B;AAC7C,EAAA,MAAM,MAAA,GAAS,KAAK,IAAI,CAAA;AACxB,EAAA,MAAM,MAAM,MAAA,CAAO,MAAA;AACnB,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,GAAG,CAAA;AAChC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,EAAK,CAAA,EAAA,EAAK;AAC5B,IAAA,KAAA,CAAM,CAAC,CAAA,GAAI,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA;AAAA,EAChC;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,aAAa,KAAA,EAA2B;AAC/C,EAAA,OAAO,SAAA,CAAU,KAAK,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACnF;AAEA,SAAS,eAAe,IAAA,EAA0B;AAChD,EAAA,IAAI,GAAA,GAAM,KAAK,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,OAAA,CAAQ,MAAM,GAAG,CAAA;AACnD,EAAA,MAAM,MAAA,GAAA,CAAU,CAAA,GAAK,GAAA,CAAI,MAAA,GAAS,CAAA,IAAM,CAAA;AACxC,EAAA,GAAA,IAAO,GAAA,CAAI,OAAO,MAAM,CAAA;AACxB,EAAA,OAAO,YAAY,GAAG,CAAA;AACxB;AAEA,SAAS,OAAO,KAAA,EAA2B;AACzC,EAAA,OAAO,MAAM,IAAA,CAAK,KAAK,CAAA,CACpB,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AACZ;AAEA,SAAS,SAAS,IAAA,EAA0B;AAC1C,EAAA,MAAM,KAAA,GAAQ,KAAK,UAAA,CAAW,IAAI,IAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA;AACtD,EAAA,IAAI,MAAM,MAAA,GAAS,CAAA,KAAM,GAAG,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAChE,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,KAAA,CAAM,SAAS,CAAC,CAAA;AAC3C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,KAAA,CAAM,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,GAAI,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,GAAA;AACT;;;AC5FO,IAAM,uBAAA,GAA0B;AAEhC,SAAS,OAAA,GAA0B;AACxC,EAAA,IAAI;AACF,IAAA,OAAO,GAAA,CAAI,MAAA,CAAO,UAAA,EAAY,CAAA;AAAA,EAChC,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,6CAAA,EAA+C,aAAa,eAAA,CAAgB,KAAK,GAAG,CAAA;AAAA,EAC7G;AACF;AAEO,SAAS,aAAa,GAAA,EAAgC;AAC3D,EAAA,OACE,QAAQ,IAAA,IACR,GAAA,KAAQ,MAAA,IACR,OAAO,QAAQ,QAAA,IACf,MAAA,IAAU,GAAA,IACV,OAAO,IAAI,IAAA,KAAS,QAAA,IACpB,eAAe,GAAA,IACf,OAAO,IAAI,SAAA,KAAc,QAAA,IACzB,aAAA,IAAiB,GAAA,IACjB,OAAO,GAAA,CAAI,WAAA,KAAgB,aAC3B,QAAA,IAAY,GAAA,IACZ,MAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IACxB,IAAI,MAAA,CAAO,KAAA,CAAM,CAAC,KAAA,KAAU,OAAO,UAAU,QAAQ,CAAA;AAEzD;;;ACtBO,IAAM,iBAAA,GAAoB;AAEjC,eAAsB,KAAK,IAAA,EAAuC;AAChE,EAAA,IAAI,CAAC,MAAA,CAAO,IAAI,CAAA,EAAG;AACjB,IAAA,OAAO,KAAK,EAAE,OAAA,EAAS,wBAAA,EAA0B,WAAA,EAAa,mCAAmC,CAAA;AAAA,EACnG;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,GAAI,MAAA,CAAO,MAAM,MAAM,CAAA;AAC5C,EAAA,IAAI,KAAA,EAAO,OAAO,IAAA,CAAK,KAAK,CAAA;AAE5B,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,KAAK,CAAA;AAC1D,IAAA,OAAO,MAAA,CAAO,QAAQ,WAAW,CAAA;AAAA,EACnC,SAASA,MAAAA,EAAO;AACd,IAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,yCAAA,EAA2C,aAAa,eAAA,CAAgBA,MAAK,GAAG,CAAA;AAAA,EACzG;AACF;AAEA,eAAsB,aAAa,GAAA,EAAoE;AACrG,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,MAAA,CAAO,GAAA,EAAK,CAAC,CAAA,EAAG,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,8BAAA,EAAgC,WAAA,EAAa,oBAAA,EAAsB,CAAA;AAE/G,IAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,GAAI,MAAA,CAAO,KAAK,MAAM,CAAA;AAC3C,IAAA,IAAI,KAAA,EAAO,OAAO,IAAA,CAAK,KAAK,CAAA;AAE5B,IAAA,IAAI;AACF,MAAA,MAAM,YAAY,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,KAAK,CAAA;AAC7D,MAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,EAAE,IAAA,EAAM,iBAAA,EAAkB,EAAG,IAAA,EAAM;AAAA,QACnG,SAAA;AAAA,QACA;AAAA,OACD,CAAA;AACD,MAAA,OAAO,GAAA,CAAI,EAAE,SAAA,EAAW,CAAA;AAAA,IAC1B,SAASA,MAAAA,EAAO;AACd,MAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,iDAAA,EAAmD,aAAa,eAAA,CAAgBA,MAAK,GAAG,CAAA;AAAA,IACjH;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,YAAA,CAAa,GAAG,CAAA,EAAG,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,oBAAA,EAAsB,WAAA,EAAa,gCAAA,EAAkC,CAAA;AACpH,EAAA,OAAO,GAAA,CAAI,EAAE,SAAA,EAAW,GAAA,EAAK,CAAA;AAC/B;AAEA,eAAsB,OAAA,CAAQ,MAAc,SAAA,EAA+C;AACzF,EAAA,IAAI,CAAC,MAAA,CAAO,IAAI,CAAA,EAAG;AACjB,IAAA,OAAO,KAAK,EAAE,OAAA,EAAS,2BAAA,EAA6B,WAAA,EAAa,mCAAmC,CAAA;AAAA,EACtG;AAEA,EAAA,IAAI,CAAC,YAAA,CAAa,SAAS,CAAA,EAAG;AAC5B,IAAA,OAAO,KAAK,EAAE,OAAA,EAAS,wBAAA,EAA0B,WAAA,EAAa,kCAAkC,CAAA;AAAA,EAClG;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,GAAI,MAAA,CAAO,MAAM,MAAM,CAAA;AAC5C,EAAA,IAAI,KAAA,EAAO,OAAO,IAAA,CAAK,KAAK,CAAA;AAE5B,EAAA,IAAI;AACF,IAAA,MAAM,KAAK,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,EAAE,IAAA,EAAM,iBAAA,EAAmB,EAAA,EAAO,EAAG,SAAA,EAAW,KAAK,CAAA;AAEnG,IAAA,MAAM,EAAE,QAAQ,SAAA,EAAW,KAAA,EAAO,SAAQ,GAAI,MAAA,CAAO,IAAI,WAAW,CAAA;AACpE,IAAA,MAAM,EAAE,QAAQ,gBAAA,EAAkB,KAAA,EAAO,gBAAe,GAAI,MAAA,CAAO,WAAW,WAAW,CAAA;AAEzF,IAAA,IAAI,WAAW,cAAA,EAAgB;AAC7B,MAAA,OAAO,KAAK,EAAE,OAAA,EAAS,uCAAA,EAAyC,WAAA,EAAa,kBAAkB,CAAA;AAAA,IACjG;AAEA,IAAA,OAAO,GAAA,CAAI,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,gBAAgB,CAAA,CAAA,CAAG,CAAA;AAAA,EAChD,SAASA,MAAAA,EAAO;AACd,IAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,4CAAA,EAA8C,aAAa,eAAA,CAAgBA,MAAK,GAAG,CAAA;AAAA,EAC5G;AACF;AAEA,eAAsB,OAAA,CAAQ,WAAmB,SAAA,EAA+C;AAC9F,EAAA,IAAI,uBAAA,CAAwB,IAAA,CAAK,SAAS,CAAA,KAAM,KAAA,EAAO;AACrD,IAAA,OAAO,IAAA,CAAK;AAAA,MACV,OAAA,EAAS,+BAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,CAAC,EAAA,EAAI,gBAAgB,IAAI,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,CAAA;AACrD,EAAA,IAAI,CAAC,OAAO,EAAA,EAAI,CAAC,KAAK,CAAC,MAAA,CAAO,gBAAA,EAAkB,CAAC,CAAA,EAAG;AAClD,IAAA,OAAO,IAAA,CAAK;AAAA,MACV,OAAA,EAAS,mCAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,CAAC,YAAA,CAAa,SAAS,CAAA,EAAG;AAC5B,IAAA,OAAO,KAAK,EAAE,OAAA,EAAS,wBAAA,EAA0B,WAAA,EAAa,kCAAkC,CAAA;AAAA,EAClG;AAEA,EAAA,MAAM,EAAE,OAAO,OAAA,EAAS,KAAA,EAAO,SAAQ,GAAI,MAAA,CAAO,IAAI,WAAW,CAAA;AACjE,EAAA,MAAM,EAAE,OAAO,cAAA,EAAgB,KAAA,EAAO,gBAAe,GAAI,MAAA,CAAO,kBAAkB,WAAW,CAAA;AAC7F,EAAA,IAAI,WAAW,cAAA,EAAgB;AAC7B,IAAA,OAAO,KAAK,EAAE,OAAA,EAAS,uCAAA,EAAyC,WAAA,EAAa,kBAAkB,CAAA;AAAA,EACjG;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,EAAE,IAAA,EAAM,iBAAA,EAAmB,EAAA,EAAI,OAAA,EAAQ,EAAG,SAAA,EAAW,cAAc,CAAA;AAEjH,IAAA,OAAO,MAAA,CAAO,WAAW,MAAM,CAAA;AAAA,EACjC,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,IAAA,CAAK,EAAE,OAAA,EAAS,4CAAA,EAA8C,aAAa,eAAA,CAAgB,KAAK,GAAG,CAAA;AAAA,EAC5G;AACF","file":"chunk-57CXI3PH.js","sourcesContent":["import { $err, $ok, $stringifyError, type Result } from '~/error';\r\nimport type { EncodingFormat } from '~/types';\r\n\r\nconst textEncoder = new TextEncoder();\r\nconst textDecoder = new TextDecoder();\r\n\r\nexport function encode(data: string, format: EncodingFormat = 'utf8'): Result<{ bytes: Uint8Array }> {\r\n try {\r\n switch (format) {\r\n case 'base64':\r\n return $ok({ bytes: $fromBase64(data) });\r\n case 'base64url':\r\n return $ok({ bytes: $fromBase64Url(data) });\r\n case 'hex':\r\n return $ok({ bytes: $fromHex(data) });\r\n case 'utf8':\r\n return $ok({ bytes: textEncoder.encode(data) });\r\n default:\r\n return $err({\r\n message: `Unsupported encode format: ${format}`,\r\n description: 'Use base64, base64url, hex, or utf8',\r\n });\r\n }\r\n } catch (error) {\r\n return $err({ message: 'Failed to encode data', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport function decode(data: ArrayBuffer | Uint8Array, format: EncodingFormat = 'utf8'): Result<string> {\r\n try {\r\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\r\n switch (format) {\r\n case 'base64':\r\n return $ok($toBase64(bytes));\r\n case 'base64url':\r\n return $ok($toBase64Url(bytes));\r\n case 'hex':\r\n return $ok($toHex(bytes));\r\n case 'utf8':\r\n return $ok(textDecoder.decode(bytes));\r\n default:\r\n return $err({\r\n message: `Unsupported decode format: ${format}`,\r\n description: 'Use base64, base64url, hex, or utf8',\r\n });\r\n }\r\n } catch (error) {\r\n return $err({ message: 'Failed to decode data', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nfunction $toBase64(bytes: Uint8Array): string {\r\n let binary = '';\r\n const chunkSize = 0x8000; // 32KB per chunk\r\n for (let i = 0; i < bytes.length; i += chunkSize) {\r\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\r\n }\r\n return btoa(binary);\r\n}\r\n\r\nfunction $fromBase64(data: string): Uint8Array {\r\n const binary = atob(data);\r\n const len = binary.length;\r\n const bytes = new Uint8Array(len);\r\n for (let i = 0; i < len; i++) {\r\n bytes[i] = binary.charCodeAt(i);\r\n }\r\n return bytes;\r\n}\r\n\r\nfunction $toBase64Url(bytes: Uint8Array): string {\r\n return $toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\r\n}\r\n\r\nfunction $fromBase64Url(data: string): Uint8Array {\r\n let b64 = data.replace(/-/g, '+').replace(/_/g, '/');\r\n const padLen = (4 - (b64.length % 4)) % 4;\r\n b64 += '='.repeat(padLen);\r\n return $fromBase64(b64);\r\n}\r\n\r\nfunction $toHex(bytes: Uint8Array): string {\r\n return Array.from(bytes)\r\n .map((b) => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n}\r\n\r\nfunction $fromHex(data: string): Uint8Array {\r\n const clean = data.startsWith('0x') ? data.slice(2) : data;\r\n if (clean.length % 2 !== 0) throw new Error('Invalid hex string');\r\n const out = new Uint8Array(clean.length / 2);\r\n for (let i = 0; i < out.length; i++) {\r\n out[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\r\n }\r\n return out;\r\n}\r\n","import { $err, $ok, $stringifyError, type Result } from '~/error';\r\nimport type { WebApiKey } from '~/types';\r\n\r\nexport const ENCRYPTED_WEB_API_REGEX = /^([A-Za-z0-9_-]+)\\.([A-Za-z0-9_-]+)\\.$/;\r\n\r\nexport function newUuid(): Result<string> {\r\n try {\r\n return $ok(crypto.randomUUID());\r\n } catch (error) {\r\n return $err({ message: 'Failed to generate UUID with Crypto Web API', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport function $isWebApiKey(key: unknown): key is WebApiKey {\r\n return (\r\n key !== null &&\r\n key !== undefined &&\r\n typeof key === 'object' &&\r\n 'type' in key &&\r\n typeof key.type === 'string' &&\r\n 'algorithm' in key &&\r\n typeof key.algorithm === 'object' &&\r\n 'extractable' in key &&\r\n typeof key.extractable === 'boolean' &&\r\n 'usages' in key &&\r\n Array.isArray(key.usages) &&\r\n key.usages.every((usage) => typeof usage === 'string')\r\n );\r\n}\r\n","import { $err, $ok, $stringifyError, type Result } from '~/error';\r\nimport type { WebApiKey } from '~/types';\r\nimport { $isStr } from '~/utils';\r\nimport { decode, encode } from './encode';\r\nimport { $isWebApiKey, ENCRYPTED_WEB_API_REGEX } from './utils';\r\n\r\nexport const WEB_API_ALGORITHM = 'AES-GCM';\r\n\r\nexport async function hash(data: string): Promise<Result<string>> {\r\n if (!$isStr(data)) {\r\n return $err({ message: 'Empty data for hashing', description: 'Data must be a non-empty string' });\r\n }\r\n\r\n const { bytes, error } = encode(data, 'utf8');\r\n if (error) return $err(error);\r\n\r\n try {\r\n const hashed = await crypto.subtle.digest('SHA-256', bytes);\r\n return decode(hashed, 'base64url');\r\n } catch (error) {\r\n return $err({ message: 'Failed to hash data with Crypto Web API', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport async function newSecretKey(key: string | WebApiKey): Promise<Result<{ secretKey: WebApiKey }>> {\r\n if (typeof key === 'string') {\r\n if (!$isStr(key, 1)) return $err({ message: 'Empty key for Crypto Web API', description: 'Invalid secret key' });\r\n\r\n const { bytes, error } = encode(key, 'utf8');\r\n if (error) return $err(error);\r\n\r\n try {\r\n const hashedKey = await crypto.subtle.digest('SHA-256', bytes);\r\n const secretKey = await crypto.subtle.importKey('raw', hashedKey, { name: WEB_API_ALGORITHM }, true, [\r\n 'encrypt',\r\n 'decrypt',\r\n ]);\r\n return $ok({ secretKey });\r\n } catch (error) {\r\n return $err({ message: 'Failed to create secret key with Crypto Web API', description: $stringifyError(error) });\r\n }\r\n }\r\n\r\n if (!$isWebApiKey(key)) return $err({ message: 'Invalid secret key', description: 'Expected a webcrypto.CryptoKey' });\r\n return $ok({ secretKey: key });\r\n}\r\n\r\nexport async function encrypt(data: string, secretKey: WebApiKey): Promise<Result<string>> {\r\n if (!$isStr(data)) {\r\n return $err({ message: 'Empty data for encryption', description: 'Data must be a non-empty string' });\r\n }\r\n\r\n if (!$isWebApiKey(secretKey)) {\r\n return $err({ message: 'Invalid encryption key', description: 'Expected a webcrypto.CryptoKey' });\r\n }\r\n\r\n const { bytes, error } = encode(data, 'utf8');\r\n if (error) return $err(error);\r\n\r\n try {\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n const encrypted = await crypto.subtle.encrypt({ name: WEB_API_ALGORITHM, iv: iv }, secretKey, bytes);\r\n\r\n const { result: decodedIv, error: ivError } = decode(iv, 'base64url');\r\n const { result: decodedEncrypted, error: encryptedError } = decode(encrypted, 'base64url');\r\n\r\n if (ivError || encryptedError) {\r\n return $err({ message: 'Failed to encode IV or encrypted data', description: 'Encoding error' });\r\n }\r\n\r\n return $ok(`${decodedIv}.${decodedEncrypted}.`);\r\n } catch (error) {\r\n return $err({ message: 'Failed to encrypt data with Crypto Web API', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport async function decrypt(encrypted: string, secretKey: WebApiKey): Promise<Result<string>> {\r\n if (ENCRYPTED_WEB_API_REGEX.test(encrypted) === false) {\r\n return $err({\r\n message: 'Invalid encrypted data format',\r\n description: 'Data must be in the format \"iv.encryptedWithTag.\"',\r\n });\r\n }\r\n\r\n const [iv, encryptedWithTag] = encrypted.split('.', 3);\r\n if (!$isStr(iv, 1) || !$isStr(encryptedWithTag, 1)) {\r\n return $err({\r\n message: 'Invalid parameters for decryption',\r\n description: 'IV and encrypted data must be non-empty strings',\r\n });\r\n }\r\n\r\n if (!$isWebApiKey(secretKey)) {\r\n return $err({ message: 'Invalid decryption key', description: 'Expected a webcrypto.CryptoKey' });\r\n }\r\n\r\n const { bytes: ivBytes, error: ivError } = encode(iv, 'base64url');\r\n const { bytes: encryptedBytes, error: encryptedError } = encode(encryptedWithTag, 'base64url');\r\n if (ivError || encryptedError) {\r\n return $err({ message: 'Failed to encode IV or encrypted data', description: 'Encoding error' });\r\n }\r\n\r\n try {\r\n const decrypted = await crypto.subtle.decrypt({ name: WEB_API_ALGORITHM, iv: ivBytes }, secretKey, encryptedBytes);\r\n\r\n return decode(decrypted, 'utf8');\r\n } catch (error) {\r\n return $err({ message: 'Failed to decrypt data with Crypto Web API', description: $stringifyError(error) });\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/utils.ts
|
|
4
|
+
function $isStr(value, min = 0) {
|
|
5
|
+
return (value !== null || value !== void 0) && typeof value === "string" && value.trim().length >= min;
|
|
6
|
+
}
|
|
7
|
+
function $isObj(value) {
|
|
8
|
+
return typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/error.ts
|
|
12
|
+
function $ok(result) {
|
|
13
|
+
if ($isObj(result)) return { success: true, ...result };
|
|
14
|
+
return { success: true, result };
|
|
15
|
+
}
|
|
16
|
+
function $err(typeOrErr) {
|
|
17
|
+
return { success: false, error: typeOrErr };
|
|
18
|
+
}
|
|
19
|
+
function $stringifyError(error) {
|
|
20
|
+
if (error instanceof Error) return error.message;
|
|
21
|
+
if (typeof error === "string") return error;
|
|
22
|
+
return String(error);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.$err = $err;
|
|
26
|
+
exports.$isStr = $isStr;
|
|
27
|
+
exports.$ok = $ok;
|
|
28
|
+
exports.$stringifyError = $stringifyError;
|
|
29
|
+
//# sourceMappingURL=chunk-GYHEGPUY.cjs.map
|
|
30
|
+
//# sourceMappingURL=chunk-GYHEGPUY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/error.ts"],"names":[],"mappings":";;;AAAO,SAAS,MAAA,CAAO,KAAA,EAAgB,GAAA,GAAM,CAAA,EAAoB;AAC/D,EAAA,OAAA,CAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,KAAc,OAAO,UAAU,QAAA,IAAY,KAAA,CAAM,IAAA,EAAK,CAAE,MAAA,IAAU,GAAA;AACxG;AAEO,SAAS,OAAO,KAAA,EAAkD;AACvE,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,SACT,MAAA,CAAO,cAAA,CAAe,KAAK,CAAA,KAAM,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,cAAA,CAAe,KAAK,CAAA,KAAM,IAAA,CAAA;AAE3F;;;ACKO,SAAS,IAAO,MAAA,EAAuB;AAC5C,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,GAAI,MAAA,EAAsB;AACtE,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,MAAA,EAAO;AACjC;AAIO,SAAS,KAAK,SAAA,EAA2F;AAC9G,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,SAAA,EAAU;AAC5C;AAEO,SAAS,gBAAgB,KAAA,EAAwB;AACtD,EAAA,IAAI,KAAA,YAAiB,KAAA,EAAO,OAAO,KAAA,CAAM,OAAA;AACzC,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB","file":"chunk-GYHEGPUY.cjs","sourcesContent":["export function $isStr(value: unknown, min = 0): value is string {\r\n return (value !== null || value !== undefined) && typeof value === 'string' && value.trim().length >= min;\r\n}\r\n\r\nexport function $isObj(value: unknown): value is Record<string, unknown> {\r\n return (\r\n typeof value === 'object' &&\r\n value !== null &&\r\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)\r\n );\r\n}\r\n","import { $isObj } from './utils';\r\n\r\nexport interface ResultErr {\r\n readonly message: string;\r\n readonly description: string;\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(typeOrErr: { message: string; description: string }): Result<never, ResultErr>;\r\nexport function $err(typeOrErr: ResultErr): Result<never, ResultErr>;\r\nexport function $err(typeOrErr: { message: string; description: string } | ResultErr): Result<never, ResultErr> {\r\n return { success: false, error: typeOrErr } as Result<never, ResultErr>;\r\n}\r\n\r\nexport function $stringifyError(error: unknown): string {\r\n if (error instanceof Error) return error.message;\r\n if (typeof error === 'string') return error;\r\n return String(error);\r\n}\r\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
function $isStr(value, min = 0) {
|
|
3
|
+
return (value !== null || value !== void 0) && typeof value === "string" && value.trim().length >= min;
|
|
4
|
+
}
|
|
5
|
+
function $isObj(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// src/error.ts
|
|
10
|
+
function $ok(result) {
|
|
11
|
+
if ($isObj(result)) return { success: true, ...result };
|
|
12
|
+
return { success: true, result };
|
|
13
|
+
}
|
|
14
|
+
function $err(typeOrErr) {
|
|
15
|
+
return { success: false, error: typeOrErr };
|
|
16
|
+
}
|
|
17
|
+
function $stringifyError(error) {
|
|
18
|
+
if (error instanceof Error) return error.message;
|
|
19
|
+
if (typeof error === "string") return error;
|
|
20
|
+
return String(error);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { $err, $isStr, $ok, $stringifyError };
|
|
24
|
+
//# sourceMappingURL=chunk-K5MLGTAJ.js.map
|
|
25
|
+
//# sourceMappingURL=chunk-K5MLGTAJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/error.ts"],"names":[],"mappings":";AAAO,SAAS,MAAA,CAAO,KAAA,EAAgB,GAAA,GAAM,CAAA,EAAoB;AAC/D,EAAA,OAAA,CAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,KAAc,OAAO,UAAU,QAAA,IAAY,KAAA,CAAM,IAAA,EAAK,CAAE,MAAA,IAAU,GAAA;AACxG;AAEO,SAAS,OAAO,KAAA,EAAkD;AACvE,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,SACT,MAAA,CAAO,cAAA,CAAe,KAAK,CAAA,KAAM,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,cAAA,CAAe,KAAK,CAAA,KAAM,IAAA,CAAA;AAE3F;;;ACKO,SAAS,IAAO,MAAA,EAAuB;AAC5C,EAAA,IAAI,MAAA,CAAO,MAAM,CAAA,EAAG,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,GAAI,MAAA,EAAsB;AACtE,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,MAAA,EAAO;AACjC;AAIO,SAAS,KAAK,SAAA,EAA2F;AAC9G,EAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,SAAA,EAAU;AAC5C;AAEO,SAAS,gBAAgB,KAAA,EAAwB;AACtD,EAAA,IAAI,KAAA,YAAiB,KAAA,EAAO,OAAO,KAAA,CAAM,OAAA;AACzC,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,OAAO,OAAO,KAAK,CAAA;AACrB","file":"chunk-K5MLGTAJ.js","sourcesContent":["export function $isStr(value: unknown, min = 0): value is string {\r\n return (value !== null || value !== undefined) && typeof value === 'string' && value.trim().length >= min;\r\n}\r\n\r\nexport function $isObj(value: unknown): value is Record<string, unknown> {\r\n return (\r\n typeof value === 'object' &&\r\n value !== null &&\r\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null)\r\n );\r\n}\r\n","import { $isObj } from './utils';\r\n\r\nexport interface ResultErr {\r\n readonly message: string;\r\n readonly description: string;\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(typeOrErr: { message: string; description: string }): Result<never, ResultErr>;\r\nexport function $err(typeOrErr: ResultErr): Result<never, ResultErr>;\r\nexport function $err(typeOrErr: { message: string; description: string } | ResultErr): Result<never, ResultErr> {\r\n return { success: false, error: typeOrErr } as Result<never, ResultErr>;\r\n}\r\n\r\nexport function $stringifyError(error: unknown): string {\r\n if (error instanceof Error) return error.message;\r\n if (typeof error === 'string') return error;\r\n return String(error);\r\n}\r\n"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { $ok, $err, $stringifyError, $isStr } from './chunk-K5MLGTAJ.js';
|
|
2
|
+
import { Buffer } from 'buffer';
|
|
3
|
+
import nodeCrypto2 from 'crypto';
|
|
4
|
+
|
|
5
|
+
function encode(data, format = "utf8") {
|
|
6
|
+
try {
|
|
7
|
+
return $ok({ bytes: Buffer.from(data, format) });
|
|
8
|
+
} catch (error) {
|
|
9
|
+
return $err({ message: "Failed to encode data", description: $stringifyError(error) });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function decode(data, format = "utf8") {
|
|
13
|
+
try {
|
|
14
|
+
return $ok(Buffer.from(data).toString(format));
|
|
15
|
+
} catch (error) {
|
|
16
|
+
return $err({ message: "Failed to decode data", description: $stringifyError(error) });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
var ENCRYPTED_NODE_REGEX = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.$/;
|
|
20
|
+
function newUuid() {
|
|
21
|
+
try {
|
|
22
|
+
return $ok(nodeCrypto2.randomUUID());
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return $err({ message: "Failed to generate UUID with Crypto NodeJS", description: $stringifyError(error) });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function $isNodeKey(key) {
|
|
28
|
+
return key instanceof nodeCrypto2.KeyObject;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/node/encrypt.ts
|
|
32
|
+
var NODE_ALGORITHM = "aes-256-gcm";
|
|
33
|
+
function hash(data) {
|
|
34
|
+
if (!$isStr(data)) {
|
|
35
|
+
return $err({ message: "Empty data for hashing", description: "Data must be a non-empty string" });
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const hashed = nodeCrypto2.createHash("sha256").update(data).digest();
|
|
39
|
+
return decode(hashed, "base64url");
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return $err({ message: "Failed to hash data with Crypto NodeJS", description: $stringifyError(error) });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function newSecretKey(key) {
|
|
45
|
+
if (typeof key === "string") {
|
|
46
|
+
if (!$isStr(key, 1)) return $err({ message: "Empty key for Crypto NodeJS", description: "Invalid secret key" });
|
|
47
|
+
try {
|
|
48
|
+
const hashedKey = nodeCrypto2.createHash("sha256").update(key).digest();
|
|
49
|
+
const secretKey = nodeCrypto2.createSecretKey(hashedKey);
|
|
50
|
+
return $ok({ secretKey });
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return $err({ message: "Failed to create secret key with Crypto NodeJS", description: $stringifyError(error) });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!$isNodeKey(key)) return $err({ message: "Invalid secret key", description: "Expected a crypto.KeyObject" });
|
|
56
|
+
return $ok({ secretKey: key });
|
|
57
|
+
}
|
|
58
|
+
function encrypt(data, secretKey) {
|
|
59
|
+
if (!$isStr(data)) {
|
|
60
|
+
return $err({ message: "Empty data for encryption", description: "Data must be a non-empty string" });
|
|
61
|
+
}
|
|
62
|
+
if (!$isNodeKey(secretKey)) {
|
|
63
|
+
return $err({ message: "Invalid encryption key", description: "Expected a crypto.KeyObject" });
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const iv = nodeCrypto2.randomBytes(12);
|
|
67
|
+
const cipher = nodeCrypto2.createCipheriv(NODE_ALGORITHM, secretKey, iv);
|
|
68
|
+
const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
69
|
+
const tag = cipher.getAuthTag();
|
|
70
|
+
const { result: decodedIv, error: ivError } = decode(iv, "base64url");
|
|
71
|
+
const { result: decodedEncrypted, error: encryptedError } = decode(encrypted, "base64url");
|
|
72
|
+
const { result: decodedTag, error: tagError } = decode(tag, "base64url");
|
|
73
|
+
if (ivError || encryptedError || tagError) {
|
|
74
|
+
return $err({ message: "Failed to encode encrypted data", description: "Encoding error" });
|
|
75
|
+
}
|
|
76
|
+
return $ok(`${decodedIv}.${decodedEncrypted}.${decodedTag}.`);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
return $err({ message: "Failed to encrypt data with Crypto NodeJS", description: $stringifyError(error) });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function decrypt(encrypted, secretKey) {
|
|
82
|
+
if (ENCRYPTED_NODE_REGEX.test(encrypted) === false) {
|
|
83
|
+
return $err({
|
|
84
|
+
message: "Invalid encrypted data format",
|
|
85
|
+
description: 'Encrypted data must be in the format "iv.encrypted.tag."'
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const [iv, encryptedData, tag] = encrypted.split(".", 4);
|
|
89
|
+
if (!$isStr(iv, 1) || !$isStr(encryptedData, 1) || !$isStr(tag, 1)) {
|
|
90
|
+
return $err({
|
|
91
|
+
message: "Invalid parameters for decryption",
|
|
92
|
+
description: "IV, encrypted data, and tag must be non-empty strings"
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (!$isNodeKey(secretKey)) {
|
|
96
|
+
return $err({ message: "Invalid decryption key", description: "Expected a crypto.KeyObject" });
|
|
97
|
+
}
|
|
98
|
+
const { bytes: ivBytes, error: ivError } = encode(iv, "base64url");
|
|
99
|
+
const { bytes: encryptedBytes, error: encryptedError } = encode(encryptedData, "base64url");
|
|
100
|
+
const { bytes: tagBytes, error: tagError } = encode(tag, "base64url");
|
|
101
|
+
if (ivError || encryptedError || tagError) {
|
|
102
|
+
return $err({ message: "Failed to encode IV or encrypted data", description: "Encoding error" });
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const decipher = nodeCrypto2.createDecipheriv(NODE_ALGORITHM, secretKey, ivBytes);
|
|
106
|
+
decipher.setAuthTag(tagBytes);
|
|
107
|
+
const decrypted = Buffer.concat([decipher.update(encryptedBytes), decipher.final()]);
|
|
108
|
+
return decode(decrypted, "utf8");
|
|
109
|
+
} catch (error) {
|
|
110
|
+
return $err({ message: "Failed to decrypt data with Crypto NodeJS", description: $stringifyError(error) });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { ENCRYPTED_NODE_REGEX, NODE_ALGORITHM, decode, decrypt, encode, encrypt, hash, newSecretKey, newUuid };
|
|
115
|
+
//# sourceMappingURL=chunk-P6FZJODK.js.map
|
|
116
|
+
//# sourceMappingURL=chunk-P6FZJODK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/node/encode.ts","../src/node/utils.ts","../src/node/encrypt.ts"],"names":["nodeCrypto","Buffer"],"mappings":"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","file":"chunk-P6FZJODK.js","sourcesContent":["import { Buffer } from 'node:buffer';\r\nimport { $err, $ok, $stringifyError, type Result } from '~/error';\r\nimport type { EncodingFormat } from '~/types';\r\n\r\nexport function encode(data: string, format: EncodingFormat = 'utf8'): Result<{ bytes: Buffer }> {\r\n try {\r\n return $ok({ bytes: Buffer.from(data, format) });\r\n } catch (error) {\r\n return $err({ message: 'Failed to encode data', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport function decode(data: Buffer, format: EncodingFormat = 'utf8'): Result<string> {\r\n try {\r\n return $ok(Buffer.from(data).toString(format));\r\n } catch (error) {\r\n return $err({ message: 'Failed to decode data', description: $stringifyError(error) });\r\n }\r\n}\r\n","import nodeCrypto from 'node:crypto';\r\nimport { $err, $ok, $stringifyError, type Result } from '~/error';\r\n\r\nexport const ENCRYPTED_NODE_REGEX = /^([A-Za-z0-9_-]+)\\.([A-Za-z0-9_-]+)\\.([A-Za-z0-9_-]+)\\.$/;\r\n\r\nexport function newUuid(): Result<string> {\r\n try {\r\n return $ok(nodeCrypto.randomUUID());\r\n } catch (error) {\r\n return $err({ message: 'Failed to generate UUID with Crypto NodeJS', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport function $isNodeKey(key: unknown): key is nodeCrypto.KeyObject {\r\n return key instanceof nodeCrypto.KeyObject;\r\n}\r\n","import { Buffer } from 'node:buffer';\r\nimport nodeCrypto from 'node:crypto';\r\nimport { $err, $ok, $stringifyError, type Result } from '~/error';\r\nimport type { NodeKey } from '~/types';\r\nimport { $isStr } from '~/utils';\r\nimport { decode, encode } from './encode';\r\nimport { $isNodeKey, ENCRYPTED_NODE_REGEX } from './utils';\r\n\r\nexport const NODE_ALGORITHM = 'aes-256-gcm';\r\n\r\nexport function hash(data: string): Result<string> {\r\n if (!$isStr(data)) {\r\n return $err({ message: 'Empty data for hashing', description: 'Data must be a non-empty string' });\r\n }\r\n\r\n try {\r\n const hashed = nodeCrypto.createHash('sha256').update(data).digest();\r\n return decode(hashed, 'base64url');\r\n } catch (error) {\r\n return $err({ message: 'Failed to hash data with Crypto NodeJS', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport function newSecretKey(key: string | NodeKey): Result<{ secretKey: NodeKey }> {\r\n if (typeof key === 'string') {\r\n if (!$isStr(key, 1)) return $err({ message: 'Empty key for Crypto NodeJS', description: 'Invalid secret key' });\r\n\r\n try {\r\n const hashedKey = nodeCrypto.createHash('sha256').update(key).digest();\r\n const secretKey = nodeCrypto.createSecretKey(hashedKey);\r\n return $ok({ secretKey });\r\n } catch (error) {\r\n return $err({ message: 'Failed to create secret key with Crypto NodeJS', description: $stringifyError(error) });\r\n }\r\n }\r\n\r\n if (!$isNodeKey(key)) return $err({ message: 'Invalid secret key', description: 'Expected a crypto.KeyObject' });\r\n return $ok({ secretKey: key });\r\n}\r\n\r\nexport function encrypt(data: string, secretKey: NodeKey): Result<string> {\r\n if (!$isStr(data)) {\r\n return $err({ message: 'Empty data for encryption', description: 'Data must be a non-empty string' });\r\n }\r\n\r\n if (!$isNodeKey(secretKey)) {\r\n return $err({ message: 'Invalid encryption key', description: 'Expected a crypto.KeyObject' });\r\n }\r\n\r\n try {\r\n const iv = nodeCrypto.randomBytes(12);\r\n const cipher = nodeCrypto.createCipheriv(NODE_ALGORITHM, secretKey, iv);\r\n const encrypted = Buffer.concat([cipher.update(data, 'utf8'), cipher.final()]);\r\n const tag = cipher.getAuthTag();\r\n\r\n const { result: decodedIv, error: ivError } = decode(iv, 'base64url');\r\n const { result: decodedEncrypted, error: encryptedError } = decode(encrypted, 'base64url');\r\n const { result: decodedTag, error: tagError } = decode(tag, 'base64url');\r\n if (ivError || encryptedError || tagError) {\r\n return $err({ message: 'Failed to encode encrypted data', description: 'Encoding error' });\r\n }\r\n\r\n return $ok(`${decodedIv}.${decodedEncrypted}.${decodedTag}.`);\r\n } catch (error) {\r\n return $err({ message: 'Failed to encrypt data with Crypto NodeJS', description: $stringifyError(error) });\r\n }\r\n}\r\n\r\nexport function decrypt(encrypted: string, secretKey: NodeKey): Result<string> {\r\n if (ENCRYPTED_NODE_REGEX.test(encrypted) === false) {\r\n return $err({\r\n message: 'Invalid encrypted data format',\r\n description: 'Encrypted data must be in the format \"iv.encrypted.tag.\"',\r\n });\r\n }\r\n\r\n const [iv, encryptedData, tag] = encrypted.split('.', 4);\r\n if (!$isStr(iv, 1) || !$isStr(encryptedData, 1) || !$isStr(tag, 1)) {\r\n return $err({\r\n message: 'Invalid parameters for decryption',\r\n description: 'IV, encrypted data, and tag must be non-empty strings',\r\n });\r\n }\r\n\r\n if (!$isNodeKey(secretKey)) {\r\n return $err({ message: 'Invalid decryption key', description: 'Expected a crypto.KeyObject' });\r\n }\r\n\r\n const { bytes: ivBytes, error: ivError } = encode(iv, 'base64url');\r\n const { bytes: encryptedBytes, error: encryptedError } = encode(encryptedData, 'base64url');\r\n const { bytes: tagBytes, error: tagError } = encode(tag, 'base64url');\r\n if (ivError || encryptedError || tagError) {\r\n return $err({ message: 'Failed to encode IV or encrypted data', description: 'Encoding error' });\r\n }\r\n\r\n try {\r\n const decipher = nodeCrypto.createDecipheriv(NODE_ALGORITHM, secretKey, ivBytes);\r\n decipher.setAuthTag(tagBytes);\r\n\r\n const decrypted = Buffer.concat([decipher.update(encryptedBytes), decipher.final()]);\r\n return decode(decrypted, 'utf8');\r\n } catch (error) {\r\n return $err({ message: 'Failed to decrypt data with Crypto NodeJS', description: $stringifyError(error) });\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkGYHEGPUY_cjs = require('./chunk-GYHEGPUY.cjs');
|
|
4
|
+
var buffer = require('buffer');
|
|
5
|
+
var nodeCrypto2 = require('crypto');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var nodeCrypto2__default = /*#__PURE__*/_interopDefault(nodeCrypto2);
|
|
10
|
+
|
|
11
|
+
function encode(data, format = "utf8") {
|
|
12
|
+
try {
|
|
13
|
+
return chunkGYHEGPUY_cjs.$ok({ bytes: buffer.Buffer.from(data, format) });
|
|
14
|
+
} catch (error) {
|
|
15
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to encode data", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function decode(data, format = "utf8") {
|
|
19
|
+
try {
|
|
20
|
+
return chunkGYHEGPUY_cjs.$ok(buffer.Buffer.from(data).toString(format));
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to decode data", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
var ENCRYPTED_NODE_REGEX = /^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.$/;
|
|
26
|
+
function newUuid() {
|
|
27
|
+
try {
|
|
28
|
+
return chunkGYHEGPUY_cjs.$ok(nodeCrypto2__default.default.randomUUID());
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to generate UUID with Crypto NodeJS", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function $isNodeKey(key) {
|
|
34
|
+
return key instanceof nodeCrypto2__default.default.KeyObject;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/node/encrypt.ts
|
|
38
|
+
var NODE_ALGORITHM = "aes-256-gcm";
|
|
39
|
+
function hash(data) {
|
|
40
|
+
if (!chunkGYHEGPUY_cjs.$isStr(data)) {
|
|
41
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Empty data for hashing", description: "Data must be a non-empty string" });
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const hashed = nodeCrypto2__default.default.createHash("sha256").update(data).digest();
|
|
45
|
+
return decode(hashed, "base64url");
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to hash data with Crypto NodeJS", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function newSecretKey(key) {
|
|
51
|
+
if (typeof key === "string") {
|
|
52
|
+
if (!chunkGYHEGPUY_cjs.$isStr(key, 1)) return chunkGYHEGPUY_cjs.$err({ message: "Empty key for Crypto NodeJS", description: "Invalid secret key" });
|
|
53
|
+
try {
|
|
54
|
+
const hashedKey = nodeCrypto2__default.default.createHash("sha256").update(key).digest();
|
|
55
|
+
const secretKey = nodeCrypto2__default.default.createSecretKey(hashedKey);
|
|
56
|
+
return chunkGYHEGPUY_cjs.$ok({ secretKey });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to create secret key with Crypto NodeJS", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!$isNodeKey(key)) return chunkGYHEGPUY_cjs.$err({ message: "Invalid secret key", description: "Expected a crypto.KeyObject" });
|
|
62
|
+
return chunkGYHEGPUY_cjs.$ok({ secretKey: key });
|
|
63
|
+
}
|
|
64
|
+
function encrypt(data, secretKey) {
|
|
65
|
+
if (!chunkGYHEGPUY_cjs.$isStr(data)) {
|
|
66
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Empty data for encryption", description: "Data must be a non-empty string" });
|
|
67
|
+
}
|
|
68
|
+
if (!$isNodeKey(secretKey)) {
|
|
69
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Invalid encryption key", description: "Expected a crypto.KeyObject" });
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const iv = nodeCrypto2__default.default.randomBytes(12);
|
|
73
|
+
const cipher = nodeCrypto2__default.default.createCipheriv(NODE_ALGORITHM, secretKey, iv);
|
|
74
|
+
const encrypted = buffer.Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
75
|
+
const tag = cipher.getAuthTag();
|
|
76
|
+
const { result: decodedIv, error: ivError } = decode(iv, "base64url");
|
|
77
|
+
const { result: decodedEncrypted, error: encryptedError } = decode(encrypted, "base64url");
|
|
78
|
+
const { result: decodedTag, error: tagError } = decode(tag, "base64url");
|
|
79
|
+
if (ivError || encryptedError || tagError) {
|
|
80
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to encode encrypted data", description: "Encoding error" });
|
|
81
|
+
}
|
|
82
|
+
return chunkGYHEGPUY_cjs.$ok(`${decodedIv}.${decodedEncrypted}.${decodedTag}.`);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to encrypt data with Crypto NodeJS", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function decrypt(encrypted, secretKey) {
|
|
88
|
+
if (ENCRYPTED_NODE_REGEX.test(encrypted) === false) {
|
|
89
|
+
return chunkGYHEGPUY_cjs.$err({
|
|
90
|
+
message: "Invalid encrypted data format",
|
|
91
|
+
description: 'Encrypted data must be in the format "iv.encrypted.tag."'
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const [iv, encryptedData, tag] = encrypted.split(".", 4);
|
|
95
|
+
if (!chunkGYHEGPUY_cjs.$isStr(iv, 1) || !chunkGYHEGPUY_cjs.$isStr(encryptedData, 1) || !chunkGYHEGPUY_cjs.$isStr(tag, 1)) {
|
|
96
|
+
return chunkGYHEGPUY_cjs.$err({
|
|
97
|
+
message: "Invalid parameters for decryption",
|
|
98
|
+
description: "IV, encrypted data, and tag must be non-empty strings"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (!$isNodeKey(secretKey)) {
|
|
102
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Invalid decryption key", description: "Expected a crypto.KeyObject" });
|
|
103
|
+
}
|
|
104
|
+
const { bytes: ivBytes, error: ivError } = encode(iv, "base64url");
|
|
105
|
+
const { bytes: encryptedBytes, error: encryptedError } = encode(encryptedData, "base64url");
|
|
106
|
+
const { bytes: tagBytes, error: tagError } = encode(tag, "base64url");
|
|
107
|
+
if (ivError || encryptedError || tagError) {
|
|
108
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to encode IV or encrypted data", description: "Encoding error" });
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const decipher = nodeCrypto2__default.default.createDecipheriv(NODE_ALGORITHM, secretKey, ivBytes);
|
|
112
|
+
decipher.setAuthTag(tagBytes);
|
|
113
|
+
const decrypted = buffer.Buffer.concat([decipher.update(encryptedBytes), decipher.final()]);
|
|
114
|
+
return decode(decrypted, "utf8");
|
|
115
|
+
} catch (error) {
|
|
116
|
+
return chunkGYHEGPUY_cjs.$err({ message: "Failed to decrypt data with Crypto NodeJS", description: chunkGYHEGPUY_cjs.$stringifyError(error) });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
exports.ENCRYPTED_NODE_REGEX = ENCRYPTED_NODE_REGEX;
|
|
121
|
+
exports.NODE_ALGORITHM = NODE_ALGORITHM;
|
|
122
|
+
exports.decode = decode;
|
|
123
|
+
exports.decrypt = decrypt;
|
|
124
|
+
exports.encode = encode;
|
|
125
|
+
exports.encrypt = encrypt;
|
|
126
|
+
exports.hash = hash;
|
|
127
|
+
exports.newSecretKey = newSecretKey;
|
|
128
|
+
exports.newUuid = newUuid;
|
|
129
|
+
//# sourceMappingURL=chunk-RKUUM2D6.cjs.map
|
|
130
|
+
//# sourceMappingURL=chunk-RKUUM2D6.cjs.map
|