Windows resolves Authenticode chains against machine/user certificate stores plus Microsoft Authenticode roots. On Linux/macOS, portable trust verification can use explicit roots, or it can automatically download and cache Microsoft’s authrootstl.cab when no explicit roots are supplied.
By default, psign-tool portable trust-verify-* and bare psign-tool --mode portable verify download authrootstl.cab from Microsoft’s Windows Update distribution URL when the cache is missing or stale. The cache lives at ~/.psign/authroot/authrootstl.cab with metadata in authrootstl.cab.json. The default refresh window is 7 days.
Set PSIGN_NO_AUTO_TRUST=1 (also accepts true or yes) to disable automatic AuthRoot use. Set PSIGN_AUTHROOT_MAX_AGE_DAYS=<days> to change the staleness window. Advanced/offline environments can set PSIGN_AUTHROOT_CACHE_DIR or PSIGN_AUTHROOT_URL for an alternate cache location or mirror. Explicit --authroot-cab, --anchor-dir, or repeatable --trusted-ca inputs take precedence and suppress automatic AuthRoot resolution.
- On a Windows machine with updates, sync roots you trust, for example:
certutil -generateSSTFromWU roots.sstthen export, or- Copy known
.crt/.cerfiles into a folder (repo-local or CI cache).
- Pass
--anchor-dir /path/to/certstotrust-verify-pe, or pass individual files with repeatable--trusted-ca /path/to/root.cer.
Non-recursive: only*.crt,*.cer,*.pemin that directory are loaded. - Thumbprints are SHA-1 over full certificate DER (same convention as many Windows tools), not TBSCertificate-only.
Keep separate what you trust as an anchor vs what happens to be embedded in the PE (intermediates are usually present in the signature).
psign-authenticode-trust reads a Microsoft authrootstl.cab, walks *.stl entries, and:
- Harvests X.509 certificates from PKCS#7 blobs (
Pkcs7::from_deron each member). - Parses PKCS#7
ContentInfo→SignedDatawhen present and extracts CTLeContentTrustedSubject SHA-1SubjectIdentifieroctets into the anchor thumbprint set (alongside cert-derived thumbs).
Pass --authroot-cab /path/to/authrootstl.cab on any trust-verify-* subcommand to use a pinned or mirrored CAB instead of the automatic cache.
- CI / reproducibility: pin a SHA-256 of the CAB; pass
--authroot-caband--expect-authroot-cab-sha256 <64-hex>so ingest aborts on mismatch. - Future hardening: verify the outer Authenticode signature / CTL semantics on the STL (see technical plan).
Default portable trust using the automatic AuthRoot cache:
psign-tool portable trust-verify-pe ./signed.exeBare portable verify also routes to trust verification for supported formats when auto trust is enabled:
psign-tool --mode portable verify ./signed.exepsign-tool portable trust-verify-pe \
--anchor-dir ./my-trusted-roots \
./signed.exeSingle-file non-admin trust anchor:
psign-tool portable trust-verify-pe \
--trusted-ca ./test-root.cer \
./signed.exeThe unified CLI uses the same trust path without writing to the Windows or Linux OS trust store. With --mode portable verify, supported formats route to the corresponding portable trust-verify-* command by default when automatic AuthRoot is enabled. Explicit trust inputs such as --trusted-ca, --anchor-dir, --authroot-cab, AIA/OCSP/CRL flags, and timestamp policy flags still route to the same trust commands:
psign-tool --mode portable verify \
--trusted-ca ./test-root.cer \
./signed.exeWith Microsoft root harvest from CAB:
psign-tool --mode portable verify \
--authroot-cab ./authrootstl.cab \
--anchor-dir ./extra-enterprise-roots \
--verbose-chain \
./signed.exeStrict code signing EKU is default; for diagnostics only:
psign-tool portable trust-verify-pe --allow-loose-signing-cert ...Expired corpora / reproducible CI: pin verification instant:
psign-tool portable trust-verify-pe --anchor-dir ./roots --as-of 2023-07-01 ./fixture.exeFor local online issuer tests, enable bounded in-memory AIA fetching. Only HTTP AIA URLs are currently supported, intended for loopback psign-server tests:
psign-tool portable trust-verify-pe \
--trusted-ca ./test-root.cer \
--online-aia \
./signed-with-missing-intermediate.exeFor local CRL revocation tests, use strict revocation with an explicit loopback CRL URL. The CRL is fetched into memory, checked against the issuing CA signature, and evaluated for revoked signer/intermediate serials without touching OS stores:
psign-tool portable trust-verify-detached \
./content.bin ./signature.p7 \
--trusted-ca ./test-root.cer \
--revocation-mode require \
--crl-url-override http://127.0.0.1:5000/crl.derOCSP loopback tests use the same revocation policy. The portable verifier sends a bounded OCSP request, verifies the BasicOCSPResponse signature with the issuing CA, and applies good/revoked/unknown status:
psign-tool portable trust-verify-detached \
./content.bin ./signature.p7 \
--trusted-ca ./test-root.cer \
--revocation-mode require \
--online-ocsp \
--ocsp-url-override http://127.0.0.1:5000/ocsp- authenticode-trust-stack.md — crate split and verification order.
- plan-linux-authenticode-trust-verify.md — full design / risks / test matrix.