How to find WiX RemotePayload's CertificatePublicKey hash
-
02-07-2021 - |
Question
I'm trying to resolve WiX RemotePayload hashes, but I'm not sure how the CertificatePublicKey
attribute is found.
Take, for example, the .NET 4.0 Package definition from WiX 3.6 sources:
<Fragment>
<util:RegistrySearchRef Id="NETFRAMEWORK40"/>
<WixVariable Id="WixMbaPrereqPackageId" Value="NetFx40Redist" />
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="$(var.NetFx40EulaLink)" />
<PackageGroup Id="NetFx40Redist">
<ExePackage
InstallCommand="/q /norestart /ChainingPackage "[WixBundleName]""
RepairCommand="/q /norestart /repair /ChainingPackage "[WixBundleName]""
UninstallCommand="/uninstall /q /norestart /ChainingPackage "[WixBundleName]""
PerMachine="yes"
DetectCondition="NETFRAMEWORK40"
Id="NetFx40Redist"
Vital="yes"
Permanent="yes"
Protocol="netfx4"
DownloadUrl="$(var.NetFx40RedistLink)"
Compressed="no"
Name="redist\dotNetFx40_Full_x86_x64.exe">
<RemotePayload
Size="50449456"
Version="4.0.30319.1"
ProductName="Microsoft .NET Framework 4"
Description="Microsoft .NET Framework 4 Setup"
CertificatePublicKey="672605E36DD71EC6B8325B91C5FE6971390CB6B6"
CertificateThumbprint="9617094A1CFB59AE7C1F7DFDB6739E4E7C40508F"
Hash="58DA3D74DB353AAD03588CBB5CEA8234166D8B99"/>
</ExePackage>
</PackageGroup>
</Fragment>
From wix36-sources\src\ext\NetFxExtension\wixlib\NetFx4.wxs
I can find the sha1 Hash
with fciv -sha1 dotNetFx40_Full_x86_x64.exe
...
58da3d74db353aad03588cbb5cea8234166d8b99 dotnetfx40_full_x86_x64.exe
I can find a matching CertificateThumbprint
easily through the properties dialog for the file, or using signtool
which displays the following output
C:\redist>signtool verify /v /ph dotNetFx40_Full_x86_x64.exe
Verifying: dotNetFx40_Full_x86_x64.exe
Signature Index: 0 (Primary Signature)
Hash of file (sha1): 8E8582D10521962F45F33935C38A2412C4F2D4C7
Signing Certificate Chain:
Issued to: Microsoft Root Authority
Issued by: Microsoft Root Authority
Expires: Thu Dec 31 03:00:00 2020
SHA1 hash: A43489159A520F0D93D032CCAF37E7FE20A8B419
Issued to: Microsoft Code Signing PCA
Issued by: Microsoft Root Authority
Expires: Sat Aug 25 03:00:00 2012
SHA1 hash: 3036E3B25B88A55B86FC90E6E9EAAD5081445166
Issued to: Microsoft Corporation
Issued by: Microsoft Code Signing PCA
Expires: Mon Mar 07 18:40:29 2011
SHA1 hash: 9617094A1CFB59AE7C1F7DFDB6739E4E7C40508F
The signature is timestamped: Thu Mar 18 21:13:46 2010
Timestamp Verified by:
Issued to: Microsoft Root Authority
Issued by: Microsoft Root Authority
Expires: Thu Dec 31 03:00:00 2020
SHA1 hash: A43489159A520F0D93D032CCAF37E7FE20A8B419
Issued to: Microsoft Timestamping PCA
Issued by: Microsoft Root Authority
Expires: Sun Sep 15 03:00:00 2019
SHA1 hash: 3EA99A60058275E0ED83B892A909449F8C33B245
Issued to: Microsoft Time-Stamp Service
Issued by: Microsoft Timestamping PCA
Expires: Thu Jul 25 15:11:15 2013
SHA1 hash: 4D6F357F0E6434DA97B1AFC540FB6FDD0E85A89F
SignTool Error: The signing certificate is not valid for the requested usage.
This error sometimes means that you are using the wrong verification
policy. Consider using the /pa option.
Number of files successfully Verified: 0
Number of warnings: 0
Number of errors: 1
What tool can provide the hash for CertificatePublicKey
?
edit: Without using heat, I want to understand where the hashes come from.
edit: I'm aware of how this is done in WiX source code and that I can execute
heat payload file -out file.wxs
, but I'm looking for some external tool which can provide the expected hash(es) without using heat. This is really only to sate my curiosity.
Solution
If you take a look at the sourcecode of the heat tool it uses the Microsoft.Tools.WindowsInstallerXml.Cab.Interop.NativeMethods.HashPublicKeyInfo
function to generate the CertificatePublicKey
.
byte[] publicKeyIdentifierHash = new byte[128];
uint publicKeyIdentifierHashSize = (uint)publicKeyIdentifierHash.Length;
Microsoft.Tools.WindowsInstallerXml.Cab.Interop.NativeMethods.HashPublicKeyInfo(
certificate.Handle,
publicKeyIdentifierHash,
ref publicKeyIdentifierHashSize);
StringBuilder sb = new StringBuilder(((int)publicKeyIdentifierHashSize + 1) * 2);
for (int i = 0; i < publicKeyIdentifierHashSize; ++i)
{
sb.AppendFormat("{0:X2}", publicKeyIdentifierHash[i]);
}
this.PublicKey = sb.ToString();
You can obviously use this code to generate the thumbprint or according to the wiki page on Public Key fingerprints you can also use the commandline
ssh-keygen -lf /path/to/key.pub
The problem is generating a ssh-keygen pub file that complies with RFC4716 from the certificate and this is where I was stumped.
Personally I just use the heat command-line:
heat.exe payload PATH_TO_FILE -o Output.wxs
and not worry about what it is actually doing as it works!! :)
OTHER TIPS
You can find all the information about a signature in the file properties dialog:
In the file properties dialog, click the signature tab.
Click details, then click 'View Certificate'.
Properties like 'Public Key' can be found on the 'Details' tab.
If you need a hash of this Public Key, then you can use your standard hashing tools to get it by using the 'Copy to File' button and hashing that file.I was incorrect, the 'Copy to File' does not export the selected property, but instead the whole certificate. You can copy and paste this value into a hash program or a hex editor to get the hash though.