Repository navigation
Preserve PFX certificate chains in portable signing and add portable test PKI commands - #48
Merged
Marc-André Moreau (mamoreau-devolutions) merged 4 commits intoNov 12, 2026
Conversation
…chains - Add `psign_authenticode_trust::test_pki` for generating Windows/RFC 5280-compatible Root CA, Code Signing (`1.3.6.1.5.5.7.3.3`), and TLS Server (`1.3.6.1.5.5.7.3.1` + DNS/IP SANs) certificates, Windows `X500DistinguishedName` DN parsing/formatting (including `S=`, `E=`, and quoted commas), and PKCS#12 `.pfx` bundles with `localKeyId`. - Preserve bundled CA chain certificates when parsing `.pfx` identities in `psign-portable-core` (`--mode portable sign --pfx`), `psign-tool code --pfx`, and ZIP Authenticode signing, and deduplicate CMS `SignedData.certificates` entries. - Expose `psign-tool portable generate-root-ca`, `issue-code-signing-cert`, and `issue-tls-server-cert`, update the CLI parity matrix, and add end-to-end MSIX portable + Windows `AppxSip`/CryptoAPI `CustomRootTrust` tests without mutating host certificate stores. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…res test import Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
… split, and code PE chain certs - Fix X.500 DN attribute mapping so `SN` maps to `surname` (`2.5.4.4`) and `SERIALNUMBER` maps to `2.5.4.5`, matching RFC 4519 and Windows `CertStrToName`. - Quote backslash-containing RDN values in `format_windows_dn`, treat `\` as literal inside `"..."` quotes (`CERT_X500_NAME_STR`), reject invalid unquoted backslash escapes, and preserve RFC 4514 escaped trailing spaces (`\ `) when trimming. - Validate RFC 5280 `PrintableString` (including 2-character `C=`) and `IA5String` (`DC=`, `E=`) character sets in `parse_distinguished_name`, and decode `BMPString` RDNs in `format_windows_dn`. - Extract production PKCS#12 parsing into `psign_authenticode_trust::pkcs12` (while re-exporting in `test_pki` for compatibility). - Thread `--chain-cert` into `psign-tool code` PE/WinMD signing (both local and remote signers) alongside bundled PFX chain certificates. - Add unit and Windows `.NET` + Win32 `PFXImportCertStore` (`powershell.exe`) tests covering DN edge cases, empty-password PBES2 PFX import, and `code --chain-cert` PE signing. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…s-15 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Marc-André Moreau (mamoreau-devolutions)
requested a review
from a team
as a code owner
November 12, 2026 19:08
Marc-André Moreau (mamoreau-devolutions)
merged commit Nov 12, 2026
0e188ff
into
master
36 checks passed
Marc-André Moreau (mamoreau-devolutions)
deleted the
copilot/winget-static-feed-signing
branch
November 12, 2026 19:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
While prototyping and validating end-to-end WinGet static feed (
source2.msix) signing and HTTPS hosting withpinget+psign, we identified a PFX chain-dropping bug in portable signing and added first-class portable test PKI commands so isolated dev/test environments do not need ad-hoc PowerShell/.NET crypto scripts.1. Fix: Preserve PFX certificate chains in portable CMS/PKCS#7 signing
load_pfx_cert_and_keyinpsign-portable-core,psign-tool code --pfx, and ZIP Authenticode signing extracted only the leaf certificate matching the private key and discarded all bundled issuer/CA certificates in the.pfx. As a result,AppxSignature.p7x(and other CMS signatures) omitted intermediate/issuer certificates (certificate_count = 1) unless--ac/--chain-certwas also passed separately.psign_authenticode_trust::test_pki::parse_pfx_identity, which prefers explicit PKCS#12localKeyIdmatching (falling back to public-key matching) and preserves all remaining certificates in the PFX as chain certificates.crates/psign-sip-digest/src/pkcs7.rswhen assemblingSignedData.certificatesso overlapping PFX +--ac/--chain-certinputs never emit duplicate certificates.2. Feature: Portable test PKI generation (
psign-tool portable)Added
crates/psign-authenticode-trust/src/test_pki.rsand three portable CLI subcommands:psign-tool portable generate-root-ca: Mints a self-signed X.509 v3 Root CA (BasicConstraints CA=true,KeyUsage KeyCertSign|CRLSign,SubjectKeyIdentifier) as.cer,.pem,.key, and/or.pfxwithout touching OS certificate stores.psign-tool portable issue-code-signing-cert: Issues an X.509 v3 Code Signing leaf (BasicConstraints CA=false,KeyUsage DigitalSignature,EKU 1.3.6.1.5.5.7.3.3+ optional--eku-oid,SKI+AKI) chained to--ca-pfxor--ca-cert/--ca-key, bundling the full chain ([leaf, ca, ...]) into--pfx-out.psign-tool portable issue-tls-server-cert: Issues an X.509 v3 TLS Server leaf (BasicConstraints CA=false,KeyUsage DigitalSignature|KeyEncipherment,EKU 1.3.6.1.5.5.7.3.1,SubjectAltNamefor repeatable--dnsand--ip) chained to the same CA, bundling the full chain into--pfx-outand--pem-out.X500DistinguishedNameand RFC 4514 Subject DNs (S=,E=, quoted commas, and ASN.1RDNSequencereversal so WindowsX509Certificate2.Subjectformats in exact MSIXIdentity/@Publisherorder), backdatesnotBeforeby 24h for VM clock skew tolerance, clamps leafnotAfterto the issuing CA, and attaches PKCS#12localKeyIdattributes for Win32PFXImportCertStorecompatibility.Testing
crates/psign-authenticode-trust/src/test_pki.rsand end-to-end integration tests intests/test_pki_msix.rs:@response.rspportable MSIX signing (--mode portable sign --pfx),portable verify-msix,portable inspect-pkcs7(certificate_count == 2), andportable trust-verify-msix --trusted-ca(including wrong-CA rejection).Root -> SubCA -> LeafPFX signing without--ac, proving intermediate CA chain embedding and verification againstroot.ceralone.AppxSip/WinVerifyTrust(0x800B0109untrusted-root-only check) and in-memory Windows CryptoAPIX509Chain(CustomRootTrust) validation for both Code Signing and TLS Server PFXs without modifyingLocalMachine\Root.wingetv1.29.380 +AppxSip/WinVerifyTrust+ HTTPS TLS static feed) trusting a single generatedroot-ca.cer.docs/psign-cli-matrix.json,docs/psign-cli-matrix.md,docs/linux-signing-pipelines.md, andREADME.md.