yamlock 0.2.3 → 0.2.5
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 +6 -1
- package/dist/cli/cli.js +76 -10
- package/dist/crypto/utils.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,9 @@ yamlock encrypt config.json --key "$YAMLOCK_KEY" --paths "db.password,api.token"
|
|
|
54
54
|
# Inspect CLI metadata
|
|
55
55
|
yamlock version
|
|
56
56
|
yamlock algorithms
|
|
57
|
+
|
|
58
|
+
# Generate a random key for YAMLOCK_KEY
|
|
59
|
+
yamlock keygen --length 64 --format base64
|
|
57
60
|
```
|
|
58
61
|
|
|
59
62
|
The CLI detects YAML (`.yaml`/`.yml`) and JSON extensions automatically and writes the file back in the same format.
|
|
@@ -61,7 +64,9 @@ The CLI detects YAML (`.yaml`/`.yml`) and JSON extensions automatically and writ
|
|
|
61
64
|
Options of note:
|
|
62
65
|
- `--output <file>` writes the result to a separate file instead of overwriting the input.
|
|
63
66
|
- `--paths <path1,path2>` targets only the specified fields (dot/bracket notation like `db.password` or `users[0].token`).
|
|
64
|
-
-
|
|
67
|
+
- Command `keygen` produces a random key and shows how to store it (shell export or `.env`).
|
|
68
|
+
- Command `algorithms` prints two lists: tested presets (covered by yamlock) and additional ciphers available from the runtime.
|
|
69
|
+
- Command `version` prints the installed CLI version.
|
|
65
70
|
|
|
66
71
|
### Node.js API
|
|
67
72
|
|
package/dist/cli/cli.js
CHANGED
|
@@ -3,19 +3,24 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
3
3
|
import { resolve, extname } from 'node:path';
|
|
4
4
|
import { exit } from 'node:process';
|
|
5
5
|
import { createRequire } from 'node:module';
|
|
6
|
+
import { randomBytes } from 'node:crypto';
|
|
6
7
|
|
|
7
8
|
import yaml from 'js-yaml';
|
|
8
9
|
|
|
9
10
|
import { processConfig } from '../utils/config.js';
|
|
10
|
-
import { listSupportedAlgorithms } from '../crypto/utils.js';
|
|
11
|
+
import { listSupportedAlgorithms, TESTED_ALGORITHMS } from '../crypto/utils.js';
|
|
11
12
|
|
|
12
13
|
const require = createRequire(import.meta.url);
|
|
13
14
|
const packageJson = require('../../package.json');
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
+
const BANNER = `
|
|
16
17
|
░█░█░█▀█░█▄░▄█░█░░░█▀█░█▀▀░█░█░
|
|
17
18
|
░░█░░█▀█░█░▀░█░█░░░█░█░█░░░█▀▄░
|
|
18
|
-
|
|
19
|
+
░░▀░░▀░▀░▀░░░▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░`;
|
|
20
|
+
|
|
21
|
+
function getHelpText() {
|
|
22
|
+
return `${BANNER}
|
|
23
|
+
Version: ${packageJson.version}
|
|
19
24
|
|
|
20
25
|
Usage:
|
|
21
26
|
yamlock <command> [options]
|
|
@@ -25,13 +30,17 @@ Commands:
|
|
|
25
30
|
decrypt <file> Decrypt string values in the given YAML/JSON file.
|
|
26
31
|
version Print the yamlock CLI version.
|
|
27
32
|
algorithms Print the list of supported cipher algorithms.
|
|
33
|
+
keygen Generate a random YAMLOCK_KEY.
|
|
28
34
|
|
|
29
35
|
Options:
|
|
30
36
|
-k, --key <value> Encryption key (or use YAMLOCK_KEY env).
|
|
31
37
|
-a, --algorithm <value> Cipher algorithm (default: aes-256-cbc).
|
|
32
38
|
-o, --output <file> Write the result to a different file (otherwise overwrites the input file).
|
|
33
39
|
-p, --paths <p1,p2> Comma-separated list of field paths to process (dot/bracket notation).
|
|
40
|
+
--length <bytes> (keygen) Number of random bytes to generate (default: 32).
|
|
41
|
+
--format <hex|base64> (keygen) Output format (default: base64).
|
|
34
42
|
`;
|
|
43
|
+
}
|
|
35
44
|
|
|
36
45
|
function print(message) {
|
|
37
46
|
console.log(message);
|
|
@@ -87,11 +96,20 @@ function parseArgs(argv) {
|
|
|
87
96
|
const args = argv.slice(2);
|
|
88
97
|
const result = {
|
|
89
98
|
command: args[0],
|
|
90
|
-
file:
|
|
99
|
+
file: undefined,
|
|
91
100
|
options: {}
|
|
92
101
|
};
|
|
93
102
|
|
|
94
|
-
|
|
103
|
+
let index = 1;
|
|
104
|
+
const potentialFile = args[1];
|
|
105
|
+
if (potentialFile && !potentialFile.startsWith('-')) {
|
|
106
|
+
result.file = potentialFile;
|
|
107
|
+
index = 2;
|
|
108
|
+
} else {
|
|
109
|
+
index = 1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (let i = index; i < args.length; i += 1) {
|
|
95
113
|
const arg = args[i];
|
|
96
114
|
const next = args[i + 1];
|
|
97
115
|
|
|
@@ -107,17 +125,32 @@ function parseArgs(argv) {
|
|
|
107
125
|
} else if (arg === '-p' || arg === '--paths') {
|
|
108
126
|
result.options.paths = parsePaths(next);
|
|
109
127
|
i += 1;
|
|
128
|
+
} else if (arg === '--length') {
|
|
129
|
+
result.options.length = next;
|
|
130
|
+
i += 1;
|
|
131
|
+
} else if (arg === '--format') {
|
|
132
|
+
result.options.format = next;
|
|
133
|
+
i += 1;
|
|
110
134
|
}
|
|
111
135
|
}
|
|
112
136
|
|
|
113
137
|
return result;
|
|
114
138
|
}
|
|
115
139
|
|
|
140
|
+
function generateRandomKey(length, format) {
|
|
141
|
+
const size = Number.isFinite(length) && length > 0 ? Math.floor(length) : 32;
|
|
142
|
+
const buffer = randomBytes(size);
|
|
143
|
+
if (format === 'hex') {
|
|
144
|
+
return buffer.toString('hex');
|
|
145
|
+
}
|
|
146
|
+
return buffer.toString('base64');
|
|
147
|
+
}
|
|
148
|
+
|
|
116
149
|
export async function runCli(argv = process.argv) {
|
|
117
150
|
const { command, file, options } = parseArgs(argv);
|
|
118
151
|
|
|
119
152
|
if (!command) {
|
|
120
|
-
print(
|
|
153
|
+
print(getHelpText().trim());
|
|
121
154
|
return exit(1);
|
|
122
155
|
}
|
|
123
156
|
|
|
@@ -128,14 +161,47 @@ export async function runCli(argv = process.argv) {
|
|
|
128
161
|
|
|
129
162
|
if (command === 'algorithms') {
|
|
130
163
|
const algorithms = listSupportedAlgorithms();
|
|
131
|
-
|
|
132
|
-
|
|
164
|
+
const tested = TESTED_ALGORITHMS.slice().sort();
|
|
165
|
+
const testedSet = new Set(tested);
|
|
166
|
+
const additional = algorithms.filter((name) => !testedSet.has(name));
|
|
167
|
+
|
|
168
|
+
print('Tested algorithms (covered by yamlock fixtures):');
|
|
169
|
+
tested.forEach((name) => print(`- ${name}`));
|
|
170
|
+
|
|
171
|
+
if (additional.length > 0) {
|
|
172
|
+
print('\nAdditional algorithms available in this runtime:');
|
|
173
|
+
additional.forEach((name) => print(`- ${name}`));
|
|
174
|
+
print('\nUse at your own risk; these ciphers are not part of the official test matrix yet.');
|
|
175
|
+
}
|
|
176
|
+
return exit(0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (command === 'keygen') {
|
|
180
|
+
const desiredLength = options.length ? Number(options.length) : 32;
|
|
181
|
+
const normalizedFormat = (options.format ?? 'base64').toLowerCase();
|
|
182
|
+
|
|
183
|
+
if (!Number.isFinite(desiredLength) || desiredLength <= 0) {
|
|
184
|
+
printError('Key length must be a positive number.');
|
|
185
|
+
return exit(1);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!['base64', 'hex'].includes(normalizedFormat)) {
|
|
189
|
+
printError('Key format must be either "base64" or "hex".');
|
|
190
|
+
return exit(1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const keyValue = generateRandomKey(desiredLength, normalizedFormat);
|
|
194
|
+
print(`Generated key (${normalizedFormat}, ${Math.floor(desiredLength)} bytes of entropy):`);
|
|
195
|
+
print(keyValue);
|
|
196
|
+
print('\nStore it securely, e.g.');
|
|
197
|
+
print(` export YAMLOCK_KEY="${keyValue}"`);
|
|
198
|
+
print(' # or place in an .env file as YAMLOCK_KEY=your-key');
|
|
133
199
|
return exit(0);
|
|
134
200
|
}
|
|
135
201
|
|
|
136
202
|
if (!file) {
|
|
137
203
|
printError('A file path is required for this command.');
|
|
138
|
-
print(
|
|
204
|
+
print(getHelpText().trim());
|
|
139
205
|
return exit(1);
|
|
140
206
|
}
|
|
141
207
|
|
|
@@ -184,7 +250,7 @@ export async function runCli(argv = process.argv) {
|
|
|
184
250
|
}
|
|
185
251
|
|
|
186
252
|
printError(`Unknown command: ${command}`);
|
|
187
|
-
print(
|
|
253
|
+
print(getHelpText().trim());
|
|
188
254
|
return exit(1);
|
|
189
255
|
} catch (error) {
|
|
190
256
|
printError(`Operation failed: ${error.message}`);
|
package/dist/crypto/utils.js
CHANGED
|
@@ -9,6 +9,7 @@ export const ALGORITHM_PRESETS = {
|
|
|
9
9
|
'aes-128-cbc': { keyLength: 16, ivLength: 16, authTagLength: 0 },
|
|
10
10
|
'chacha20-poly1305': { keyLength: 32, ivLength: 12, authTagLength: 16 }
|
|
11
11
|
};
|
|
12
|
+
export const TESTED_ALGORITHMS = Object.keys(ALGORITHM_PRESETS);
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Returns the sorted list of cipher algorithms supported by the current runtime.
|
package/package.json
CHANGED