- Deep signing
- File elements
- <directory> element
- Signing methods
- Using wildcards
- File and directory sets
- File attribute restrictions
The artifact configuration describes the structure of the artifacts you want to sign. You can upload a sample artifact to be analyzed automatically or select a predefined configurations to get started quickly. Alternatively, you can also specify the structure of your artifact and provide signing directives using XML.
In case you have more complex, nested artifacts, you might want to not only sign the container itself (for instance, an MSI installer package), but also all files that are shipped within the container (e.g. .exe and .dll files within the MSI installer). Therefore, every container format can contain multiple other file or directory elements to be signed. Each of those will be extracted, signed, and then put back into the container file during the signing process. In order for SignPath to find the right file, all inner elements need a path attribute.
Every XML description is wrapped in an
<artifact-configuration> root element which contains exactly one file element. This file element specifies the type of artifact and signing method. Optionally, you can restrict the name of the file using the
Container-format elements may contain other file elements for deep signing.
File element types and signing directives
|Element||Container format||Signing directive||Extensions||Description|
||.acm, .ax, .cpl, .dll, .drv, .efi, .exe, .mui, .ocx, .scr, .sys, .tsp||Portable Executable (PE) files: EXE, DLL, and other executable files|
||.ps1, .psm1, psd1, .psdc1, .ps1xml||PowerShell scripts and modules|
||.msi, .msm, .msp||Microsoft installer files|
||.cab||Windows cabinet files|
||.appx, .appxbundle||App packages for Microsoft Store/Universal Windows Platform
Deep signing is not yet supported.
||.vsix, .xps, ...||Open Packaging Conventions (OPC) files including Visual Studio Extensions (VSIX)|
||Directories within container files|
File element examples
Signing an MSI package
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <msi-file> <authenticode-sign/> </msi-file> </artifact-configuration>
See Examples for more complex artifact configurations.
Signing multiple artifacts
If you want to sign multiple independent artifacts in one step, you need to package them into a ZIP archive before processing.
You can combine signing multiple artifacts with deep signing.
All supported container formats have an internal directory structure. You can see this structure if you extract a container to a local disk.
You can either specify these directories in the
path attribute of each file element, or nest these file elements within
<directory> elements are also used for ClickOnce signing.
|The following fragment||is equivalent to|
Specify signing directives in file and directory elements. See file elements for available methods per element type.
For file and directory sets, specify the signing directive in the
Microsoft Authenticode is the primary signing method on the Windows platform. Authenticode is a versatile and extensible mechanism that works for many different file types:
- Portable Executable (PE) files: EXE, DLL, and some other executable file formats including device drivers
- Installation formats: AppX, MSI, and CAB
- PowerShell scripts and modules
<authenticode-sign> is equivalent to using Microsoft's
ClickOnce signing, also called 'manifest signing', is a method used for ClickOnce applications and Microsoft Office Add-ins.
ClickOnce signing applies to directories, not to individual files. Therefore, you need to specify a
<directory> element for this method. If you want to sign files in the root directory of a container, specify
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <zip-file> <directory path="."> <clickonce-sign/> </directory> </zip-file> </artifact-configuration>
<clickonce-sign> is equivalent to using Microsoft's
NuGet package signing is currently being introduced to the NuGet Gallery.
Although the NuGet Package format is based on OPC (see next section), it uses its own specific signing format.
<nuget-sign> is equivalent to using Microsoft's
The Open Packaging Conventions (OPC) specification has its own signature format. Since OPC is the foundation for several file formats, it is not strictly a code signing format. However, code signing is used for Visual Studio Extensions (VSIX).
Other OPC formats include:
- Open XML Paper Specification (OpenXPS)
- Office Open XML files (Microsoft Office)
Note that while OPC signing can be applied to all OPC formats, specific applications and formats do not necessarily use or verify signatures, or even require a different signing format (case in point: NuGet packages).
<opc-sign> for Visual Studio Extensions is equivalent to using Microsoft's
Every path attribute can contain the following wildcard patterns:
||Matches any number of any character (including none, excluding the directory separator)|
||Matches any single character|
||Matches one character given in the bracket|
||Matches one character from the range given in the bracket|
||Matches one character that is not given in the bracket|
||Matches one character that is not from the range given in the bracket|
||Matches any number of path/directory segments. When used, they must be the only contents of the dedicated segment.|
If wildcards are used, optional
min-matches parameters can be specified to limit the number of files which are allowed to match the wildcard expression. Both default to
1. (You can also use
min-matches="0" for optional elements even without wildcards.)
File and directory sets
If multiple files or directories should be handled in the same way, you can enumerate them using one of the following file or directory set elements:
Each set element contains:
<include>element for each file (or pattern) to be processed
<for-each>element that will be applied to all included elements of the set
<for-each> element can include the same child elements as the corresponding simple file or directory element:
Sets are especially useful if your artifacts contain repeating nested structures.
File set example
|The following fragment||is equivalent to|
File attribute restrictions
For Microsoft Portable Executable (PE) files, the existence of their Product Name / Product Version header attributes can be enforced by setting the
productVersion attributes on the
<pe-file-set> and including
<include> elements. The value of the
<include> overrides any value set on the
File attribute restriction example
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <msi-file> <!-- requires all pe-files to have the respective attributes set --> <pe-file-set productName="YourProductName" productVersion="220.127.116.11"> <include path="main.exe" /> <!-- overrides the value of the parent pe-file-set --> <include path="resources*.resource.dll" max-occurs="unbounded" productVersion="18.104.22.168" /> <for-each> <authenticode-sign /> </for-each> </pe-file-set> <authenticode-sign /> <!-- finally sign the MSI file --> </msi-file> </artifact-configuration>
Examples are shortened
For the sake of clarity, all examples omit the XML prolog. A complete artifact configuration looks like this:
<?xml version="1.0" encoding="utf-8" ?> <artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <!-- ... --> </artifact-configuration>
Predefined configuration for single Portable Executable file
This configuration works for all PE files.
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <pe-file> <authenticode-sign/> </pe-file> </artifact-configuration>
Signing multiple artifacts in a ZIP container
You can sign multiple unrelated artifacts by packing them into a single ZIP file.
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <zip-file> <pe-file path="app.exe"> <authenticode-sign/> </pe-file> <powershell-file path="setup.ps1"> <authenticode-sign/> </powershell-file> </zip-file> </artifact-configuration>
Deep-signing an MSI installer
This will sign the PE files
main.exe, then re-package their MSI container and sign it too. It also restricts the name of the MSI container file.
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <msi-file path="MyProduct.v*.msi"> <directory path="libs"> <pe-file path="common.dll"> <authenticode-sign/> </pe-file> </directory> <pe-file path="main.exe"> <authenticode-sign/> </pe-file> <authenticode-sign/> </msi-file> </artifact-configuration>
Signing similar directories within an MSI file
This artifact configuration describes an MSI installer package containing several components. These components have a similar structure and are therefore defined as a
<directory-set>. Each component contains a
main.exe and zero or more resource DLLs.
<artifact-configuration xmlns="http://signpath.io/artifact-configuration/v1"> <msi-file> <directory-set> <include path="component1" /> <include path="component2" /> <include path="component3" /> <for-each> <pe-file-set> <include path="main.exe" /> <include path="resources*.resource.dll" min-matches="0" max-matches="unbounded" /> <for-each> <authenticode-sign/> </for-each> </pe-file-set> </for-each> </directory-set> <authenticode-sign/> </msi-file> </artifact-configuration>
Example of a directory structure that would match this configuration:
MyApp.msi component1/ main.exe resources/ de.resource.dll en.resource.dll fr.resource.dll component2/ main.exe component3/ main.exe resources/ en.resource.dll