MCPcopy Index your code
hub / github.com/Devolutions/psign

github.com/Devolutions/psign @v0.6.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.6.1 ↗ · + Follow
2,752 symbols 8,799 edges 148 files 229 documented · 8%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

psign

psign is a Rust port of the Windows SDK signtool.exe behavior (sign, verify, timestamp, remove, and related Authenticode flows), validated with differential parity tests against the native tool where CI fixtures allow.

Canonical repository: https://github.com/Devolutions/psign.

CLI surface

  • verify, remove, catdb: Windows-compatible signtool.exe flows backed by WinTrust and CryptSIP where native APIs are required.
  • sign: Rust mssign32 core (SignerSignEx3) with PFX/system-store cert selection, RFC3161 sign-time timestamping, first-class custom ZIP Authenticode support (docs/zip-authenticode-signing.md), and decoupled-digest bridge flow (--dlib or --trusted-signing-dlib-root + --dmdf) for MSIX parity and Azure Artifact Signing / Trusted Signing.
  • inspect-signature: JSON dump of PKCS#7 signers, timestamp OIDs, and nested signatures (1.3.6.1.4.1.311.2.4.1) — same parser as psign-tool portable inspect-authenticode (docs/psa-interoperability.md).
  • timestamp: Rust mssign32 core (SignerTimeStampEx3/SignerTimeStampEx2) plus AppX restrictions.
  • rdp: Rust port of rdpsign.exe for .rdp files (SignScope / Signature records, detached PKCS#7 over the secure-settings blob).
  • cert-store: Portable file-backed certificate store under ~/.psign/cert-store by default, with Windows-style store/thumbprint selection.
  • code: dotnet/sign-style orchestration entry point. It supports --dry-run / --plan-json planning over inputs, file lists, globs, and nested ZIP/OPC containers, plus guarded local cert/key, PFX, portable cert-store SHA-1, Azure Key Vault, or Artifact Signing execution for PE/WinMD, NuGet/SNuGet, VSIX, generic ZIP nested package entries, MSIX/AppX unsigned-package prepare including nested packages inside upload/bundle containers, encrypted MSIX/AppX OS-only diagnostics, ClickOnce .manifest / .application / .vsto XMLDSig signing, PE-like ClickOnce .deploy payloads, App Installer publisher updates + top-level or nested companion signatures, --continue-on-error, --skip-signed, --overwrite, and inside-out VSIX/ZIP -> NuGet/VSIX -> PE/ClickOnce-manifest signing.
  • portable ...: Cross-platform digest, verification, trust, signing, package, RFC3161, and remote-hash helpers that avoid Win32 APIs, including PE/WinMD signing through Azure Artifact Signing REST without Microsoft client DLLs.

MSIX parity notes

  • MSIX/AppX signing requires --timestamp-url in the current parity profile.
  • Sign-time digest controls now distinguish file digest (--digest, native /fd) and RFC3161 timestamp digest (--timestamp-digest, native /td).
  • Decoupled digest inputs (--dlib + --dmdf) are executed via a native-signature bridge path and parity-gated in CI scenarios.

Build

cargo build

At the repo root, cargo build targets default-members, including the unified psign-tool executable from src\main.rs plus the portable digest / trust / package / REST crates. On Windows, cargo build -p psign --bin psign-tool remains the explicit way to build only that executable. Default Cargo features include azure-kv-sign (Key Vault digest callback), artifact-signing-rest (artifact-signing-submit LRO against *.codesigning.azure.net), timestamp-http (portable RFC3161 HTTP POST), and timestamp-server (local RFC3161 test server); use --no-default-features for a minimal build.

Dotnet tool package from NuGet.org (.NET 10+)

psign-tool is published as the RID-specific Devolutions.Psign.Tool dotnet tool package:

dotnet tool install -g Devolutions.Psign.Tool
psign-tool --help

Update an existing global install:

dotnet tool update -g Devolutions.Psign.Tool

One-shot execution from NuGet.org:

dotnet tool exec Devolutions.Psign.Tool -- --help
dnx Devolutions.Psign.Tool --help

For repository-local tool manifests, omit -g:

dotnet new tool-manifest
dotnet tool install Devolutions.Psign.Tool
dotnet tool run psign-tool -- --help

Create local dotnet tool packages from prebuilt release artifacts:

pwsh ./nuget/pack-psign-dotnet-tool.ps1 -Version 0.6.1 -ArtifactsRoot ./dist -OutputDir ./dist/nuget

The package is built from native psign-tool artifacts for win-x64, win-arm64, linux-x64, linux-arm64, osx-x64, and osx-arm64, plus an any fallback package for unsupported runtimes.

Linux / portable tooling

The canonical psign-tool CLI (package psign) supports an optional backend selector: --mode auto|windows|portable. When omitted, auto is used; PSIGN_TOOL_MODE can set the same default for parity automation. Windows mode uses Win32 APIs and registered SIP DLLs. Portable mode and the psign-tool portable ... namespace use the cross-platform Rust implementations from psign-sip-digest, psign-authenticode-trust, psign-opc-sign, psign-codesigning-rest, and psign-azure-kv-rest without WinVerifyTrust or the OS trust store.

Feature gaps vs native signtool, AzureSignTool, and Azure Artifact Signing: docs/gap-analysis-signing-platforms.md. Linux workflows (verify, REST hash sign, hybrid embed): docs/linux-signing-pipelines.md. For Key Vault RS256 over CMS authenticated attributes (not the PE image hash), use psign-tool portable pe-signer-rs256-prehash — see docs/migration-azuresigntool.md.

From the repo root (see docs/roadmap-authenticode-linux.md):

cargo build -p psign --bin psign-tool --locked
# Portable RDP signing:
# psign-tool portable rdp --cert cert.der --key key.pk8 file.rdp
# Portable PE signing with a local RSA key:
# psign-tool portable sign-pe --cert cert.der --key key.pk8 --output signed.exe unsigned.exe
# Existing PE signatures are replaced by default; add --append-signature to match signtool /as.
# Portable trust verification downloads/caches Microsoft AuthRoot automatically when no anchors are supplied:
# psign-tool portable trust-verify-pe signed.exe
# Explicit anchors still override auto trust:
# psign-tool portable trust-verify-pe signed.exe --anchor-dir anchors
# Portable custom ZIP Authenticode verification:
# psign-tool portable trust-verify-zip archive.zip --anchor-dir anchors
# Portable unsigned CAB signing with a local RSA key:
# psign-tool portable sign-cab --cert cert.der --key key.pk8 --output signed.cab unsigned.cab
# Portable MSI/MSP signing with a local RSA key:
# psign-tool portable sign-msi --cert cert.der --key key.pk8 --output signed.msi unsigned.msi
# Portable generic catalog signing with a local RSA key:
# psign-tool portable sign-catalog --cert cert.der --key key.pk8 --output files.cat file1.exe file2.txt
# Portable RFC3161 timestamp token embedding after signing:
# psign-tool portable timestamp-pe-rfc3161 signed.exe --response timestamp.tsr --output timestamped.exe
# Portable package inspection helpers:
# psign-tool portable nupkg-signature-info package.nupkg
# psign-tool portable nupkg-digest package.nupkg --algorithm sha256
# psign-tool portable nupkg-signature-content package.nupkg --output signature-content.txt
# psign-tool portable nupkg-signature-pkcs7 package.nupkg --cert signer.der --key signer.pkcs8 --timestamp-url http://tsa --timestamp-digest sha256 --output signature.p7s
# psign-tool portable nupkg-signature-pkcs7-prehash package.nupkg --encoding raw --output prehash.bin
# psign-tool portable nupkg-signature-pkcs7-from-signature package.nupkg --cert signer.der --signature remote.sig --output signature.p7s
# psign-tool portable nupkg-verify-signature-content package.nupkg --content signature-content.txt
# psign-tool portable nupkg-embed-signature package.nupkg --signature signature.p7s --output signed.nupkg
# psign-tool portable nupkg-sign package.nupkg --cert signer.der --key signer.pkcs8 --timestamp-url http://tsa --timestamp-digest sha256 --output signed.nupkg
# psign-tool portable nupkg-verify-signature signed.nupkg --trusted-ca signer.der --allow-loose-signing-cert
# psign-tool portable vsix-signature-info extension.vsix
# psign-tool portable vsix-signature-reference-xml extension.vsix --output signature-reference.xml
# psign-tool portable vsix-verify-signature-reference-xml extension.vsix --signature-xml signature-reference.xml
# psign-tool portable vsix-signature-xml extension.vsix --cert signer.der --key signer.pkcs8 --output signature.xml
# psign-tool portable vsix-signature-xml-prehash extension.vsix --encoding raw --output prehash.bin
# psign-tool portable vsix-signature-xml-from-signature extension.vsix --cert signer.der --signature remote.sig --output signature.xml
# psign-tool portable vsix-verify-signature-xml extension.vsix --signature-xml signature.xml --cert signer.der --trusted-ca root.der
# psign-tool portable vsix-embed-signature-xml extension.vsix --signature-xml signature.xml --output signed.vsix
# psign-tool portable vsix-sign extension.vsix --cert signer.der --key signer.pkcs8 --output signed.vsix
# psign-tool portable vsix-verify-signature signed.vsix --trusted-ca root.der
# psign-tool portable appinstaller-info app.appinstaller --signature app.appinstaller.p7
# psign-tool portable appinstaller-sign-companion app.appinstaller --cert signer.der --key signer.pkcs8 --timestamp-url http://tsa --timestamp-digest sha256 --output app.appinstaller.p7
# psign-tool portable appinstaller-sign-companion-prehash app.appinstaller --encoding raw --output prehash.bin
# psign-tool portable appinstaller-sign-companion-from-signature app.appinstaller --cert signer.der --signature remote.sig --output app.appinstaller.p7
# psign-tool portable appinstaller-verify-companion app.appinstaller --signature app.appinstaller.p7 --anchor-dir anchors
# psign-tool portable appinstaller-set-publisher app.appinstaller --publisher "CN=Example" --output updated.appinstaller
# psign-tool portable business-central-app-info package.app
# psign-tool portable msix-manifest-info package.msix
# psign-tool portable msix-set-publisher package.msix --publisher "CN=Example" --output updated.msix
# psign-tool portable clickonce-deploy-info app.exe.deploy
# psign-tool portable clickonce-copy-deploy-payload app.exe.deploy --output app.exe
# psign-tool portable clickonce-update-manifest-hashes app.exe.manifest --base-directory . --output updated.manifest
# psign-tool portable clickonce-manifest-hashes updated.manifest --base-directory .
# psign-tool portable clickonce-sign-manifest updated.manifest --cert signer.der --key signer.pkcs8 --output signed.manifest
# psign-tool portable clickonce-sign-manifest-prehash updated.manifest --encoding raw --output prehash.bin
# psign-tool portable clickonce-sign-manifest-from-signature updated.manifest --cert signer.der --signature remote.sig --output signed.manifest
# psign-tool portable clickonce-verify-manifest-signature signed.manifest --trusted-ca signer.der
# dotnet/sign-style dry-run planning for nested package orchestration:
# psign-tool code --dry-run --plan-json --base-directory . --file-list files.txt
# Initial guarded code execution for PE/NuGet/VSIX/ZIP/MSIX/ClickOnce/App Installer inputs:
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --output signed.exe app.exe
# psign-tool code --base-directory . --pfx signer.pfx --password "pfx-password" --output signed.nupkg package.nupkg
# psign-tool code --base-directory . --cert-store-dir ~/.psign/cert-store --sha1 <thumbprint> --output signed.nupkg package.nupkg
# psign-tool code --base-directory . --azure-key-vault-url https://vault.vault.azure.net --azure-key-vault-certificate cert --azure-key-vault-accesstoken "$TOKEN" --output signed.nupkg package.nupkg
# psign-tool code --base-directory . --artifact-signing-endpoint https://wus2.codesigning.azure.net --artifact-signing-account-name acct --artifact-signing-profile-name profile --artifact-signing-access-token "$TOKEN" --output signed.nupkg package.nupkg
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --timestamp-url http://tsa --timestamp-digest sha256 --output signed.nupkg package.nupkg
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --output signed.vsix extension.vsix
# psign-tool code --base-directory . --overwrite --cert signer.der --key signer.pkcs8 --output resigned.nupkg signed-package.nupkg
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --output signed.zip package-bundle.zip
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --publisher-name "CN=Publisher" --output prepared.msix app.msix
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --output signed.manifest app.exe.manifest
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --output app.signed.exe.deploy app.exe.deploy
# psign-tool code --base-directory . --cert signer.der --key signer.pkcs8 --publisher-name "CN=Publisher" --output updated.appinstaller.p7 app.appinstaller
# Optional portable REST helpers (Linux/macOS):
# cargo build -p psign --bin psign-tool --locked --features artifact-signing-rest
# cargo build -p psign --bin psign-tool --locked --features azure-kv-sign
cargo test -p psign-sip-digest -p psign-authenticode-trust -p psign-opc-sign -p psign-codesigning-rest -p psign-azure-kv-rest -p psign-digest-cli -p psign --locked
cargo check -p psign-sip-digest -p psign-digest-cli -p psign-authenticode-trust -p psign-opc-sign -p psign-codesigning-rest -p psign-azure-kv-rest --locked

Unix CI (ci-unix) runs cargo fmt, strict clippy -D warnings on por

Extension points exported contracts — how you extend this code

SigningProvider (Interface)
(no doc)
src/signing_provider.rs

Core symbols most depended-on inside this repo

path
called by 448
tests/corpus_sign_verify.rs
portable_cmd
called by 289
tests/cli_pe_digest.rs
psign
called by 97
tests/code_command.rs
ok
called by 87
src/lib.rs
env_path
called by 72
tests/parity_signtool.rs
reject_string_option
called by 68
src/portable_sign.rs
parse_pkcs7_signed_data_der
called by 67
crates/psign-sip-digest/src/pkcs7.rs
update
called by 66
crates/psign-sip-digest/src/msix_digest.rs

Shape

Function 2,218
Method 229
Class 228
Enum 76
Interface 1

Languages

Rust94%
C#6%

Modules by API surface

tests/cli_pe_digest.rs256 symbols
crates/psign-portable-core/src/lib.rs165 symbols
src/code.rs151 symbols
crates/psign-digest-cli/src/main.rs145 symbols
crates/psign-sip-digest/src/pkcs7.rs116 symbols
crates/psign-sip-digest/src/msix_digest.rs104 symbols
src/bin/psign-server.rs75 symbols
crates/psign-sip-digest/src/timestamp.rs75 symbols
tests/code_command.rs73 symbols
tests/cli_verify_filters.rs71 symbols
crates/psign-sip-digest/src/catalog_digest.rs54 symbols
src/portable_sign.rs52 symbols

For agents

$ claude mcp add psign \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact