-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathpsign-cli-matrix.json
More file actions
340 lines (340 loc) · 49.8 KB
/
Copy pathpsign-cli-matrix.json
File metadata and controls
340 lines (340 loc) · 49.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
{
"native_style_cli_aliases": "Recognized argv tokens starting with `/` after the subcommand are rewritten to GNU-style flags before clap parses (e.g. `verify /pa /q file.exe`, `verify /vr`, `verify /p7s path.p7s`, `verify /testroot`, `verify /sl`, `verify /ph` pairs with `/v` like native, `sign /fd SHA256 /tseal URL file`, `sign /sa OID value`, `sign /seal`, `sign /c TemplateName`, `timestamp /force`, `remove /s file.exe`, `rdp /sha256 HASH /l file.rdp`, `cert-store print /s MY /sha1 HASH`, `cert-store import-pfx /p password cert.pfx`). Unknown slash-prefixed tokens are preserved so Unix absolute paths still work. Additionally, psign-tool accepts `--` long aliases mirroring native names (sign `--fd`, `--tr`, `--tseal`, `--c`, `--sa`, `--fdchw`, `--tdchw`, `--rmc`, `--seal`, `--itos`, `--force`, `--nosealwarn`, `--noenclavewarn`; verify `--tw`, `--kp`, `--vr`, `--sha1`, `--p7s`, `--testroot`, `--sl`, `--bp`, `--enclave`; timestamp `--tr`/`--td`/`--tp`, `--force`, `--nosealwarn`; catdb `--d`/`--g`/`--r`/`--u`; remove `--s`/`--c`/`--u`; rdp `--sha256`, `--sha1`, `--l`; cert-store `--s`, `--sm`, `--sha1`, `--p`).",
"invocation": [
{"native": "@responsefile", "rust": "@responsefile", "tier": "P0", "status": "implemented", "notes": "UTF-8 (optional BOM) or UTF-16 LE/BE with BOM; invalid UTF-8 falls back to UTF-16 LE without BOM; one argument per line; double-quoted lines with \"\" escapes; blank line separates commands when @file is the only tail arg; inline @path splices one block; `@@` prefix strips one `@` for a literal leading at-sign; native signtool may mis-parse @ when the signtool.exe path contains spaces—parity script uses a TEMP copy"}
],
"sdk_help_source": "parity-output/signtool-help-*.txt (local / gitignored)",
"sdk_kit": "10.0.26100.0",
"learn_doc": "https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool",
"last_audited": "2026-05-30",
"matrix_scope": {
"native_cli": "Windows SDK signtool.exe and rdpsign.exe switch parity where psign-tool delegates to Win32 signing, verify, timestamp, catalog, remove, and RDP code.",
"portable_lifecycle": "Linux/macOS-safe digest, CMS inspection, explicit-anchor trust, local/remote signing, timestamp helpers, and package-specific primitives surfaced through psign-tool portable and --mode portable.",
"package_orchestration": "dotnet/sign-style planning and guarded execution through psign-tool code for PE/WinMD, NuGet/SNuGet, VSIX, ZIP, MSIX/AppX prepare, ClickOnce/VSTO, and App Installer companion signatures."
},
"capability_dimensions": [
{"id": "argv-parity", "meaning": "Native-style slash aliases, response files, and global mode/verbosity behavior."},
{"id": "sign-embed", "meaning": "Create a signature and embed it in the subject format or companion artifact."},
{"id": "timestamp", "meaning": "Create or attach legacy/RFC3161 timestamp evidence to an existing or newly-created signature."},
{"id": "verify-policy", "meaning": "Native WinTrust/CryptoAPI policy verification where available."},
{"id": "digest-consistency", "meaning": "Recompute format-specific indirect data and compare it with PKCS#7/CMS contents without making an OS trust decision."},
{"id": "explicit-anchor-trust", "meaning": "Portable CMS signature and certificate-chain verification to caller-supplied anchors, optionally with bounded AIA/OCSP/CRL fetches."},
{"id": "inspect-extract", "meaning": "Read, list, or extract embedded PKCS#7/CMS/XMLDSig/package metadata for diagnostics and split-signing workflows."},
{"id": "remove-mutate", "meaning": "Strip signatures, unauthenticated attributes, chains, or mutate signed package metadata."},
{"id": "orchestrate", "meaning": "Plan and execute nested inside-out signing flows across files, manifests, and package containers."}
],
"top_gap_ids": [
"portable-msix-bundle-upload-final-signing",
"catalog-driver-package-authoring",
"wdac-ci-policy-signing"
],
"top_gap_plan_doc": "docs/gap-analysis-signing-platforms.md#top-3-gaps-worth-filling-next",
"global_options": [
{"native": "/q", "rust": "--quiet (-q)", "tier": "P0", "status": "implemented", "notes": "Suppress stdout on success"},
{"native": "/v", "rust": "--verbose (-v)", "tier": "P0", "status": "implemented", "notes": "Verbose diagnostics"},
{"native": "/debug", "rust": "--debug", "tier": "P0", "status": "implemented", "notes": "Extra debug lines to stderr"}
],
"commands": {
"cert-store": [
{"native": "(portable psign store)", "rust": "cert-store import|import-pfx|list|print|export|remove", "tier": "P1", "status": "implemented", "notes": "File-based X.509 store under ~/.psign/cert-store by default; PSIGN_CERT_STORE or --cert-store-dir can override the base directory. Certificates are <SHA1>.der; optional local private keys are PEM unencrypted PKCS#8 <SHA1>.key."},
{"native": "(PFX import)", "rust": "cert-store import-pfx --password <value> <pfx>", "tier": "P1", "status": "implemented", "notes": "Extracts cert+key from PKCS#12/PFX and stores DER certificate plus PEM PKCS#8 key; the PFX is not retained internally."},
{"native": "(private key import/export)", "rust": "cert-store import --key <key.pem>; cert-store export --with-key --key-out <key.pem>", "tier": "P1", "status": "implemented", "notes": "Direct key import requires PEM unencrypted PKCS#8 with BEGIN PRIVATE KEY; key export writes the matching .key separately from --out."},
{"native": "/s", "rust": "--store (--s)", "tier": "P1", "status": "implemented", "notes": "Selects a Windows-like logical store directory such as MY, Root, or CA."},
{"native": "/sm", "rust": "--machine-store (--sm)", "tier": "P1", "status": "implemented", "notes": "Selects LocalMachine under the configured psign cert-store base directory; does not use /etc/psign yet."},
{"native": "/sha1", "rust": "--sha1", "tier": "P1", "status": "implemented", "notes": "Selects certificate by uppercase SHA-1 over full DER bytes; input accepts case-insensitive hex with optional spaces or colons."}
],
"sign": [
{"native": "/a", "rust": "--auto-select", "tier": "P0", "status": "implemented"},
{"native": "/ac", "rust": "--additional-cert", "tier": "P0", "status": "implemented", "notes": "DER/serialized cert file merged into signing store"},
{"native": "/c", "rust": "--certificate-template (--c)", "tier": "P2", "status": "partial", "notes": "CLI + argv; explicit not-implemented error"},
{"native": "/sa", "rust": "--sign-auth (--sa)", "tier": "P1", "status": "partial", "notes": "Repeatable OID+value; explicit not-implemented error"},
{"native": "/fdchw", "rust": "--fdchw", "tier": "P1", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/tdchw", "rust": "--tdchw", "tier": "P1", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/rmc", "rust": "--rmc", "tier": "P2", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/seal", "rust": "--seal", "tier": "P1", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/itos", "rust": "--itos", "tier": "P1", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/force", "rust": "--force (sign subcommand)", "tier": "P1", "status": "partial", "notes": "Sign-time sealing removal; explicit not-implemented (timestamp also has --force)"},
{"native": "/nosealwarn", "rust": "--nosealwarn (sign)", "tier": "P1", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/noenclavewarn", "rust": "--noenclavewarn", "tier": "P1", "status": "partial", "notes": "Explicit not-implemented error"},
{"native": "/csp", "rust": "--csp", "tier": "P0", "status": "implemented"},
{"native": "/d", "rust": "--description", "tier": "P0", "status": "implemented", "notes": "SIGNER_ATTR_AUTHCODE.pwszName"},
{"native": "/dg", "rust": "--digest-generate", "tier": "P1", "status": "partial", "notes": "Returns explicit error; use native signtool for split digest"},
{"native": "/di", "rust": "--digest-ingest", "tier": "P1", "status": "partial"},
{"native": "/ds", "rust": "--digest-sign-only", "tier": "P1", "status": "partial"},
{"native": "/dlib", "rust": "--dlib", "tier": "P0", "status": "implemented"},
{"native": "/dmdf", "rust": "--dmdf", "tier": "P0", "status": "implemented", "notes": "Windows dlib metadata; in --mode portable Artifact Signing PE/WinMD signing, accepted as metadata JSON without loading the dlib"},
{"native": "/dxml", "rust": "--digest-xml", "tier": "P1", "status": "partial"},
{"native": "/du", "rust": "--description-url", "tier": "P0", "status": "implemented"},
{"native": "/f", "rust": "--pfx", "tier": "P0", "status": "implemented"},
{"native": "/fd", "rust": "--digest", "tier": "P0", "status": "implemented", "notes": "Native signtool 10.0.26100.0 throws `No /fd flag specified` when omitted; psign currently defaults to SHA-256 for compatibility/back-compat"},
{"native": "/fd certHash", "rust": "--digest cert-hash", "tier": "P0", "status": "implemented", "notes": "Uses CERT_SIGN_HASH_CNG_ALG_PROP_ID when available"},
{"native": "/i", "rust": "--issuer-name", "tier": "P0", "status": "implemented"},
{"native": "/kc", "rust": "--key-container", "tier": "P0", "status": "implemented"},
{"native": "/n", "rust": "--subject-name", "tier": "P0", "status": "implemented"},
{"native": "/nph", "rust": "--no-page-hashes", "tier": "P0", "status": "implemented", "notes": "Sets SIGNTOOL_PAGE_HASHES=0 around SignerSignEx3"},
{"native": "/p", "rust": "--password", "tier": "P0", "status": "implemented"},
{"native": "/p7", "rust": "--pkcs7-output-dir", "tier": "P2", "status": "partial", "notes": "Explicit error; PKCS#7 product signing differs from PE SIP"},
{"native": "/p7ce", "rust": "--pkcs7-content-embedding", "tier": "P2", "status": "partial"},
{"native": "/p7co", "rust": "--pkcs7-content-oid", "tier": "P2", "status": "partial"},
{"native": "/ph", "rust": "--page-hashes", "tier": "P0", "status": "implemented", "notes": "Requires --dlib/--dmdf"},
{"native": "/r", "rust": "--root-subject-name", "tier": "P0", "status": "implemented"},
{"native": "/s", "rust": "--store-name", "tier": "P0", "status": "implemented"},
{"native": "/sha1", "rust": "--cert-sha1", "tier": "P0", "status": "implemented", "notes": "Windows mode selects from PFX/system stores; `--mode portable sign` resolves <SHA1>.der plus <SHA1>.key from the file cert-store for PE/WinMD RSA/SHA-256 signing."},
{"native": "/sm", "rust": "--machine-store", "tier": "P0", "status": "implemented"},
{"native": "/t", "rust": "--legacy-timestamp-url", "tier": "P0", "status": "implemented", "notes": "Mutually exclusive with --timestamp-url"},
{"native": "/td", "rust": "--timestamp-digest", "tier": "P0", "status": "implemented", "notes": "Required for RFC3161 sign-time timestamp paths (`/tr` and `/tseal`); legacy `/t` does not require it"},
{"native": "/tr", "rust": "--timestamp-url", "tier": "P0", "status": "implemented"},
{"native": "/tseal", "rust": "--seal-timestamp-url (--tseal)", "tier": "P0", "status": "implemented", "notes": "Sign-time sealed RFC3161 URL; mutually exclusive with /tr and /t; same SignerSignEx3 RFC3161 path as /tr here"},
{"native": "/u", "rust": "--eku-oid", "tier": "P0", "status": "implemented"},
{"native": "/uw", "rust": "--eku-windows-system-component", "tier": "P0", "status": "implemented"},
{"native": "(experimental)", "rust": "--rust-sip pe|off", "tier": "P2", "status": "partial", "notes": "Post-sign PE Authenticode digest vs PKCS#7 indirect digest after `SignerSignEx3`; `PSIGN_RUST_SIP=pe`; `/rust-sip pe` native argv; not production SIP replacement"},
{"native": "(experimental env)", "rust": "PSIGN_RUST_SIP", "tier": "P2", "status": "partial", "notes": "`pe` / `script` / `msi` / `esd` / `msix` / `cab` / `catalog` enable digest gates; `off` disables env; `--rust-sip off` overrides"},
{"native": "(experimental)", "rust": "--rust-sip script", "tier": "P2", "status": "partial", "notes": "Post-sign script digest vs PKCS#7: PowerShell UTF-16 strip (pwrshsip); WSH strip + offset dword (wshext); COM text decode may differ"},
{"native": "(experimental)", "rust": "--rust-sip msi", "tier": "P2", "status": "partial", "notes": "Post-sign MSI OLE fingerprint vs PKCS#7 indirect digest after `SignerSignEx3` (Signify-compatible `sip_rust::msi_digest`); `/rust-sip msi` argv; only when target resolves to Windows Installer format"},
{"native": "(experimental)", "rust": "--rust-sip esd", "tier": "P2", "status": "partial", "notes": "Post-sign WIM/ESD prefix digest vs PKCS#7 (`sip_rust::esd_digest`, `EsdSip.dll` semantics); `/rust-sip esd` argv; `.wim`/`.esd` only"},
{"native": "(experimental)", "rust": "--rust-sip msix", "tier": "P2", "status": "partial", "notes": "Cleartext MSIX/APPX/bundles only; post-sign ZIP-rehash digest vs PKCS#7 (`sip_rust::msix_digest`); `/rust-sip msix`; encrypted `.eappx`/`.emsix` rejected"},
{"native": "(experimental)", "rust": "--rust-sip cab", "tier": "P2", "status": "partial", "notes": "Post-sign CAB Authenticode digest vs PKCS#7 (`sip_rust::cab_digest`); `/rust-sip cab`; `.cab` only"},
{"native": "(experimental)", "rust": "--rust-sip catalog", "tier": "P2", "status": "partial", "notes": "Post-sign catalog digest vs PKCS#7 (`sip_rust::catalog_digest`); `/rust-sip catalog`; `.cat` only"}
],
"verify": [
{"native": "/a", "rust": "--catalog-search all", "tier": "P0", "status": "implemented", "notes": "Try resolved catalogs then embedded"},
{"native": "/ad", "rust": "--catalog-search default", "tier": "P0", "status": "implemented"},
{"native": "/as", "rust": "--catalog-search system", "tier": "P0", "status": "partial", "notes": "Subsystem GUID best-effort"},
{"native": "/ag", "rust": "--catalog-database-guid", "tier": "P0", "status": "implemented"},
{"native": "/c", "rust": "--catalog", "tier": "P0", "status": "implemented"},
{"native": "/hash", "rust": "--catalog-hash-algorithm", "tier": "P0", "status": "implemented"},
{"native": "/o", "rust": "--os-version-check", "tier": "P0", "status": "implemented", "notes": "Catalog WinTrust only: Rust sets `WTD_USE_DEFAULT_OSVER_CHECK` in `verify_with_catalog`; embedded `/pa` + `/o` is rejected by current signtool unless `/a`/`/c`/… so Rust errors without `--catalog`/`--catalog-search`. Parity: `verify_pa_os_version_check_exit_match`"},
{"native": "/pa", "rust": "--policy pa", "tier": "P0", "status": "implemented"},
{"native": "/pg", "rust": "--policy pg --policy-guid", "tier": "P0", "status": "implemented"},
{"native": "/kp", "rust": "--kernel-policy", "tier": "P0", "status": "implemented"},
{"native": "/vr", "rust": "--revocation-check (--vr)", "tier": "P0", "status": "implemented", "notes": "WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT when set"},
{"native": "/tw", "rust": "--warn-if-not-timestamped", "tier": "P0", "status": "implemented"},
{"native": "/ds", "rust": "--signature-index", "tier": "P0", "status": "implemented"},
{"native": "/all", "rust": "--all-signatures", "tier": "P0", "status": "implemented"},
{"native": "/ms", "rust": "--multiple-semantics", "tier": "P1", "status": "partial", "notes": "Documented no-op; WinVerifyTrust default varies by OS"},
{"native": "/p7", "rust": "--verify-pkcs7-file", "tier": "P0", "status": "partial", "notes": "Same WinTrust file path as PE; PKCS-only semantics limited"},
{"native": "/d", "rust": "--print-description", "tier": "P1", "status": "implemented", "notes": "SPC_SP_OPUS_INFO from WinVerifyTrust state; requires -v like native"},
{"native": "/ph", "rust": "--verify-page-hashes", "tier": "P1", "status": "implemented", "notes": "Requires -v like native; WTD_HASH_ONLY_FLAG + OID scan for SPC_PE_IMAGE_PAGE_HASHES; warns exit 2 if absent; portable probe + table parse (no WinTrust): `psign-tool portable pe-has-page-hashes` / `pe-page-hash-info` — see `portable_digest_cli`"},
{"native": "/r", "rust": "--chain-root-subject", "tier": "P0", "status": "implemented"},
{"native": "/sha1", "rust": "--signer-thumbprint-sha1", "tier": "P0", "status": "implemented", "notes": "Repeatable; signer cert SHA1 must match one value"},
{"native": "/ca", "rust": "--intermediate-ca-sha1", "tier": "P0", "status": "implemented", "notes": "Repeatable; at least one intermediate CA thumbprint must match chain"},
{"native": "/u", "rust": "--warn-if-missing-eku", "tier": "P0", "status": "implemented", "notes": "Verify verb: warn exit 2 if EKU OID missing (distinct from sign --eku-oid)"},
{"native": "/p7content", "rust": "--detached-pkcs7-content", "tier": "P0", "status": "implemented", "notes": "Content file for detached PKCS#7 verify"},
{"native": "(detached sig file)", "rust": "--detached-pkcs7 (--p7s)", "tier": "P0", "status": "implemented", "notes": "Alias p7s for detached PKCS#7 path"},
{"native": "(allow test roots)", "rust": "--allow-test-root (--testroot)", "tier": "P1", "status": "implemented", "notes": "Windows argv /testroot supported"},
{"native": "(portable explicit root)", "rust": "--trusted-ca", "tier": "P1", "status": "implemented", "notes": "Portable trust only; repeatable PEM/DER root files, no OS trust-store writes. In `--mode portable verify`, supported formats route to portable trust by default when automatic AuthRoot is enabled; this flag supplies explicit roots and suppresses auto AuthRoot resolution."},
{"native": "(portable anchor directory)", "rust": "--anchor-dir", "tier": "P1", "status": "implemented", "notes": "Portable trust only; loads .crt/.cer/.pem files as anchors without elevation or persistent store changes."},
{"native": "(portable AIA)", "rust": "--online-aia", "tier": "P2", "status": "partial", "notes": "Portable trust only; explicit in-memory HTTP AIA caIssuers fetch for missing issuers. Revocation is available through OCSP/CRL HTTP overrides and CRL Distribution Points."},
{"native": "(portable AIA test override)", "rust": "--aia-url-override", "tier": "P2", "status": "partial", "notes": "Portable trust only; deterministic local test override used before certificate AIA URLs."},
{"native": "(portable OCSP)", "rust": "--online-ocsp", "tier": "P2", "status": "partial", "notes": "Portable trust only; sends HTTP OCSP requests and verifies issuing-CA-signed BasicOCSPResponse good/revoked/unknown status. Delegated responders, nonce, and freshness policy are not implemented yet."},
{"native": "(portable OCSP test override)", "rust": "--ocsp-url-override", "tier": "P2", "status": "partial", "notes": "Portable trust only; deterministic OCSP responder URL for local psign-server tests."},
{"native": "(portable CRL revocation mode)", "rust": "--revocation-mode off|best-effort|require", "tier": "P2", "status": "partial", "notes": "Portable trust only; require fails when CRL status cannot be obtained or when a signer/intermediate is revoked. Uses --crl-url-override or the first HTTP CRL Distribution Point URL; indirect/delta/freshness policy is not implemented yet."},
{"native": "(portable CRL test override)", "rust": "--crl-url-override", "tier": "P2", "status": "partial", "notes": "Portable trust only; deterministic HTTP CRL URL for local psign-server tests. CRL signatures are verified with the issuing CA."},
{"native": "(portable verification date)", "rust": "--as-of", "tier": "P1", "status": "implemented", "notes": "Portable trust only; fixed UTC date for reproducible chain validation."},
{"native": "/w2010pca", "rust": "--warn-pca-2010", "tier": "P0", "status": "implemented", "notes": "Warn exit 2 when PCA 2010 in chain; auto with driver policy or /kp"},
{"native": "/now2010pca", "rust": "--no-warn-pca-2010", "tier": "P0", "status": "implemented", "notes": "Suppress PCA 2010 warnings"},
{"native": "/sl", "rust": "--verify-sealing-signatures (--sl)", "tier": "P1", "status": "implemented", "notes": "WinTrust `WSS_VERIFY_SEALING` on embedded verify; not combined with `--catalog` path or detached PKCS#7; parity `verify_pa_sl_exit_match`"},
{"native": "/bp", "rust": "--biometric-policy (--bp)", "tier": "P1", "status": "partial", "notes": "CLI + argv; WinTrust Action GUID for biometric policy is not published in `SoftPub.h` / standard SDK headers like `WINTRUST_ACTION_GENERIC_VERIFY_V2` — needs parity against native `signtool.exe` or Microsoft guidance before safe wiring"},
{"native": "/enclave", "rust": "--enclave-policy (--enclave)", "tier": "P1", "status": "partial", "notes": "CLI + argv; same as /bp — dedicated enclave verify Action/policy not exposed in public Authenticode headers used elsewhere in this crate"},
{"native": "(experimental)", "rust": "--rust-sip-pe-digest-check", "tier": "P2", "status": "partial", "notes": "After embedded WinTrust success on PE/WinMD, recompute Authenticode digest in Rust vs PKCS#7; `/rust-sip-pe-digest-check` argv alias"},
{"native": "(experimental)", "rust": "--rust-sip-script-digest-check", "tier": "P2", "status": "partial", "notes": "After WinTrust on signed scripts (PowerShell or WSH), heuristic digest vs PKCS#7; `/rust-sip-script-digest-check` argv alias"},
{"native": "(experimental)", "rust": "--rust-sip-msi-digest-check", "tier": "P2", "status": "partial", "notes": "After WinTrust on signed `.msi`, Rust MSI SIP fingerprint vs PKCS#7 + optional `MsiDigitalSignatureEx` pre-hash; `/rust-sip-msi-digest-check` argv alias"},
{"native": "(experimental)", "rust": "--rust-sip-esd-digest-check", "tier": "P2", "status": "partial", "notes": "After WinTrust on signed `.wim`/`.esd`, Rust ESD SIP prefix digest vs PKCS#7; `/rust-sip-esd-digest-check` argv alias"},
{"native": "(experimental)", "rust": "--rust-sip-msix-digest-check", "tier": "P2", "status": "partial", "notes": "Cleartext packages only; after WinTrust success, Rust MSIX ZIP digest vs PKCS#7; `/rust-sip-msix-digest-check`; encrypted extensions explicit error"},
{"native": "(experimental)", "rust": "--rust-sip-cab-digest-check", "tier": "P2", "status": "partial", "notes": "After WinTrust on signed `.cab`, Rust CAB digest vs PKCS#7; `/rust-sip-cab-digest-check`"},
{"native": "(experimental)", "rust": "--rust-sip-catalog-digest-check", "tier": "P2", "status": "partial", "notes": "After WinTrust on `.cat`, Rust catalog digest vs PKCS#7; `/rust-sip-catalog-digest-check`"},
{"native": "(experimental)", "rust": "--rust-sip-all-digest-checks", "tier": "P2", "status": "partial", "notes": "Enables every `--rust-sip-*-digest-check` flag for this verify; `/rust-sip-all-digest-checks`; additive to WinVerifyTrust only"},
{"native": "(experimental)", "rust": "(verify rust sip)", "tier": "P2", "status": "partial", "notes": "Never replaces default WinVerifyTrust; consistency checks only"}
],
"timestamp": [
{"native": "/tr", "rust": "--rfc3161-url", "tier": "P0", "status": "implemented"},
{"native": "/tseal", "rust": "--seal-timestamp-url (--tseal)", "tier": "P0", "status": "implemented", "notes": "Mutually exclusive with /tr and /t; uses same SignerTimeStampEx3 RFC3161 path as /tr in this build"},
{"native": "/t", "rust": "--legacy-url", "tier": "P0", "status": "implemented"},
{"native": "/td", "rust": "--digest", "tier": "P0", "status": "implemented", "notes": "Required for RFC3161 timestamp paths (`/tr` and `/tseal`); legacy `/t` does not require it"},
{"native": "/tp", "rust": "--signature-index", "tier": "P0", "status": "implemented"},
{"native": "/p7", "rust": "--timestamp-pkcs7-files", "tier": "P1", "status": "partial", "notes": "Explicit error"},
{"native": "/force", "rust": "--remove-seal (--force)", "tier": "P1", "status": "partial", "notes": "CLI + argv; explicit not-implemented error"},
{"native": "/nosealwarn", "rust": "--no-seal-warn (--nosealwarn)", "tier": "P1", "status": "partial", "notes": "CLI + argv; explicit not-implemented error"}
],
"catdb": [
{"native": "/d", "rust": "--default-database", "tier": "P0", "status": "implemented"},
{"native": "/g", "rust": "--database-guid", "tier": "P0", "status": "implemented"},
{"native": "/r", "rust": "--remove", "tier": "P0", "status": "implemented"},
{"native": "/u", "rust": "--unique-name", "tier": "P0", "status": "implemented"}
],
"remove": [
{"native": "/s", "rust": "--strip-signature", "tier": "P0", "status": "implemented", "notes": "Global /q (--quiet): no per-file success lines on stdout, matching native; `ImageEnumerateCertificates` uses `CERT_SECTION_TYPE_ANY` (aligned with remove /u path)"},
{"native": "/c", "rust": "--strip-chain-except-signer (--c)", "tier": "P1", "status": "implemented", "notes": "CryptMsgControl CMSG_CTRL_DEL_CERT after matching SignerInfo Issuer+Serial to cert bag; PE Image* replace PKCS#7; `/c`+`/u` one CryptMsg session (parity `remove_cu_sha256_match_native`)"},
{"native": "/u", "rust": "--strip-unauthenticated-attributes (--u)", "tier": "P1", "status": "implemented", "notes": "CryptMsgControl DEL_SIGNER_UNAUTH_ATTR + PE Image* replace PKCS#7; enumerate uses CERT_SECTION_TYPE_ANY"},
{"native": "(required mode)", "rust": "at least one of /s /c /u", "tier": "P0", "status": "implemented", "notes": "Matches native requirement text"}
],
"rdp": [
{"native": "rdpsign /sha256 <hash>", "rust": "rdp --sha256 <hash>", "tier": "P0", "status": "implemented", "notes": "Looks up the RDP signing certificate by SHA256 thumbprint in LocalMachine\\MY then CurrentUser\\MY; builds native SignScope/Signature records and overwrites the `.rdp` file on success."},
{"native": "rdpsign /sha1 <hash>", "rust": "rdp --sha1 <hash>", "tier": "P1", "status": "implemented", "notes": "Legacy thumbprint selection mode retained for older rdpsign compatibility."},
{"native": "/l", "rust": "--dry-run (--l)", "tier": "P0", "status": "implemented", "notes": "Signs and validates the generated payload without replacing the input file."},
{"native": "/q", "rust": "--quiet (-q)", "tier": "P0", "status": "implemented", "notes": "Uses the shared global quiet flag."},
{"native": "/v", "rust": "--verbose (-v)", "tier": "P0", "status": "implemented", "notes": "Uses the shared global verbose flag for per-file status."}
],
"code": [
{"native": "(dotnet/sign-style)", "rust": "code --dry-run --plan-json --base-directory <dir> --file-list <file>", "tier": "P1", "status": "implemented", "notes": "Plans file-list/glob selection plus nested ZIP/OPC inside-out ordering without modifying inputs."},
{"native": "(dotnet/sign-style)", "rust": "code (--cert <cert> --key <key>|--pfx <pfx> [--password <password>]|--sha1 <thumbprint> [--cert-store-dir <dir>]|--azure-key-vault-url <url> --azure-key-vault-certificate <name>|--artifact-signing-endpoint <url> --artifact-signing-account-name <acct> --artifact-signing-profile-name <profile>) --output <path> [--max-concurrency <n>] [--skip-signed|--overwrite] <app.exe|package.nupkg|package.snupkg|extension.vsix|bundle.zip|app.msix|app.msixupload|app.exe.manifest|app.exe.deploy|app.appinstaller>", "tier": "P1", "status": "partial", "notes": "Guarded execution for local RSA cert/key, PFX, portable cert-store SHA-1, Azure Key Vault, or Artifact Signing identity over PE/WinMD, package-native NuGet/SNuGet, VSIX, generic ZIP nested package entries, unsigned MSIX/AppX prepare with --publisher-name and AppxBlockMap regeneration, MSIX/AppX upload/bundle nested package prepare, encrypted MSIX/AppX OS-only diagnostics, ClickOnce .manifest/.application/.vsto XMLDSig signing, PE-like ClickOnce .deploy payloads, namespace-aware App Installer publisher updates plus top-level and nested ZIP companion signatures, --continue-on-error, --max-concurrency for independent top-level inputs, --skip-signed, --overwrite, and VSIX/ZIP/MSIX -> NuGet/VSIX -> PE/WinMD/ClickOnce-manifest/App-Installer-companion nested inside-out signing. Unsupported non-PE nested Authenticode payloads fail explicitly unless excluded."}
]
},
"tier_summary": {
"P0": "Common CLI surface aligned with native workflows where feasible",
"P1": "Digest split pipeline and advanced verify metadata — partial by design",
"P2": "Low-volume PKCS7 product modes and rare remove modes"
},
"code_sign_file_formats": [
{
"extensions": [".ps1", ".psm1", ".psd1"],
"windows_mechanism": "Registered Cryptography SIP for PowerShell / module / manifest files; native `signtool` and `SignerSignEx3` load the OS SIP implementation.",
"rust_path": "Same Win32 stack (`SignerSignEx3`, `WinVerifyTrust`) — uses the OS SIP DLL; see `src/win/code_sign_format.rs`.",
"parity": "`scripts/run-parity-diff.ps1`: `.ps1` — `sign_ps1_*`, `verify_ps1_*`, `artifact_verify_ps1_print_description_match` (`/d` `/du` + `verify /v /d` vs `--print-description`; shares `$parityDesc`/`$parityUrl` with PE). `.psm1` / `.psd1` — same plus `artifact_verify_psm1_print_description_match`, `artifact_verify_psd1_print_description_match`. Fixtures under `tests/fixtures/` or env overrides `PSIGN_PS1_UNSIGNED_FIXTURE`, `_PSM1_`, `_PSD1_`. Exact SHA256 when PKCS#7 matches native; else `artifact_semantic_match` if both `/pa` verify succeed."
},
{
"extensions": [".exe", ".dll", ".sys", ".ocx", ".efi", ".scr", ".cpl", ".mui"],
"windows_mechanism": "PE Authenticode (`WIN_CERTIFICATE`); SIP resolves from PE metadata.",
"rust_path": "Same Win32 SIP delegation as native; optional experimental `--rust-sip pe` post-sign digest gate (`crates/psign-sip-digest`, re-exported under `sip_rust`).",
"parity": "`run-parity-diff.ps1` `sign_pe_fixture_sha256_match_native` / `verify_pe_fixture_pa_exit_match` on `PSIGN_UNSIGNED_FIXTURE` (two-copy sign + SHA256 or verify-valid semantic match); plus `artifact_sign_two_pe_exit_parity` and semantic verify scenarios."
},
{
"extensions": [".winmd"],
"windows_mechanism": "Windows metadata files are CLI assemblies in a PE-based container; Authenticode via OS SIP (same `SignerSignEx3` / `WinVerifyTrust` stack as PE signing).",
"rust_path": "`CodeSignFormat::WindowsMetadata` in `src/win/code_sign_format.rs`; same Win32 delegation as native.",
"parity": "Optional `scripts/run-parity-diff.ps1` when `PSIGN_WINMD_UNSIGNED_FIXTURE` + `PSIGN_TEST_PFX` set: `sign_winmd_sha256_match_native`, `verify_winmd_pa_exit_match`, `artifact_verify_winmd_print_description_match`; optional `PSIGN_WINMD_TIMESTAMP_URL`. Local smoke: `scripts/sip-format-smoke.ps1`. `remove /s` allowed only for PE-image-backed mapped extensions — `.winmd` is treated as PE-backed (`Image*` APIs) like `.exe`."
},
{
"extensions": [".msix", ".msixbundle", ".appx", ".appxbundle"],
"windows_mechanism": "AppX/MSIX SIP; tooling often uses decoupled digest `/dlib` + `/dmdf` + `/ph`.",
"rust_path": "Same Win32 SIP + decoupled digest bridge as native.",
"parity": "`scripts/msix-parity-sign.ps1` and MSIX blocks in `run-parity-diff.ps1` (`artifact_msix_sign_semantic`, `artifact_msix_decoupled_semantic` when dlib env set). Description parity: `artifact_verify_msix_print_description_match` — sign with `/d` `/du` + RFC3161 (`PSIGN_MSIX_*` env), then `verify /v /d` vs `--print-description` (same strings as PE description test)."
},
{
"extensions": [".msi", ".msp", ".mst"],
"windows_mechanism": "Windows Installer SIP (OLE compound storage Authenticode).",
"rust_path": "`SignerSignEx3` / `WinVerifyTrust` — OS SIP; `code_sign_format::WindowsInstaller`; experimental digest parity in `sip_rust::msi_digest` (`--rust-sip msi`, `verify --rust-sip-msi-digest-check`); `remove` rejects (not PE `Image*`).",
"parity": "No bundled unsigned `.msi` in-repo (OLE compound); optional parity in `run-parity-diff.ps1` when `PSIGN_MSI_UNSIGNED_FIXTURE` + `PSIGN_TEST_PFX` point at a valid package: `sign_msi_sha256_match_native`, `verify_msi_pa_exit_match`, `artifact_verify_msi_print_description_match`. Optional sign-time RFC3161: `PSIGN_MSI_TIMESTAMP_URL`."
},
{
"extensions": [".wim", ".esd"],
"windows_mechanism": "WIM/ESD image SIP (`EsdSip.dll`; GUID `9F3053C5-439D-4BF7-8A77-04F0450A1D9F`).",
"rust_path": "`SignerSignEx3` / `WinVerifyTrust` — OS SIP; `code_sign_format::WimImage`; experimental digest parity in `sip_rust::esd_digest` (`--rust-sip esd`, `verify --rust-sip-esd-digest-check`); `remove` rejects.",
"parity": "No bundled signed WIM in-repo; optional local sign/verify with native `signtool` then `psign-tool verify /pa --rust-sip-esd-digest-check` for Rust consistency."
},
{
"extensions": [".js", ".vbs", ".wsf"],
"windows_mechanism": "Windows Script Host–related SIP where registered for the extension.",
"rust_path": "Same Win32 stack as native (`SignerSignEx3`, `WinVerifyTrust`); no in-tree SIP port.",
"parity": "`run-parity-diff.ps1`: per-extension sign/verify SHA256 + `artifact_verify_{js,vbs,wsf}_print_description_match` (`/d` `/du` then `verify /v /d` vs `--print-description`; same `$parityDesc`/`$parityUrl` as PE). Fixtures `unsigned-sample.{js,vbs,wsf}` or env `PSIGN_JS_UNSIGNED_FIXTURE`, `_VBS_`, `_WSF_`. Requires OS SIP registration per extension."
},
{
"extensions": [".rdp"],
"windows_mechanism": "`rdpsign.exe` parses RDP settings, signs the UTF-16 secure-settings blob with detached PKCS#7 (`CryptSignMessage`), serializes `{version,type,length,pkcs7}`, and writes `SignScope` / `Signature` records.",
"rust_path": "`psign-tool rdp --sha256 <thumbprint> file.rdp` implements the RDP-specific path directly; `psign-tool portable rdp --cert cert.pem --key key.pem file.rdp` uses the same RDP SignScope/secure-blob serializer and creates detached RSA/SHA-256 CMS without Win32. This is not a SIP/SignerSignEx3 file format.",
"parity": "Unit fixtures under `tests/fixtures/rdp/` cover UTF-8, UTF-8 BOM, UTF-16 LE/BE with and without BOM, partial/stale SignScope/Signature records, malformed records, secure blob generation, serialized signature shape, and a signed `.rdp` generated with the repo test PFX. Portable CLI tests cover external PKCS#7 embedding and local RSA/SHA-256 cert+key signing; Windows tests exercise the same shared fixtures through the `psign` crate and optional integration can compare against native `rdpsign` output shape."
},
{
"extensions": [".zip"],
"windows_mechanism": "No native signtool SIP peer for generic ZIP archives; package-specific ZIP containers such as VSIX, NuGet, and MSIX have their own signing formats.",
"rust_path": "`psign-tool portable verify-zip` and `trust-verify-zip` validate psign-defined custom ZIP Authenticode comment signatures. `psign-tool code` can also traverse generic ZIP containers for nested package/PE signing.",
"parity": "Portable tests cover `verify-zip` / `trust-verify-zip` and tamper rejection. See `docs/zip-authenticode-signing.md`; this is a psign compatibility format, not a WinTrust policy surface."
}
],
"portable_digest_cli": {
"binary": "psign-tool portable",
"crate": "crates/psign-digest-cli",
"depends_on": "crates/psign-sip-digest; crates/psign-authenticode-trust (trust-verify-* subcommands)",
"platforms_note": "Builds on Linux/macOS/Windows; no `windows` / WinVerifyTrust dependency.",
"purpose": "Optional digest recomputation vs PKCS#7 indirect data and PE page-hash OID scans — additive to native signtool, not a full replacement.",
"commands": [
{"name": "pe-digest", "maps_to_native_concept": "PE SIP image hash (algorithm-selectable)"},
{"name": "verify-pe", "maps_to_native_concept": "Consistency check after conceptual WinTrust success — similar to `psign-tool verify --rust-sip-pe-digest-check`"},
{"name": "trust-verify-pe", "maps_to_native_concept": "Explicit-anchor PKCS#7 trust + picky chain + PE digest (not WinTrust); optional `--as-of YYYY-MM-DD` for expired fixtures"},
{"name": "trust-verify-cab", "maps_to_native_concept": "`verify-cab` digest consistency then same trust stack as PE"},
{"name": "trust-verify-msi", "maps_to_native_concept": "`verify-msi` digest consistency then same trust stack as PE"},
{"name": "trust-verify-esd", "maps_to_native_concept": "`verify-esd` digest consistency then same trust stack as PE"},
{"name": "trust-verify-catalog", "maps_to_native_concept": "`verify-catalog` CMS digest consistency then picky trust when Authenticode-wrapped"},
{"name": "trust-verify-detached", "maps_to_native_concept": "Detached PKCS#7 vs raw content bytes (digest algo inferred from PKCS#7); blob normalization like Win32 detached helpers"},
{"name": "trust-verify-zip", "maps_to_native_concept": "Custom ZIP Authenticode comment signature digest binding plus same explicit-anchor trust stack as PE"},
{"name": "pe-has-page-hashes", "maps_to_native_concept": "Subset of `verify /ph` — CMS signed-attribute probe plus raw OID TLV fallback"},
{"name": "pe-page-hash-info", "maps_to_native_concept": "CMS listing of SPC_PE_IMAGE_PAGE_HASHES V1/V2 attrs plus Authenticode flat-table parse (`parsed_page_hash_pairs`; `-` if unwrap fails)"},
{"name": "verify-pe-page-hashes", "maps_to_native_concept": "Experimental contiguous raw-file range verify vs parsed page-hash digests — not full WinTrust `/ph`"},
{"name": "pe-authenticode-ranges", "maps_to_native_concept": "Diagnostic listing of disjoint PE file ranges hashed by Authenticode image digest (`authenticode-rs` layout); aids `/ph` vs subject-digest reasoning"},
{"name": "verify-cab", "maps_to_native_concept": "`verify --rust-sip-cab-digest-check`"},
{"name": "verify-zip", "maps_to_native_concept": "Custom ZIP Authenticode comment signature digest binding and reconstructed script digest"},
{"name": "verify-msi", "maps_to_native_concept": "`verify --rust-sip-msi-digest-check`"},
{"name": "verify-esd", "maps_to_native_concept": "`verify --rust-sip-esd-digest-check`"},
{"name": "verify-msix", "maps_to_native_concept": "`verify --rust-sip-msix-digest-check` (cleartext packages)"},
{"name": "msix-manifest-info", "maps_to_native_concept": "Inspect cleartext MSIX/AppX AppxManifest.xml Identity metadata"},
{"name": "msix-set-publisher", "maps_to_native_concept": "Update unsigned cleartext MSIX/AppX AppxManifest.xml Identity Publisher before final signing"},
{"name": "clickonce-deploy-info", "maps_to_native_concept": "Inspect ClickOnce `.deploy` payload names for rename/sign/restore workflows"},
{"name": "clickonce-copy-deploy-payload", "maps_to_native_concept": "Copy a ClickOnce `.deploy` payload to an explicit undeployed output path before signing"},
{"name": "clickonce-manifest-hashes", "maps_to_native_concept": "Verify ClickOnce manifest file size/digest references before or after payload signing"},
{"name": "clickonce-update-manifest-hashes", "maps_to_native_concept": "Update ClickOnce manifest file size/digest references after payload signing"},
{"name": "clickonce-sign-manifest", "maps_to_native_concept": "Deterministic portable structural XMLDSig signing for ClickOnce manifests (not full Mage parity)"},
{"name": "clickonce-sign-manifest-prehash", "maps_to_native_concept": "ClickOnce remote-signing primitive: compute the SignedInfo digest that an external RSA signer signs"},
{"name": "clickonce-sign-manifest-from-signature", "maps_to_native_concept": "ClickOnce remote-signing primitive: assemble manifest XMLDSig from signer certificate plus external RSA signature bytes"},
{"name": "clickonce-verify-manifest-signature", "maps_to_native_concept": "Verify deterministic portable ClickOnce manifest XMLDSig signature value, manifest digest, and optional explicit-anchor signer chain"},
{"name": "verify-catalog", "maps_to_native_concept": "`verify --rust-sip-catalog-digest-check`"},
{"name": "verify-catalog-member", "maps_to_native_concept": "Explicit file + catalog membership check by CTL member SpcIndirectData digest; no OS catalog database search"},
{"name": "verify-script", "maps_to_native_concept": "`verify --rust-sip-script-digest-check`"},
{"name": "cab-digest", "maps_to_native_concept": "CAB Authenticode digest hex without PKCS#7"},
{"name": "extract-cab-pkcs7", "maps_to_native_concept": "Tail PKCS#7 from signed CAB (same blob AzureSignTool/CMS path would hash for signer attrs)"},
{"name": "cab-signer-rs256-prehash", "maps_to_native_concept": "SHA-256 over SignerInfo signedAttrs SET (RFC 5652 §5.4) for RSA KV RS256 — not cab-digest"},
{"name": "extract-msi-pkcs7", "maps_to_native_concept": "DigitalSignature stream PKCS#7 DER from signed MSI"},
{"name": "msi-signer-rs256-prehash", "maps_to_native_concept": "Same RS256 prehash as pkcs7-signer on MSI embedded PKCS#7 — not verify-msi installer fingerprint"},
{"name": "catalog-signer-rs256-prehash", "maps_to_native_concept": "Same RS256 prehash on whole-file .cat PKCS#7 as pkcs7-signer-rs256-prehash; distinct from verify-catalog CTL scan"},
{"name": "pkcs7-signer-rs256-prehash", "maps_to_native_concept": "RS256 prehash from PKCS#7 DER alone (post-extract from PE/CAB/MSI or detached blob)"},
{"name": "pe-signer-rs256-prehash", "maps_to_native_concept": "RS256 prehash from embedded PE PKCS#7 row (index + signer-index)"},
{"name": "inspect-pkcs7", "maps_to_native_concept": "Standalone PKCS#7/P7X inspection; accepts ContentInfo, bare SignedData, or AppX PKCX-wrapped AppxSignature.p7x"},
{"name": "extract-pkcx-pkcs7", "maps_to_native_concept": "Strip AppX AppxSignature.p7x PKCX wrapper to inner PKCS#7 DER"},
{"name": "extract-pe-pkcs7", "maps_to_native_concept": "WIN_CERTIFICATE PKCS#7 row as raw DER (same index order as list-pe-pkcs7)"},
{"name": "list-pe-pkcs7", "maps_to_native_concept": "Enumerate embedded PKCS#7 rows (byte_len per index)"},
{"name": "inspect-pe-spc-indirect", "maps_to_native_concept": "JSON for SpcIndirectDataContent / digest in embedded PE PKCS#7"},
{"name": "append-pe-pkcs7", "maps_to_native_concept": "Experimental: append PKCS#7 row + recompute PE CheckSum — not SignerSignEx3"},
{"name": "sign-pe", "maps_to_native_concept": "Portable PE Authenticode signing: create RSA/SHA-2 SignedData with local key, Azure Key Vault RSA signing, or Azure Artifact Signing REST; optionally attach RFC3161 timestamp, append WIN_CERTIFICATE, recompute CheckSum; no WinTrust policy"},
{"name": "sign-cab", "maps_to_native_concept": "Portable unsigned single-volume CAB Authenticode signing: insert reserve header, create RSA/SHA-2 SignedData, append tail PKCS#7"},
{"name": "sign-msi", "maps_to_native_concept": "Portable MSI/MSP Authenticode signing: create RSA/SHA-2 SignedData and write the DigitalSignature OLE stream"},
{"name": "sign-catalog", "maps_to_native_concept": "Portable generic catalog signing: author CTL member entries, create RSA/SHA-2 SignedData over Microsoft CTL eContent; no catalog database or driver/INF policy"},
{"name": "timestamp-pe-rfc3161", "maps_to_native_concept": "Portable PE RFC3161 timestamp embedding: attach timeStampToken / granted TimeStampResp to SignerInfo unsigned attrs and replace PE PKCS#7 row"},
{"name": "rdp", "maps_to_native_concept": "Portable RDP SignScope/Signature writer using local RSA/SHA-256 cert+key or an externally-created detached PKCS#7"},
{"name": "pe-checksum", "maps_to_native_concept": "Optional header CheckSum vs ImageHlp-style computation"},
{"name": "inspect-authenticode", "maps_to_native_concept": "Portable PKCS#7 inspection JSON (PE or raw)"},
{"name": "artifact-signing-metadata-check", "maps_to_native_concept": "Validate --dmdf-style JSON shape (no network)"},
{"name": "artifact-signing-submit", "maps_to_native_concept": "Trusted Signing :sign LRO (feature artifact-signing-rest); hash file in, JSON out; PE/WinMD embedding is handled by sign-pe --artifact-signing-*"},
{"name": "azure-key-vault-sign-digest", "maps_to_native_concept": "KV keys/sign on digest file (feature azure-kv-sign-portable); AzureSignTool remote step analogue"},
{"name": "nupkg-signature-info", "maps_to_native_concept": "NuGet package-signature marker inspection for `.signature.p7s` (not SIP; groundwork for dotnet nuget sign-compatible portable signing)"},
{"name": "nupkg-digest", "maps_to_native_concept": "Unsigned NuGet package byte hash used by the package-signature properties document (SHA-256/384/512; rejects already signed packages)"},
{"name": "nupkg-signature-content", "maps_to_native_concept": "NuGet v1 signature-content document (`Version` plus OID-hash property) generated from an unsigned package hash"},
{"name": "nupkg-signature-pkcs7", "maps_to_native_concept": "NuGet split-signing primitive: create local RSA/SHA-2 CMS over generated signature-content bytes, optionally with RFC3161 timestamp token"},
{"name": "nupkg-signature-pkcs7-prehash", "maps_to_native_concept": "NuGet remote-signing primitive: compute the stable CMS authenticated-attributes digest that an external RSA signer signs; requires the signer certificate for NuGet signingCertificateV2"},
{"name": "nupkg-signature-pkcs7-from-signature", "maps_to_native_concept": "NuGet remote-signing primitive: assemble attached author-signature CMS from signer certificate plus external RSA signature bytes using the same stable split-signing attributes"},
{"name": "nupkg-sign", "maps_to_native_concept": "NuGet local package signing primitive: create timestampable CMS over signature-content and embed it as root `.signature.p7s`"},
{"name": "nupkg-verify-signature-content", "maps_to_native_concept": "NuGet signature-content package hash verification against an unsigned package"},
{"name": "nupkg-verify-signature", "maps_to_native_concept": "NuGet embedded `.signature.p7s` verification against reconstructed package hash content plus explicit-anchor CMS trust"},
{"name": "nupkg-embed-signature", "maps_to_native_concept": "NuGet split-signing primitive: add or overwrite root `.signature.p7s` as a stored ZIP entry"},
{"name": "vsix-signature-info", "maps_to_native_concept": "VSIX OPC XMLDSig marker inspection under package digital-signature service parts (not SIP; groundwork for portable VSIX XMLDSig signing)"},
{"name": "vsix-signature-reference-xml", "maps_to_native_concept": "Deterministic VSIX XMLDSig Reference/DigestValue XML over package parts"},
{"name": "vsix-signature-xml", "maps_to_native_concept": "Deterministic VSIX XMLDSig XML with local RSA/SHA-2 SignatureValue and embedded X.509 certificate"},
{"name": "vsix-signature-xml-prehash", "maps_to_native_concept": "VSIX remote-signing primitive: compute the SignedInfo digest that an external RSA signer signs"},
{"name": "vsix-signature-xml-from-signature", "maps_to_native_concept": "VSIX remote-signing primitive: assemble XMLDSig from signer certificate plus external RSA signature bytes"},
{"name": "vsix-sign", "maps_to_native_concept": "VSIX local signing primitive: generate deterministic XMLDSig XML and embed the OPC signature parts"},
{"name": "vsix-verify-signature-reference-xml", "maps_to_native_concept": "Verify VSIX package part digests against Reference/DigestValue XML"},
{"name": "vsix-verify-signature-xml", "maps_to_native_concept": "Verify VSIX package part digests and local RSA/SHA-2 SignatureValue against an explicit signer certificate, with optional explicit-anchor signer chain validation"},
{"name": "vsix-verify-signature", "maps_to_native_concept": "Verify embedded VSIX OPC XMLDSig package part digests and local RSA/SHA-2 SignatureValue against the embedded or explicit signer certificate, with optional explicit-anchor signer chain validation"},
{"name": "vsix-embed-signature-xml", "maps_to_native_concept": "VSIX OPC split-signing primitive: add signature origin marker and XML signature part"},
{"name": "appinstaller-info", "maps_to_native_concept": "App Installer descriptor and optional detached `.p7` companion metadata inspection"},
{"name": "appinstaller-verify-companion", "maps_to_native_concept": "App Installer XML descriptor plus detached PKCS#7 companion signature verification with explicit anchors"},
{"name": "appinstaller-sign-companion", "maps_to_native_concept": "App Installer XML descriptor detached PKCS#7 companion generation with local RSA/SHA-2 cert+key and optional RFC3161 timestamp token"},
{"name": "appinstaller-sign-companion-prehash", "maps_to_native_concept": "App Installer remote-signing primitive: compute the CMS authenticated-attributes digest that an external RSA signer signs"},
{"name": "appinstaller-sign-companion-from-signature", "maps_to_native_concept": "App Installer remote-signing primitive: assemble detached companion PKCS#7 from signer certificate plus external RSA signature bytes"},
{"name": "appinstaller-set-publisher", "maps_to_native_concept": "Update App Installer MainPackage/MainBundle Publisher attributes for package-signing workflows"},
{"name": "business-central-app-info", "maps_to_native_concept": "Dynamics Business Central `.app` NAVX header recognition diagnostics"},
{"name": "rfc3161-timestamp-req", "maps_to_native_concept": "RFC 3161 TimeStampReq DER from imprint preimage (TSA application/timestamp-query body)"},
{"name": "rfc3161-timestamp-resp-inspect", "maps_to_native_concept": "Parse TimeStampResp PKIStatus (label + raw int), timeStampToken length + 16-octet TLV hex prefix (CMS sniffing), statusString, failInfo TLV + PKIFailureInfo bit names, structural TSTInfo fields, and optional expected imprint/nonce diagnostics; portable trust performs the supported CryptVerifyTimeStampSignature-style checks when --require-valid-timestamp is used"},
{"name": "rfc3161-timestamp-http-post", "maps_to_native_concept": "HTTPS POST TimeStampReq to TSA (optional build feature timestamp-http; not SignerTimeStampEx3)"}
],
"ci": "`ci-unix` runs unified `psign-tool portable ...` integration tests with `cargo test -p psign --test cli_pe_digest`; `rust-sip-parity.yml` job `portable-cms-rs256-linux` filters PE/CAB/MSI/catalog RS256 tests through the same root test target; Windows workflow also builds workspace and runs the unified portable CLI tests."
}
}