stegdoc 5.7.0 → 6.0.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 +231 -106
- package/package.json +25 -2
- package/src/commands/decode.js +97 -149
- package/src/commands/encode.js +150 -9
- package/src/commands/info.js +49 -0
- package/src/commands/verify.js +66 -0
- package/src/index.js +9 -5
- package/src/lib/bindings.js +99 -0
- package/src/lib/log-generator.js +5 -2
- package/src/lib/native.js +68 -0
- package/src/lib/streams.js +0 -107
- package/src/lib/utils.js +20 -0
- package/src/lib/xlsx-writer.js +10 -0
- package/src/lib/file-handler.js +0 -113
package/README.md
CHANGED
|
@@ -1,200 +1,325 @@
|
|
|
1
1
|
# stegdoc
|
|
2
2
|
|
|
3
|
-
> Hide
|
|
3
|
+
> Hide a file inside a legitimate-looking Office document
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/stegdoc)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
**stegdoc**
|
|
8
|
+
**stegdoc** encodes any file into an ordinary-looking Excel or Word document.
|
|
9
|
+
The payload is spread across realistic nginx access log entries or Hebrew
|
|
10
|
+
incident reports, so the cover survives casual inspection. Optionally protected
|
|
11
|
+
with AES-256-GCM.
|
|
12
|
+
|
|
13
|
+
The format engine is written in Rust. It ships as a prebuilt native addon for
|
|
14
|
+
the CLI, and as WebAssembly for the single-file browser tool.
|
|
9
15
|
|
|
10
16
|
## Features
|
|
11
17
|
|
|
12
|
-
- **Log-
|
|
13
|
-
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- **
|
|
20
|
-
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
- **Log-based steganography** — the data *is* the logs; there is no hidden
|
|
19
|
+
sheet and nothing extra to notice
|
|
20
|
+
- **AES-256-GCM** encryption, password-derived keys
|
|
21
|
+
- **v6 by default** — Argon2id key derivation and tamper-evident metadata, with
|
|
22
|
+
`--v5` for older decoders
|
|
23
|
+
- **Brotli** compression (quality 6), skipped for formats that are already
|
|
24
|
+
compressed
|
|
25
|
+
- **XLSX and DOCX** covers — an access-log spreadsheet or a Hebrew RTL
|
|
26
|
+
incident report
|
|
27
|
+
- **Multi-part splitting** for payloads larger than one document
|
|
28
|
+
- **Integrity checking** with SHA-256, verified on decode
|
|
29
|
+
- **ZIP, directory, or single-file input** on decode, discovered automatically
|
|
30
|
+
- **Backward compatible** — the decoder reads every earlier format version
|
|
31
|
+
|
|
32
|
+
## Install
|
|
26
33
|
|
|
27
34
|
```bash
|
|
28
35
|
npm install -g stegdoc
|
|
29
36
|
```
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
The install pulls a prebuilt engine for the host platform (`win32-x64`,
|
|
39
|
+
`linux-x64`, `linux-arm64`, `darwin-x64`, `darwin-arm64`). No compiler or Rust
|
|
40
|
+
toolchain is required. If a platform package is missing, log-embed files cannot
|
|
41
|
+
be decoded; the CLI says so instead of guessing.
|
|
42
|
+
|
|
43
|
+
Or run it without installing:
|
|
32
44
|
|
|
33
45
|
```bash
|
|
34
|
-
npx stegdoc encode myfile.pdf
|
|
46
|
+
npx stegdoc encode myfile.pdf -p mypassword
|
|
35
47
|
```
|
|
36
48
|
|
|
37
|
-
## Quick
|
|
49
|
+
## Quick start
|
|
38
50
|
|
|
39
51
|
```bash
|
|
40
|
-
#
|
|
52
|
+
# Hide a file, encrypted
|
|
41
53
|
stegdoc encode secret.pdf -p mypassword
|
|
42
54
|
|
|
43
|
-
#
|
|
55
|
+
# Get it back
|
|
44
56
|
stegdoc decode access_log_20260315_1200_A1B2_part1.xlsx -p mypassword
|
|
45
57
|
|
|
46
|
-
#
|
|
58
|
+
# Inspect without decoding
|
|
47
59
|
stegdoc info access_log_20260315_1200_A1B2_part1.xlsx
|
|
48
60
|
|
|
49
|
-
#
|
|
61
|
+
# Check that it will decode
|
|
50
62
|
stegdoc verify access_log_20260315_1200_A1B2_part1.xlsx -p mypassword
|
|
51
63
|
```
|
|
52
64
|
|
|
53
65
|
## Commands
|
|
54
66
|
|
|
55
|
-
### `encode
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
stegdoc encode <file> [options]
|
|
59
|
-
```
|
|
67
|
+
### `encode <inputs...>`
|
|
60
68
|
|
|
61
69
|
| Option | Description | Default |
|
|
62
70
|
|--------|-------------|---------|
|
|
63
71
|
| `-o, --output-dir <dir>` | Output directory | Current directory |
|
|
64
|
-
|
|
|
65
|
-
| `-
|
|
72
|
+
| `--bundle-name <name>` | Filename recorded when several inputs are bundled | `bundle.zip` |
|
|
73
|
+
| `-s, --chunk-size <size>` | Split size: `5MB`, `25MB`, `3 parts`, or `max` | `5MB` |
|
|
74
|
+
| `-f, --format <format>` | Cover format: `xlsx` or `docx` | `xlsx` |
|
|
66
75
|
| `-p, --password <pass>` | Encryption password | None (unencrypted) |
|
|
67
|
-
| `--
|
|
68
|
-
| `--
|
|
76
|
+
| `--v5` | Emit the v5 format (PBKDF2) | Off (v6) |
|
|
77
|
+
| `--v6` | Emit the v6 format (the default) | On |
|
|
78
|
+
| `--legacy` | Emit the legacy v4 DOCX format | Off |
|
|
79
|
+
| `--no-limit` | Bypass the DOCX 1 MB limit | Off |
|
|
69
80
|
| `--force` | Overwrite existing files | Prompt |
|
|
70
81
|
| `-q, --quiet` | Minimal output for scripting | Off |
|
|
71
82
|
| `-y, --yes` | Skip interactive prompts | Off |
|
|
72
83
|
|
|
73
|
-
|
|
84
|
+
A directory is zipped before encoding, and several inputs are bundled into one
|
|
85
|
+
zip first, so a decode hands that archive back. `-s max` produces a single part;
|
|
86
|
+
`-s "3 parts"` splits into roughly three.
|
|
74
87
|
|
|
75
88
|
```bash
|
|
76
|
-
|
|
77
|
-
stegdoc encode
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
stegdoc encode
|
|
81
|
-
|
|
82
|
-
# Split into 3 parts
|
|
83
|
-
stegdoc encode large-file.zip -p mysecret -s "3 parts"
|
|
84
|
-
|
|
85
|
-
# Legacy v4 format (for older environments)
|
|
86
|
-
stegdoc encode data.bin -p mysecret --legacy
|
|
87
|
-
|
|
88
|
-
# Encode a folder
|
|
89
|
-
stegdoc encode ./my-folder -p mysecret
|
|
89
|
+
stegdoc encode document.pdf -p mysecret # access log spreadsheet
|
|
90
|
+
stegdoc encode config.json -p mysecret -f docx # Hebrew incident report
|
|
91
|
+
stegdoc encode large-file.zip -p mysecret -s "3 parts" # three parts
|
|
92
|
+
stegdoc encode ./my-folder -p mysecret # zipped first
|
|
93
|
+
stegdoc encode a.pdf b.pdf --bundle-name pair.zip -p mysecret
|
|
90
94
|
```
|
|
91
95
|
|
|
92
|
-
### `decode
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
stegdoc decode <file> [options]
|
|
96
|
-
```
|
|
96
|
+
### `decode <file>`
|
|
97
97
|
|
|
98
98
|
| Option | Description | Default |
|
|
99
99
|
|--------|-------------|---------|
|
|
100
|
-
| `-o, --output <path>` | Output file
|
|
100
|
+
| `-o, --output <path>` | Output file or directory | Original filename |
|
|
101
101
|
| `-p, --password <pass>` | Decryption password | Prompt if needed |
|
|
102
102
|
| `--force` | Overwrite existing files | Prompt |
|
|
103
103
|
| `-q, --quiet` | Minimal output | Off |
|
|
104
|
-
| `-y, --yes` | Skip prompts, fail if password needed | Off |
|
|
104
|
+
| `-y, --yes` | Skip prompts, fail if a password is needed | Off |
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
Point `decode` at any one part, a directory holding the parts, or a ZIP of
|
|
107
|
+
them; the rest are found automatically.
|
|
107
108
|
|
|
108
109
|
```bash
|
|
109
|
-
# Decode with password
|
|
110
110
|
stegdoc decode access_log_20260315_1200_A1B2_part1.xlsx -p mysecret
|
|
111
|
-
|
|
112
|
-
# Decode DOCX
|
|
113
111
|
stegdoc decode system_report_20260315_0800_CD42_part1.docx -p mysecret
|
|
114
|
-
|
|
115
|
-
# Multi-part files auto-detected (just provide part 1)
|
|
116
|
-
stegdoc decode access_log_20260315_1200_A1B2_part1.xlsx -p mysecret
|
|
112
|
+
stegdoc decode stegdoc-parts.zip -p mysecret -o ./restored
|
|
117
113
|
```
|
|
118
114
|
|
|
119
|
-
### `info
|
|
115
|
+
### `info <file>`
|
|
120
116
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
Reads metadata without decoding: cover format and version, original filename
|
|
118
|
+
and size, whether it is encrypted and compressed, the part count, and whether
|
|
119
|
+
metadata is authenticated.
|
|
124
120
|
|
|
125
|
-
### `verify
|
|
121
|
+
### `verify <file> [-p <pass>]`
|
|
126
122
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
```
|
|
123
|
+
Runs the structural and password checks without writing any output. It exits
|
|
124
|
+
non-zero if the file will not decode.
|
|
130
125
|
|
|
131
|
-
## How
|
|
126
|
+
## How it works
|
|
132
127
|
|
|
133
|
-
###
|
|
128
|
+
### Pipeline
|
|
134
129
|
|
|
135
130
|
```
|
|
136
|
-
Input
|
|
137
|
-
|
|
138
|
-
[Brotli
|
|
139
|
-
|
|
140
|
-
[AES-256-GCM
|
|
141
|
-
|
|
142
|
-
[
|
|
143
|
-
|
|
144
|
-
[Office
|
|
145
|
-
|
|
146
|
-
Output
|
|
131
|
+
Input
|
|
132
|
+
|
|
|
133
|
+
[Brotli q6] skipped for already-compressed types
|
|
134
|
+
|
|
|
135
|
+
[AES-256-GCM] optional
|
|
136
|
+
|
|
|
137
|
+
[log-embed] payload spread across log line fields
|
|
138
|
+
|
|
|
139
|
+
[Office wrapper] XLSX access logs or a DOCX incident report
|
|
140
|
+
|
|
|
141
|
+
Output part(s)
|
|
147
142
|
```
|
|
148
143
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
Each nginx access log entry carries **114 bytes** of payload across 6 channels:
|
|
144
|
+
Each log row carries **114 raw bytes** across six channels:
|
|
152
145
|
|
|
153
|
-
| Channel |
|
|
154
|
-
|
|
146
|
+
| Channel | Encoding | Bytes |
|
|
147
|
+
|---------|----------|-------|
|
|
155
148
|
| URL path segment | base64url | 21 |
|
|
156
149
|
| Query param `token` | base64url | 21 |
|
|
157
150
|
| Query param `state` | base64url | 21 |
|
|
158
151
|
| Referer `ref` param | base64url | 21 |
|
|
159
|
-
| X-Request-ID | UUID v4
|
|
160
|
-
| X-Trace-ID | 32-char hex | 16 |
|
|
152
|
+
| `X-Request-ID` | UUID v4 | 14 |
|
|
153
|
+
| `X-Trace-ID` | 32-char hex | 16 |
|
|
154
|
+
|
|
155
|
+
Metadata and encryption parameters travel in header lines marked by the
|
|
156
|
+
`/api/v1/health` path, in a length-prefixed frame:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
STGD06|<metaLen>|<encLen>|<kdfLen>|{metadataJson}{encryptionMeta}{kdfParams}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
v5 uses the shorter `STGD05|<metaLen>|<encLen>|...` frame. The decoder
|
|
163
|
+
dispatches on the marker.
|
|
161
164
|
|
|
162
|
-
|
|
165
|
+
Decoding uses `payloadSize` and `dataLineCount` from the metadata to truncate
|
|
166
|
+
the payload. Filler rows are appended for realism and ignored on decode.
|
|
163
167
|
|
|
164
|
-
|
|
168
|
+
### Covers
|
|
165
169
|
|
|
166
|
-
**
|
|
170
|
+
**XLSX** — a single "Access Logs" sheet of realistic nginx entries with columns
|
|
171
|
+
for remote address, timestamp, method, request, status, bytes, referer,
|
|
172
|
+
user-agent, `X-Request-ID`, and `X-Trace-ID`. No hidden sheets.
|
|
167
173
|
|
|
168
|
-
|
|
174
|
+
**DOCX** — a Hebrew RTL incident report: title, executive summary, timeline
|
|
175
|
+
table, log excerpts in monospace blocks, root cause, and recommendations. The
|
|
176
|
+
prose is generated deterministically from the payload hash, so covers do not
|
|
177
|
+
repeat. DOCX refuses inputs over 1 MB unless `--no-limit` is given; use XLSX
|
|
178
|
+
for large payloads.
|
|
169
179
|
|
|
170
|
-
|
|
171
|
-
- **Key Derivation**: PBKDF2-SHA256 with 100,000 iterations
|
|
172
|
-
- **Key Size**: 256 bits
|
|
173
|
-
- **IV**: 96 bits (randomly generated per part)
|
|
174
|
-
- **Salt**: 128 bits (shared per session)
|
|
175
|
-
- **Authentication**: 128-bit auth tag
|
|
180
|
+
### Multi-part output
|
|
176
181
|
|
|
177
|
-
|
|
182
|
+
Large payloads are split across parts. Parts are built in parallel, each with
|
|
183
|
+
its own IV and tag but a shared session salt, and the CLI prints progress.
|
|
184
|
+
Decode finds the sibling parts automatically.
|
|
185
|
+
|
|
186
|
+
Filenames are decoys:
|
|
178
187
|
|
|
179
188
|
```
|
|
180
189
|
access_log_YYYYMMDD_HH00_XXXX[_partN].xlsx
|
|
181
190
|
system_report_YYYYMMDD_HH00_XXXX[_partN].docx
|
|
182
191
|
```
|
|
183
192
|
|
|
184
|
-
##
|
|
193
|
+
## Encryption
|
|
194
|
+
|
|
195
|
+
Encryption is optional but recommended. Without `-p`, the payload is hidden but
|
|
196
|
+
not encrypted.
|
|
197
|
+
|
|
198
|
+
### v6 (default)
|
|
199
|
+
|
|
200
|
+
v6 makes the metadata tamper-evident and uses a memory-hard KDF. The cover,
|
|
201
|
+
channels, chunking, and filenames are identical to v5; only the header and
|
|
202
|
+
crypto change.
|
|
203
|
+
|
|
204
|
+
| | |
|
|
205
|
+
|---|---|
|
|
206
|
+
| Cipher | AES-256-GCM |
|
|
207
|
+
| Key derivation | Argon2id, version 19, `m=65536` KiB, `t=3`, `p=1` |
|
|
208
|
+
| Key | 256-bit |
|
|
209
|
+
| IV | 96-bit, random per part |
|
|
210
|
+
| Salt | 128-bit, shared per session |
|
|
211
|
+
| Tag | 128-bit |
|
|
212
|
+
|
|
213
|
+
The KDF parameters are recorded in the file and reproduced on decode. When
|
|
214
|
+
encrypted, the AEAD associated data is the header frame minus the encryption
|
|
215
|
+
parameters, so changing the original filename, size, content hash, or KDF
|
|
216
|
+
parameters breaks decryption. The frame is
|
|
217
|
+
`STGD06|<metaLen>|<encLen>|<kdfLen>|...`.
|
|
218
|
+
|
|
219
|
+
### v5 (opt-in, `--v5`)
|
|
220
|
+
|
|
221
|
+
v5 uses PBKDF2 and leaves the metadata unauthenticated. It exists for decoders
|
|
222
|
+
that predate v6, and its read compatibility is permanent.
|
|
223
|
+
|
|
224
|
+
| | |
|
|
225
|
+
|---|---|
|
|
226
|
+
| Cipher | AES-256-GCM |
|
|
227
|
+
| Key derivation | PBKDF2-SHA256, 100,000 iterations |
|
|
228
|
+
| Key | 256-bit |
|
|
229
|
+
| IV | 96-bit, random per part |
|
|
230
|
+
| Salt | 128-bit, shared per session |
|
|
231
|
+
| Tag | 128-bit |
|
|
232
|
+
|
|
233
|
+
v6 requires the native engine to produce; `--v5` is the only format the
|
|
234
|
+
JavaScript fallback can emit. The decoder reads both versions without a flag.
|
|
235
|
+
|
|
236
|
+
## Decode inputs
|
|
237
|
+
|
|
238
|
+
`decode` accepts:
|
|
239
|
+
|
|
240
|
+
- a single encoded `.xlsx`/`.docx`,
|
|
241
|
+
- a directory containing the sibling parts,
|
|
242
|
+
- a ZIP holding the parts.
|
|
243
|
+
|
|
244
|
+
A ZIP is expanded, non-container entries are ignored, and the first complete
|
|
245
|
+
part set is decoded. Only ZIP is supported; RAR and 7z would need extra
|
|
246
|
+
decoders.
|
|
247
|
+
|
|
248
|
+
## Browser tool
|
|
249
|
+
|
|
250
|
+
The same engine also runs as WebAssembly in a single self-contained HTML file,
|
|
251
|
+
for offline use where installing anything is not an option.
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pnpm install
|
|
255
|
+
pnpm build:web # -> dist/stegdoc.html
|
|
256
|
+
```
|
|
185
257
|
|
|
186
|
-
|
|
258
|
+
Open `dist/stegdoc.html` in a browser. Encoding and decoding run in a Web Worker
|
|
259
|
+
so the page stays responsive; nothing is uploaded and no network is used. The UI
|
|
260
|
+
offers XLSX or DOCX, v6 or v5, an optional password, an optional chunk size, and
|
|
261
|
+
Brotli compression. Several files can be selected at once and are bundled into
|
|
262
|
+
one zip before encoding. When the browser supports the File System Access API,
|
|
263
|
+
the page asks for an output folder and writes the documents straight into it;
|
|
264
|
+
otherwise a single part downloads directly and a multi-part set downloads as one
|
|
265
|
+
`stegdoc-parts.zip`. Input is held in memory, so the UI warns above 64 MiB and
|
|
266
|
+
refuses past 128 MiB with a pointer to the CLI.
|
|
267
|
+
|
|
268
|
+
## Security model
|
|
269
|
+
|
|
270
|
+
- The native engine performs no filesystem writes. The CLI owns the output
|
|
271
|
+
path, the overwrite prompt, and the write.
|
|
272
|
+
- The original filename in the metadata is untrusted. It is reduced to a bare
|
|
273
|
+
filename and cannot escape the chosen output directory.
|
|
274
|
+
- Decompression output and ZIP expansion are bounded, so a crafted file fails
|
|
275
|
+
on the cap instead of exhausting memory or disk.
|
|
276
|
+
- `contentHash` is verified after decoding and the output is deleted on
|
|
277
|
+
mismatch.
|
|
278
|
+
- v6 binds the metadata to the ciphertext; v5 metadata is plaintext and its
|
|
279
|
+
integrity rests on `contentHash` and the path rules.
|
|
280
|
+
|
|
281
|
+
The wire format is specified in [`spec/FORMAT.md`](spec/FORMAT.md).
|
|
282
|
+
|
|
283
|
+
## Compatibility
|
|
284
|
+
|
|
285
|
+
- The decoder auto-detects the version, so no flag is needed to read old files.
|
|
286
|
+
- v6 is the default output. `--v5` emits the older format; both cover XLSX and
|
|
287
|
+
DOCX. `--legacy` produces v4 DOCX only; legacy XLSX is unsupported.
|
|
288
|
+
- v3/v4 are read-only paths kept for old files.
|
|
289
|
+
- Log-embed (v5/v6) decoding requires the native engine. Without it, the CLI
|
|
290
|
+
fails loudly rather than falling back to an incomplete reader.
|
|
291
|
+
- Encoding and decoding are randomised, so two encodes of the same input are
|
|
292
|
+
not byte-identical; conformance is defined on the decode direction.
|
|
293
|
+
|
|
294
|
+
## Building from source
|
|
295
|
+
|
|
296
|
+
Requires Node.js >= 18 and a Rust toolchain.
|
|
187
297
|
|
|
188
298
|
```bash
|
|
189
|
-
|
|
299
|
+
pnpm install
|
|
300
|
+
pnpm build:native # build the napi binding -> native/stegdoc.node
|
|
190
301
|
```
|
|
191
302
|
|
|
192
|
-
|
|
303
|
+
Then run the CLI directly with `node src/index.js <command>`.
|
|
304
|
+
|
|
305
|
+
| Command | Purpose |
|
|
306
|
+
|---------|---------|
|
|
307
|
+
| `pnpm test` | conformance against the frozen fixtures (builds native first) |
|
|
308
|
+
| `pnpm test:rust` | the Rust decoder against the same fixtures |
|
|
309
|
+
| `pnpm test:interop` | Rust encode -> JavaScript decode |
|
|
310
|
+
| `pnpm test:safety` | output-path traversal containment |
|
|
311
|
+
| `pnpm test:contract` | CLI flags, exit codes, filenames |
|
|
312
|
+
| `pnpm build:wasm` | the wasm binding -> `web/pkg` |
|
|
313
|
+
| `pnpm build:web` | the single-file browser tool -> `dist/stegdoc.html` |
|
|
314
|
+
| `pnpm test:wasm` | wasm round-trip, headless in Node |
|
|
315
|
+
| `pnpm test:browser` | the built page, round-trip from `file://` |
|
|
316
|
+
| `cargo test` | Rust unit and property tests |
|
|
193
317
|
|
|
194
318
|
## Requirements
|
|
195
319
|
|
|
196
|
-
- Node.js 18
|
|
320
|
+
- Node.js >= 18 for the CLI
|
|
321
|
+
- A supported platform for the prebuilt engine (see Install)
|
|
197
322
|
|
|
198
323
|
## License
|
|
199
324
|
|
|
200
|
-
MIT
|
|
325
|
+
MIT — see [LICENSE](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stegdoc",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Hide files inside Office documents (XLSX/DOCX) with AES-256 encryption and steganography",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,20 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node src/index.js",
|
|
11
11
|
"dev": "node src/index.js",
|
|
12
|
-
"
|
|
12
|
+
"fixtures": "node spec/tools/generate-fixtures.js",
|
|
13
|
+
"vectors": "node spec/tools/generate-channel-vectors.js",
|
|
14
|
+
"build:native": "node scripts/build-native.js",
|
|
15
|
+
"build:binding": "node scripts/build-binding.js",
|
|
16
|
+
"prepare-publish": "node scripts/prepare-publish.js",
|
|
17
|
+
"build:wasm": "node scripts/build-wasm.js",
|
|
18
|
+
"build:web": "node scripts/build-web.js",
|
|
19
|
+
"test": "pnpm build:native && node spec/tools/conformance.js",
|
|
20
|
+
"test:rust": "node spec/tools/conformance.js --bin target/debug/stegdoc",
|
|
21
|
+
"test:interop": "node spec/tools/interop.js",
|
|
22
|
+
"test:safety": "node spec/tools/safety.js",
|
|
23
|
+
"test:contract": "pnpm build:native && node spec/tools/contract.js",
|
|
24
|
+
"test:wasm": "node spec/tools/wasm-roundtrip.js",
|
|
25
|
+
"test:browser": "node spec/tools/browser.js"
|
|
13
26
|
},
|
|
14
27
|
"keywords": [
|
|
15
28
|
"cli",
|
|
@@ -54,5 +67,15 @@
|
|
|
54
67
|
"file-type": "^16.5.4",
|
|
55
68
|
"inquirer": "^8.2.6",
|
|
56
69
|
"ora": "^5.4.1"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"playwright-core": "^1.63.0"
|
|
73
|
+
},
|
|
74
|
+
"optionalDependencies": {
|
|
75
|
+
"@stegdoc/binding-win32-x64-msvc": "6.0.0",
|
|
76
|
+
"@stegdoc/binding-linux-x64-gnu": "6.0.0",
|
|
77
|
+
"@stegdoc/binding-linux-arm64-gnu": "6.0.0",
|
|
78
|
+
"@stegdoc/binding-darwin-x64": "6.0.0",
|
|
79
|
+
"@stegdoc/binding-darwin-arm64": "6.0.0"
|
|
57
80
|
}
|
|
58
81
|
}
|