wilcocrypt 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,22 +1,23 @@
1
1
  # WilcoCrypt
2
2
 
3
- **WilcoCrypt** is a simple and secure file encryption tool for Node.js.
4
- It offers both a clean programmatic API and a practical command-line interface (CLI) for everyday use.
3
+ [![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg)](https://github.com/standard/semistandard)
5
4
 
6
- The library focuses on strong defaults, portability, and predictable behavior across environments
7
- (including low-end devices such as Raspberry Pi and Android/Termux).
5
+ > **The `master` branch may be unstable during active development.**
6
+ > For production use, always install from [npm](https://www.npmjs.com/package/wilcocrypt) or use a tagged [GitHub Release](https://github.com/computer-wilco/wilcocrypt/releases).
7
+
8
+ A simple, modern Node.js encryption library and CLI tool. AES-256-GCM, password-based key derivation via scrypt, optional gzip compression, and a streaming API for large files.
8
9
 
9
10
  ---
10
11
 
11
12
  ## Features
12
13
 
13
14
  - AES-256-GCM authenticated encryption
14
- - Password-based key derivation using scrypt
15
- - MessagePack + gzip for compact encrypted files
16
- - Built-in versioning and compatibility checks
17
- - Clear and consistent error handling
18
- - Clean separation between public API and internal helpers
19
- - Command-line interface (CLI) for quick file encryption and decryption
15
+ - scrypt key derivation with a random salt per encryption
16
+ - Optional gzip compression before encryption
17
+ - Streaming API for large files (`encryptFileStream` / `decryptFileStream`)
18
+ - CLI with interactive password prompt
19
+ - TypeScript types included
20
+ - semistandard code style
20
21
 
21
22
  ---
22
23
 
@@ -26,86 +27,95 @@ The library focuses on strong defaults, portability, and predictable behavior ac
26
27
  npm install wilcocrypt
27
28
  ```
28
29
 
29
- ### CLI Installation
30
-
31
- ```bash
32
- npm install -g wilcocrypt
33
- ```
30
+ Requires Node.js 18 or later.
34
31
 
35
32
  ---
36
33
 
37
- ## Usage (Node.js)
34
+ ## Quick Start
38
35
 
39
36
  ```js
40
37
  import wilcocrypt from 'wilcocrypt';
41
38
 
42
- // Encrypt a file
43
- wilcocrypt.encryptFile('document.txt', 'myStrongPassword');
39
+ // Encrypt / decrypt a Buffer
40
+ const encrypted = wilcocrypt.encryptData(Buffer.from('Hello!'), 'my-password');
41
+ const decrypted = wilcocrypt.decryptData(encrypted, 'my-password');
42
+
43
+ // Encrypt a file → writes file.txt.enc
44
+ wilcocrypt.encryptFile('file.txt', 'my-password');
45
+
46
+ // Decrypt to Buffer
47
+ const buf = wilcocrypt.decryptFile('file.txt.enc', 'my-password');
44
48
 
45
- // Decrypt a file
46
- const content = wilcocrypt.decryptFile('document.txt.enc', 'myStrongPassword');
47
- console.log(content);
49
+ // Decrypt directly to disk
50
+ wilcocrypt.decryptFile('file.txt.enc', 'my-password', 'output.txt');
51
+
52
+ // Stream API (memory-efficient for large files)
53
+ await wilcocrypt.encryptFileStream('big.zip', 'big.zip.enc', 'my-password');
54
+ await wilcocrypt.decryptFileStream('big.zip.enc', 'big.zip', 'my-password');
48
55
  ```
49
56
 
50
57
  ---
51
58
 
52
- ## Internal helpers (optional)
59
+ ## CLI
53
60
 
54
- Advanced users can access internal helpers via `wilcocrypt._`.
55
- These APIs are considered internal and may change between versions.
61
+ ```bash
62
+ # Encrypt
63
+ wilcocrypt -e secret.txt
64
+ # → prompts for password, writes secret.txt.enc
56
65
 
57
- ```js
58
- const iv = Buffer.from('...');
59
- const key = Buffer.from('...');
60
- const encrypted = wilcocrypt._.encryptData(Buffer.from('Hello'), key, iv);
66
+ # Decrypt to stdout
67
+ wilcocrypt -d secret.txt.enc
68
+
69
+ # Decrypt to a file
70
+ wilcocrypt -d secret.txt.enc -o secret.txt
61
71
  ```
62
72
 
73
+ See `wilcocrypt --help` for all options.
74
+
63
75
  ---
64
76
 
65
- ## CLI Usage
77
+ ## Binary Payload Format
66
78
 
67
- Once installed globally:
79
+ ```
80
+ [ HEADER (10) ] [ VERSION (dynamic) ] [ salt (16) ] [ iv (12) ] [ ciphertext ] [ authTag (16) ]
81
+ ```
68
82
 
69
- ```bash
70
- # Encrypt a file
71
- wilcocrypt -e document.txt
72
- wilcocrypt --encrypt document.txt
83
+ The auth tag is appended at the end for streaming compatibility. See [DOCS.md](./DOCS.md#binary-payload-format) for the full layout.
73
84
 
74
- # Decrypt a file
75
- wilcocrypt -d document.txt.enc
76
- wilcocrypt --decrypt document.txt.enc
85
+ > **Note:** The format changed in v2.2.0. Payloads from v2.1.x are not compatible.
77
86
 
78
- # Internal: unpack raw encrypted envelope
79
- wilcocrypt --unpack document.txt.enc
80
- ```
87
+ ---
81
88
 
82
- The CLI will securely prompt for a password (input is masked).
89
+ ## Error Handling
83
90
 
84
- ---
91
+ All errors are instances of `WilcoCryptError` with a machine-readable `code` property.
85
92
 
86
- ## Version
93
+ ```js
94
+ import wilcocrypt from 'wilcocrypt';
95
+ const { WilcoCryptError } = wilcocrypt._;
96
+
97
+ try {
98
+ wilcocrypt.decryptData(payload, 'wrong');
99
+ } catch (err) {
100
+ if (err instanceof WilcoCryptError) {
101
+ console.error(err.code); // e.g. DECRYPTION_FAILED
102
+ console.error(err.message);
103
+ }
104
+ }
105
+ ```
87
106
 
88
- - Current version: **2.0.0**
89
- - Version 1.x is deprecated and should not be used
107
+ Common codes: `WEAK_PASSWORD`, `INVALID_HEADER`, `VERSION_MISMATCH`, `DECRYPTION_FAILED`, `INVALID_FILE_EXTENSION`.
90
108
 
91
109
  ---
92
110
 
93
- ## License
111
+ ## Documentation
94
112
 
95
- WilcoCrypt is released under the **GPL-3.0-only** license.
113
+ Full API reference, CLI docs, payload format, TypeScript usage, and security notes: **[DOCS.md](./DOCS.md)**
96
114
 
97
- You are free to:
98
- - Use the software for any purpose
99
- - Study how it works and modify it
100
- - Redistribute the software
101
- - Distribute modified versions
115
+ Changelog: **[CHANGELOG.md](./CHANGELOG.md)**
102
116
 
103
- Under the condition that:
104
- - Any distributed derivative work is also licensed under GPL-3.0-only
105
- - The source code remains available to users
117
+ ---
106
118
 
107
- This software is provided **without any warranty**.
108
- Use it at your own risk.
119
+ ## License
109
120
 
110
- For full license text, see:
111
- https://www.gnu.org/licenses/gpl-3.0.html
121
+ Licensed under **GPL-3.0-only**.
package/SECURITY.md ADDED
@@ -0,0 +1,48 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ The following versions of WilcoCrypt are currently supported with security updates:
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 2.1.x | :white_check_mark: |
10
+ | 2.0.x | :x: |
11
+ | 1.x | :x: |
12
+
13
+ Only the latest minor version in the 2.x range receives security updates. All the versions below that are not supported.
14
+
15
+ ---
16
+
17
+ ## Reporting a Vulnerability
18
+
19
+ If you discover a security vulnerability in WilcoCrypt, please report it responsibly.
20
+
21
+ ### How to report
22
+
23
+ - Open a **private security advisory** via the GitHub repository
24
+
25
+ Please include:
26
+
27
+ * A clear description of the issue
28
+ * Steps to reproduce (if possible)
29
+ * Impact assessment (what can go wrong)
30
+
31
+ ### What to expect
32
+
33
+ * You will receive a response within **48 hours**
34
+ * I will investigate and confirm the issue
35
+ * If accepted, a fix will be developed as soon as possible
36
+ * A patched version will be released and documented
37
+
38
+ ### Responsible disclosure
39
+
40
+ Please do **not** publicly disclose the vulnerability until a fix has been released.
41
+
42
+ ---
43
+
44
+ ## Notes
45
+
46
+ * WilcoCrypt is designed with strong cryptographic defaults, but misuse (e.g. weak passwords) can still lead to insecure outcomes
47
+ * Always use strong, unique passwords
48
+ * Security is a shared responsibility between the library and its users
package/package.json CHANGED
@@ -1,19 +1,23 @@
1
1
  {
2
2
  "name": "wilcocrypt",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "A encrypting tool",
5
5
  "keywords": [
6
- "encrypting"
6
+ "encrypting",
7
+ "crypto"
7
8
  ],
8
9
  "license": "GPL-3.0-only",
9
- "author": "Wilco Joosen",
10
+ "author": "computerwilco",
10
11
  "type": "module",
11
- "main": "dist/wilcocrypt.min.js",
12
- "bin": "dist/cli.min.js",
12
+ "main": "src/wilcocrypt.js",
13
+ "bin": "src/cli.js",
14
+ "types": "types/wilcocrypt.d.ts",
13
15
  "scripts": {
14
- "test": "echo \"Error: no test specified\" && exit 1",
16
+ "test": "node src/cli.js",
17
+ "lint": "npx semistandard",
18
+ "lint:fix": "npx semistandard --fix",
15
19
  "update": "npx -y Jelmerro/nus",
16
- "rollup": "rollup -c && node src/scripts/fix-cli-min-import.js && node src/scripts/chmod.js",
20
+ "rollup": "node src/scripts/shebang-fix.js pre && rollup -c && node src/scripts/shebang-fix.js post && node src/scripts/fix-cli-min-import.js && node src/scripts/chmod.js",
17
21
  "sea:blob": "node src/scripts/sea-blob.js",
18
22
  "sea:linux-x64": "cp node-binaries/linux-x64/node release/wilcocrypt-linux-x64 && npx postject release/wilcocrypt-linux-x64 NODE_SEA_BLOB sea/wilcocrypt.sea --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 && chmod +x release/wilcocrypt-linux-x64",
19
23
  "sea:linux-arm64": "cp node-binaries/linux-arm64/node release/wilcocrypt-linux-arm64 && npx postject release/wilcocrypt-linux-arm64 NODE_SEA_BLOB sea/wilcocrypt.sea --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 && chmod +x release/wilcocrypt-linux-arm64",
@@ -23,13 +27,16 @@
23
27
  "build": "npm run rollup && npm run sea:blob && npm run sea:linux-x64 && npm run sea:linux-arm64 && npm run sea:windows-x64 && npm run sea:macos-x64 && npm run sea:macos-arm64",
24
28
  "clean": "rm -rf dist && rm -rf sea/*.sea && rm -rf release/*"
25
29
  },
30
+ "dependencies": {
31
+ "commander": "14.0.3"
32
+ },
26
33
  "devDependencies": {
27
34
  "@rollup/plugin-commonjs": "29.0.2",
28
35
  "@rollup/plugin-node-resolve": "16.0.3",
29
36
  "@rollup/plugin-replace": "6.0.3",
30
37
  "@rollup/plugin-terser": "1.0.0",
31
- "commander": "14.0.3",
32
- "notepack.io": "3.0.1",
33
- "rollup": "4.60.2"
38
+ "@types/node": "25.6.0",
39
+ "rollup": "4.60.2",
40
+ "semistandard": "17.0.0"
34
41
  }
35
42
  }
package/src/cli.js ADDED
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import wilcocrypt from './wilcocrypt.js';
4
+
5
+ /* =========================
6
+ Helpers
7
+ ========================= */
8
+
9
+ function promptPassword (promptText = 'Password: ') {
10
+ return new Promise((resolve) => {
11
+ const stdin = process.stdin;
12
+ const stdout = process.stdout;
13
+
14
+ if (!stdin.isTTY) {
15
+ throw new wilcocrypt._.WilcoCryptError(
16
+ 'Password prompt requires a TTY',
17
+ 'NO_TTY'
18
+ );
19
+ }
20
+
21
+ stdout.write(promptText);
22
+
23
+ let password = '';
24
+
25
+ stdin.setRawMode(true);
26
+ stdin.resume();
27
+ stdin.setEncoding('utf8');
28
+
29
+ function onData (char) {
30
+ if (char === '\r' || char === '\n') {
31
+ stdout.write('\n');
32
+ stdin.setRawMode(false);
33
+ stdin.pause();
34
+ stdin.removeListener('data', onData);
35
+ resolve(password);
36
+ return;
37
+ }
38
+
39
+ if (char === '\u0003') {
40
+ stdout.write('\n');
41
+ stdin.setRawMode(false);
42
+ stdin.pause();
43
+ stdin.removeListener('data', onData);
44
+ process.exit(1);
45
+ }
46
+
47
+ if (char === '\u007f' || char === '\b') {
48
+ if (password.length > 0) {
49
+ password = password.slice(0, -1);
50
+ stdout.write('\b \b');
51
+ }
52
+ return;
53
+ }
54
+
55
+ password += char;
56
+ stdout.write('*');
57
+ }
58
+
59
+ stdin.on('data', onData);
60
+ });
61
+ }
62
+
63
+ /* =========================
64
+ CLI setup
65
+ ========================= */
66
+
67
+ const program = new Command();
68
+
69
+ program
70
+ .name('wilcocrypt')
71
+ .description('File encryption tool')
72
+ .version(wilcocrypt._.VERSION, '--version', 'Show version')
73
+
74
+ .option('-e, --encrypt <file>', 'Encrypt file')
75
+ .option('-d, --decrypt <file>', 'Decrypt file')
76
+ .option('-o, --output <file>', 'Write output to file instead of stdout (decrypt only)')
77
+ .option('--stdout', 'Write decrypted output to stdout (default behavior, explicit flag)')
78
+
79
+ .helpOption('-h, --help', 'Display help');
80
+
81
+ program.parse(process.argv);
82
+
83
+ const options = program.opts();
84
+
85
+ /* =========================
86
+ Validation
87
+ ========================= */
88
+
89
+ const actions = [
90
+ options.encrypt,
91
+ options.decrypt
92
+ ].filter(Boolean);
93
+
94
+ if (actions.length === 0) {
95
+ program.help();
96
+ }
97
+
98
+ if (actions.length > 1) {
99
+ console.error('error: please specify only one action (-e or -d)');
100
+ process.exit(1);
101
+ }
102
+
103
+ if (options.output && options.stdout) {
104
+ console.error('error: --output and --stdout are mutually exclusive');
105
+ process.exit(1);
106
+ }
107
+
108
+ if (options.output && options.encrypt) {
109
+ console.error('error: --output is only supported for decryption');
110
+ process.exit(1);
111
+ }
112
+
113
+ /* =========================
114
+ Actions
115
+ ========================= */
116
+
117
+ (async () => {
118
+ try {
119
+ if (options.encrypt) {
120
+ const password = await promptPassword('Encryption password: ');
121
+ wilcocrypt.encryptFile(options.encrypt, password);
122
+ console.log(`Encrypted: ${options.encrypt}.enc`);
123
+ return;
124
+ }
125
+
126
+ if (options.decrypt) {
127
+ const password = await promptPassword('Decryption password: ');
128
+
129
+ if (options.output) {
130
+ wilcocrypt.decryptFile(options.decrypt, password, options.output);
131
+ console.log(`Decrypted: ${options.output}`);
132
+ } else {
133
+ const result = wilcocrypt.decryptFile(options.decrypt, password);
134
+ process.stdout.write(result);
135
+ }
136
+ }
137
+ } catch (err) {
138
+ console.error(`error: ${err.message}`);
139
+ process.exit(1);
140
+ }
141
+ })();