signtool, add that seal to your .exe, .dll, and .msi files, using a signing key that stays locked inside Infisical. It is a small plug-in for Windows’ built-in cryptography system, called Cryptography API: Next Generation (CNG). “KSP” is short for Key Storage Provider, which is just Windows’ name for a plug-in that supplies signing keys.
Here is what happens when you sign a file: signtool hands the plug-in a short fingerprint of the file, the plug-in sends that fingerprint to Infisical, Infisical signs it and sends the signature back, and signtool attaches the signature to your file. Your private signing key never leaves Infisical.
This is the Windows version of the PKCS#11 module. Both use the same Infisical Signers behind the scenes. Use the PKCS#11 module for cross-platform tools like jarsigner, osslsigncode, and cosign. Use the Windows KSP when you sign with signtool.
Before you start
You authenticate as a member of the Signer, using either a Machine Identity or your own Infisical access token. To use a Machine Identity, set it up once in Infisical:- Create a Machine Identity and enable Universal Auth on it, then copy its Client ID and Client Secret. The provider uses these to authenticate, and you will set them in Configuration below.
- Add the identity to the Signer with the Administrator or Operator role, from the Signer’s Members tab. Auditors cannot sign.
- If the Signer has an approval policy, get active signing access before signing.
To sign as yourself instead, use your own access token (see Configuration). You still need to be a member of the Signer with the Administrator or Operator role.
The Signer itself is created by a Product Admin. If you do not have one yet, create it first.
Requirements
- A 64-bit Windows computer (Windows 10/11 or Windows Server 2016 and later) where you are an Administrator. Setting up the plug-in changes a system-wide Windows setting, which needs admin rights.
signtool, Microsoft’s signing tool, which comes with the Windows SDK. Most setups use the 64-bitsigntool; there is also a 32-bit build, with a matching plug-in. The two plug-in files areinfisical-ksp.dll(64-bit) andinfisical-ksp-x86.dll(32-bit). Use the one that matches thesigntoolyou run.
Installation
Download the plug-in file from the releases page into the folder you are working in. Most people use the 64-bitsigntool, so get infisical-ksp.dll:
Signing with the 32-bit
signtool? Download infisical-ksp-x86.dll instead, and see the 32-bit note under Register the provider.Register the provider
Registering means telling Windows the plug-in exists, sosigntool can find it. This copies the file into a Windows system folder and adds a few entries to the Windows registry (the database of system settings). Open PowerShell as Administrator, go to the folder that holds infisical-ksp.dll, and run:
Using the 32-bit
signtool? It loads plug-ins from SysWOW64 instead of System32, so also place the 32-bit file there under the same name. The registry entries above are shared by both, so you do not repeat them: Copy-Item .\infisical-ksp-x86.dll "$env:windir\SysWOW64\infisical-ksp.dll" -Force.Configuration
The plug-in needs your Infisical address and the login it should use. The simplest setup is environment variables only, with no config file. This is the machine identity your admin added to the Signer:%ProgramData%\Infisical\config.json (or point INFISICAL_CONFIG at a different location) with at least your Infisical address, and keep credentials in environment variables:
You can also put these credentials inside the config file (
auth.client_id and auth.client_secret), but environment variables are safer, because the secret will not get saved into your code or log files. Whatever runs signtool must have these variables set: for a build pipeline that is the build job, and for hands-on use it is the same PowerShell window.Sign with an access token instead
Instead of a machine identity, you can hand the plug-in an Infisical access token directly, either your own or a machine identity’s. SetINFISICAL_TOKEN and the plug-in uses it as-is:
Configuration reference
Environment variable reference
If a value is set both as an environment variable and in the config file, the environment variable wins.
Sign with signtool
First, put the Signer’s certificate on the computer. A certificate is the public half of your signing identity, so it is safe to share. In Infisical, open the Signer and use Export certificate to download it, or paste it in:/kc picks the Signer by name, and /f points to the certificate file you just saved:
Add a timestamp so the signature stays valid even after the certificate expires (recommended for anything you ship). Put
/tr <timestamp-url> /td SHA256 before the file name, using any RFC 3161 timestamp service.Verify
Check that the file is signed:If your certificate comes from your own private CA (instead of one Windows already trusts),
signtool verify shows the warning A certificate chain could not be built to a trusted root authority (0x800B010A). The signature is still valid; Windows just does not recognize who issued the certificate. To clear the warning, add your CA to the computer’s Trusted Root store.Automatic signing access requests
When a Signer has an approval policy,signtool fails until someone has active signing access. The provider can open that request for you on the first denied signing attempt. Add an approval block to %ProgramData%\Infisical\config.json:
signing_durationasks for an access window of this length (30m,8h,2d).signing_countasks for access good for this many signing operations.
The first signing attempt still fails, because an approver has to act on the request. Once approved, run the same command again and it succeeds.The approval covers that exact command and artifact, so a different artifact, a changed argument, or reordered flags needs a new request. A request’s parameters are fixed once it is open, so when they are wrong the request is rejected and reopened rather than edited. To have one approval cover a batch, leave the parameters that vary out of the request from the start.
Leaving parameters out of a request
Every parameter on a request has to match at signing time, so a request that names the artifact hash covers exactly one artifact. To have one approval cover a series of builds, name the parameters that vary inapproval.exclude_scope_fields and the provider leaves them off every request it opens:
data_hash is the usual one. A timestamped signature changes the digest between runs even for the same file, so pinning it means a fresh approval for every build. The other names are command, signing_application, signing_application_hash, hostname, os_username and ip_address.
Leave out only what genuinely varies, and be aware that dropping a parameter widens the approval further than the machine you configured it on. An approval belongs to the identity that asked for it, not to a host, so once hostname is excluded the same approval covers that identity signing from anywhere its credentials are installed.
An excluded parameter is still recorded on the signing operation, so the command, machine, account and artifact hash behind every signature stay available to auditors even when they no longer constrain the approval.
Scoping by address
The address is the one parameter the provider cannot observe, because what counts is the address Infisical receives the sign call from, after any NAT or proxy in between. Infisical fills it in from the request itself, the same value it records in the audit log, so requests are scoped by address without any configuration. Two settings change that:ip_address pins a different address than the request came from, which is how you tie an approval to a build agent’s egress address from elsewhere. Excluding ip_address leaves signing unrestricted by address, which is what a fleet behind a rotating NAT pool needs, since a pinned address would stop matching between runs. Setting both leaves the address unscoped, because excluding wins.
Infisical always compares against the address it sees, never one a caller reports, so neither setting can widen access beyond what the approval already allows.
Example CI workflow
- The pipeline runs
signtool sign ... /csp "Infisical Key Storage Provider" /kc <signer>. - No active access exists, so Infisical returns 403.
- The provider sees the
approvalblock and opens a scoped signing request. - This run fails.
- A reviewer approves the request in Infisical.
- The pipeline is rerun and signing succeeds under the freshly issued access.
Troubleshooting
The plug-in writes a log to%ProgramData%\Infisical\ksp.log. signtool itself only shows a short error code, so this log is the best place to see what actually went wrong and how to fix it. For more detail, set log_level to debug.
signtool fails immediately and the log you configured is empty
signtool fails immediately and the log you configured is empty
The config file could not be read, so the log path named inside it is unknown too. The reason is written to the default log at
%ProgramData%\Infisical\ksp.log instead, and it names the setting at fault: an exclude_scope_fields entry that is not a signing parameter, an ip_address that is not an address, or invalid JSON. A UTF-8 byte order mark counts as invalid JSON, so write the file with [IO.File]::WriteAllText rather than Set-Content -Encoding utf8.signtool says 'Invalid provider specified' right after setup
signtool says 'Invalid provider specified' right after setup
Windows has not picked up the new plug-in yet. Restart the computer once and try again.
Access denied (HTTP 403 in the log)
Access denied (HTTP 403 in the log)
Your identity is not allowed to sign yet. Either it needs approved access to sign, or it must be a member of the Signer with the Administrator or Operator role (Auditors cannot sign). Fix the access (see Approvals), then run the same command again.
HTTP 401 in the log
HTTP 401 in the log
The login is missing or wrong. Set
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID and INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET, and check that the identity is a member of the Signer.Cannot reach Infisical / connection refused
Cannot reach Infisical / connection refused
A network or TLS problem. Check that
server_url is correct and that the computer can reach it. For self-hosted Infisical with a private CA, set tls.ca_cert_path to the CA file.'signtool' is not recognized
'signtool' is not recognized
signtool is not installed or is not on your PATH. Install the Windows SDK, or open a Developer Command Prompt, so Windows can find signtool.Uninstall
To remove the provider, run this in an Administrator PowerShell, then restart the computer (Windows keeps the provider in its cached list until a reboot):System32. Your %ProgramData%\Infisical config and log files are left in place; delete that folder too if you no longer need them.
What’s next
Cross-platform signing
The PKCS#11 module for jarsigner, osslsigncode, cosign, and more.
Manage Signers
Create and configure Signers.
Approvals
Require review before signing.