@fylib/crypto 0.1.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.
@@ -0,0 +1,3 @@
1
+ import { CryptoConfig } from './types';
2
+ export declare function encrypt(text: string, cfg: CryptoConfig): Promise<string>;
3
+ export declare function decrypt(payload: string, cfg: CryptoConfig): Promise<string>;
package/dist/engine.js ADDED
@@ -0,0 +1,74 @@
1
+ import { logger } from '@fylib/logger';
2
+ function getSubtle() {
3
+ const g = globalThis;
4
+ if (g.crypto && g.crypto.subtle)
5
+ return g.crypto.subtle;
6
+ return null;
7
+ }
8
+ function concatBuffers(a, b) {
9
+ const out = new Uint8Array(a.byteLength + b.byteLength);
10
+ out.set(new Uint8Array(a), 0);
11
+ out.set(new Uint8Array(b), a.byteLength);
12
+ return out;
13
+ }
14
+ function toBase64(u8) {
15
+ let bin = '';
16
+ for (let i = 0; i < u8.byteLength; i++)
17
+ bin += String.fromCharCode(u8[i]);
18
+ return btoa(bin);
19
+ }
20
+ function fromBase64(s) {
21
+ const bin = atob(s);
22
+ const out = new Uint8Array(bin.length);
23
+ for (let i = 0; i < bin.length; i++)
24
+ out[i] = bin.charCodeAt(i);
25
+ return out;
26
+ }
27
+ async function importKey(secret) {
28
+ const subtle = getSubtle();
29
+ if (!subtle)
30
+ throw new Error('WebCrypto not available');
31
+ const enc = new TextEncoder();
32
+ const raw = enc.encode(secret);
33
+ return await subtle.importKey('raw', raw, { name: 'AES-GCM' }, false, ['encrypt', 'decrypt']);
34
+ }
35
+ export async function encrypt(text, cfg) {
36
+ if (!cfg.enabled)
37
+ return text;
38
+ logger.debug('Crypto', 'Encrypting data');
39
+ const subtle = getSubtle();
40
+ if (!subtle) {
41
+ logger.error('Crypto', 'WebCrypto not available');
42
+ throw new Error('WebCrypto not available');
43
+ }
44
+ const key = await importKey(cfg.secret);
45
+ const iv = crypto.getRandomValues(new Uint8Array(cfg.ivSize));
46
+ const enc = new TextEncoder();
47
+ const data = enc.encode(text);
48
+ const ct = await subtle.encrypt({ name: 'AES-GCM', iv, tagLength: cfg.tagSize }, key, data);
49
+ const payload = concatBuffers(iv.buffer, ct);
50
+ return toBase64(payload);
51
+ }
52
+ export async function decrypt(payload, cfg) {
53
+ if (!cfg.enabled)
54
+ return payload;
55
+ logger.debug('Crypto', 'Decrypting data');
56
+ const subtle = getSubtle();
57
+ if (!subtle) {
58
+ logger.error('Crypto', 'WebCrypto not available');
59
+ throw new Error('WebCrypto not available');
60
+ }
61
+ try {
62
+ const key = await importKey(cfg.secret);
63
+ const buf = fromBase64(payload);
64
+ const iv = buf.slice(0, cfg.ivSize);
65
+ const ct = buf.slice(cfg.ivSize);
66
+ const pt = await subtle.decrypt({ name: 'AES-GCM', iv, tagLength: cfg.tagSize }, key, ct);
67
+ const dec = new TextDecoder();
68
+ return dec.decode(pt);
69
+ }
70
+ catch (e) {
71
+ logger.error('Crypto', 'Decryption failed', e);
72
+ throw e;
73
+ }
74
+ }
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * as cryptoEngine from './engine';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * as cryptoEngine from './engine';
@@ -0,0 +1,8 @@
1
+ export interface CryptoConfig {
2
+ enabled: boolean;
3
+ secret: string;
4
+ algorithm: string;
5
+ transformation: string;
6
+ ivSize: number;
7
+ tagSize: number;
8
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@fylib/crypto",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "files": ["dist"],
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc -p tsconfig.json"
12
+ },
13
+ "dependencies": {
14
+ "@fylib/core": "workspace:*",
15
+ "@fylib/logger": "workspace:*"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "catalog:",
19
+ "@types/node": "catalog:"
20
+ }
21
+ }