web-dev-qa-db-fra.com

WiX: signature numérique du projet BootStrapper

J'ai un projet pour lequel j'ai construit un fichier msi WiX. J'ai également un bootstrapper WiX (fichier exe) qui vérifie l'existence de C++ 2005, l'installe s'il n'est pas trouvé, puis installe le package msi. Mon projet inclut Crystal Reports en tant que fichier msm qui est installé avec le msi mais nécessite C++ 2005 pour s’installer correctement.

Sur le projet MSI, j'ai inclus l'événement post-build suivant pour signer numériquement le fichier msi.

  sign  /f "$(ProjectDir)\myPFXFile.pfx" /p mySecretKey/d "My Program" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "MyProgram.msi"

Si j'installe juste le msi, il identifie correctement l'éditeur lors de la demande d'une autorisation élevée d'installation.

J'ai essayé d'ajouter le même événement post-build au projet bootstrapper comme suit:

  sign  /f "$(ProjectDir)\myPFXFile.pfx" /p mySecretKey/d "My Program" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "MyProgram Setup.exe"

Lorsque j'essaie d'installer le fichier exe, il identifie correctement l'éditeur mais échoue à l'installation avec les éléments suivants dans le fichier journal:

[1604:2574][2013-12-04T11:49:51]i001: Burn v3.7.1224.0, Windows v6.2 (Build 9200: Service Pack 0), path: C:\Users\.....\MyProgram Setup.exe, cmdline: ''
[1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'WixBundleLog' to value 'C:\Users\.....\MyProgram_20131204114951.log'
[1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'WixBundleOriginalSource' to value 'C:\Users\.....\MyProgram Setup.exe'
[1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'WixBundleName' to value 'MyProgram'
[1604:2574][2013-12-04T11:49:51]i100: Detect begin, 2 packages
[1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'vcredist_x86' to value '1'
[1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'vcredist_x64' to value '1'
[1604:2574][2013-12-04T11:49:51]i052: Condition 'vcredist_x86 AND (vcredist_x86 >= 1)' evaluates to true.
[1604:2574][2013-12-04T11:49:51]i101: Detected package: vcredist_x86, state: Present, cached: None
[1604:2574][2013-12-04T11:49:51]i101: Detected package: MyProgram, state: Absent, cached: None
[1604:2574][2013-12-04T11:49:51]i199: Detect complete, result: 0x0
[1604:2574][2013-12-04T11:49:53]i200: Plan begin, 2 packages, action: Install
[1604:2574][2013-12-04T11:49:53]w321: Skipping dependency registration on package with no dependency providers: vcredist_x86
[1604:2574][2013-12-04T11:49:53]i000: Setting string variable 'WixBundleRollbackLog_MyProgram' to value 'C:\Users\.....\MyProgram_20131204114951_0_MyProgram_rollback.log'
[1604:2574][2013-12-04T11:49:53]i000: Setting string variable 'WixBundleLog_MyProgram' to value 'C:\Users\.....\MyProgram_20131204114951_0_MyProgram.log'
[1604:2574][2013-12-04T11:49:53]i201: Planned package: vcredist_x86, state: Present, default requested: Present, ba requested: Present, execute: None, rollback: None, cache: No, uncache: No, dependency: None
[1604:2574][2013-12-04T11:49:53]i201: Planned package: MyProgram, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: Register
[1604:2574][2013-12-04T11:49:53]i299: Plan complete, result: 0x0
[1604:2574][2013-12-04T11:49:53]i300: Apply begin
[1FF8:10F8][2013-12-04T11:49:58]i360: Creating a system restore point.
[1FF8:10F8][2013-12-04T11:49:59]i361: Created a system restore point.
[1FF8:10F8][2013-12-04T11:50:00]i000: Caching bundle from: 'C:\Users\.....\{6ab8eece-89c6-4417-905f-6d9c5136519d}\.be\MyProgram Setup.exe' to: 'C:\ProgramData\Package Cache\{6ab8eece-89c6-4417-905f-6d9c5136519d}\MyProgram Setup.exe'
[1FF8:10F8][2013-12-04T11:50:00]i320: Registering bundle dependency provider: {6ab8eece-89c6-4417-905f-6d9c5136519d}, version: 2.0.0.0
[1604:2FB4][2013-12-04T11:50:00]i336: Acquiring container: WixAttachedContainer, copy from: C:\Users\.....\MyProgram Setup.exe
[1604:2FB4][2013-12-04T11:50:00]i000: Setting string variable 'WixBundleLastUsedSource' to value 'C:\Users\.....'
[1604:24F8][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to extract all files from container.
[1604:2FB4][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to wait for operation complete.
[1604:2FB4][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to open container.
[1604:2FB4][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to open container: WixAttachedContainer.
[1604:2FB4][2013-12-04T11:50:00]e312: Failed to extract payloads from container: WixAttachedContainer to working path: C:\Users\.....\{6ab8eece-89c6-4417-905f-6d9c5136519d}\C7C1FB4E513C19E0F5E8F6856FF2ACC4D7D143A2, error: 0x80004005.
[1604:2574][2013-12-04T11:50:00]e000: Error 0x80004005: Failed while caching, aborting execution.
[1FF8:10F8][2013-12-04T11:50:00]i330: Removed bundle dependency provider: {6ab8eece-89c6-4417-905f-6d9c5136519d}
[1FF8:10F8][2013-12-04T11:50:00]i352: Removing cached bundle: {6ab8eece-89c6-4417-905f-6d9c5136519d}, from path: C:\ProgramData\Package Cache\{6ab8eece-89c6-4417-905f-6d9c5136519d}\
[1604:2574][2013-12-04T11:50:00]i399: Apply complete, result: 0x80004005, restart: None, ba requested restart:  No

J'ai ensuite trouvé une autre alternative à la signature de l'exe en ajoutant ce qui suit à la fin du fichier .wixproj:

  <Target Name="SignBundleEngine">
    <Exec Command="&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\signtool.exe&quot; sign /f &quot;$(ProjectDir)\sigFile.pfx&quot; /p sigKey /d &quot;My Program&quot; /t http://timestamp.verisign.com/scripts/timstamp.dll &quot;@(SignBundleEngine)&quot;" />
  </Target>
  <Target Name="SignBundle">
    <Exec Command="&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\signtool.exe&quot; sign /f &quot;$(ProjectDir)\sigFile.pfx&quot; /p sigKey /d &quot;My Program&quot; /t http://timestamp.verisign.com/scripts/timstamp.dll &quot;@(SignBundle)&quot;" />
  </Target>
  <PropertyGroup>
    <PostBuildEvent>"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\signtool.exe"  sign  /f "$(ProjectDir)\sigFile.pfx" /p sigKey /d "My Program" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "MyProgram Setup.exe"</PostBuildEvent>
  </PropertyGroup>

En utilisant cette méthode, le fichier d'installation s'exécute et installe tout correctement, mais n'identifie pas l'éditeur lors de la demande d'une autorisation élevée d'installation, il indique "Publisher: inconnu".

Quelqu'un sait comment faire fonctionner la signature numérique sur ce programme d'amorçage?

Voici mes fichiers Bundle.wxs et vcredist.wxs:

Bundle.wxs

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.Microsoft.com/wix/2006/wi"
     xmlns:bal="http://schemas.Microsoft.com/wix/BalExtension">


  <Bundle Name="My Program"
          Version="2.0.0"
          Manufacturer="My Company"
          UpgradeCode="PUT-GUID-HERE"
          HelpUrl="http://www.mycompany.com"
          AboutUrl="http://www.mycompany.com"
          HelpTelephone="888 888 8888"
          IconSourceFile="Resources\program.ico">

    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
      <Payload SourceFile="Resources\Bootstrapper Screen.png" />
    </BootstrapperApplicationRef>

    <WixVariable Id="WixStdbaLicenseUrl" Value=""/>

    <WixVariable Id="WixStdbaThemeXml" Value="Resources\CustomHyperlinkTheme.xml"/>
    <WixVariable Id="WixStdbaThemeWxl" Value="Resources\CustomHyperlinkTheme.wxl"/>

    <Chain>

      <!-- Define the list of chained packages. -->
      <PackageGroupRef Id="vcredist"/>
      <MsiPackage Id="MyProgram"
                  SourceFile="$(var.MyProgramSetup.TargetPath)"
                  ForcePerMachine="yes" />
    </Chain>
  </Bundle>
</Wix>

vcredist.wxs

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.Microsoft.com/wix/2006/wi"
     xmlns:util="http://schemas.Microsoft.com/wix/UtilExtension">
  <Fragment>
    <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86" Value="Installed" Variable="vcredist_x86" />
    <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x64" Value="Installed" Variable="vcredist_x64" />
    <PackageGroup Id="vcredist">
      <ExePackage Id="vcredist_x86"
        Cache="no"
        Compressed="yes"
        PerMachine="yes"
        Permanent="yes"
        Vital="yes"
        Name="vcredist_x86.exe"
        SourceFile="vcredist3.5_x86.exe"
        InstallCommand="/q"
        DetectCondition="vcredist_x86 AND (vcredist_x86 &gt;= 1)">
      </ExePackage>
    </PackageGroup>
  </Fragment>
</Wix>
28
BrianKE
  <Target Name="UsesFrameworkSdk">
    <GetFrameworkSdkPath>
      <Output TaskParameter="Path" PropertyName="FrameworkSdkPath" />
    </GetFrameworkSdkPath>
    <PropertyGroup>
      <Win8SDK>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0@InstallationFolder)</Win8SDK>
    </PropertyGroup>    
  </Target>

  <Target Name="UsesSignTool" DependsOnTargets="UsesFrameworkSdk">
    <PropertyGroup>
      <SignToolPath Condition="('@(SignToolPath)'=='') and Exists('$(FrameworkSdkPath)bin\signtool.exe')">$(FrameworkSdkPath)bin\signtool.exe</SignToolPath>
      <SignToolPath Condition="('@(SignToolPath)'=='') and Exists('$(Win8SDK)\bin\x86\signtool.exe')">$(Win8SDK)\bin\x86\signtool.exe</SignToolPath>
    </PropertyGroup>
  </Target>

  <Target Name="SignBundleEngine" DependsOnTargets="UsesSignTool">
    <Exec Command="&quot;$(SignToolPath)&quot; sign /d &quot;App Setup&quot; /t http://timestamp.digicert.com /a &quot;@(SignBundleEngine)&quot;" />
  </Target>

  <Target Name="SignBundle" DependsOnTargets="UsesSignTool">
    <Exec Command="&quot;$(SignToolPath)&quot; sign /d &quot;App Setup&quot; /t http://timestamp.digicert.com /a &quot;@(SignBundle)&quot;" />
  </Target>

Cela fonctionne bien pour moi. Soit vous le faites pendant la construction, soit vous devez utiliser des insignes.
Ex: http://wixtoolset.org/documentation/manual/v3/overview/insignia.html

insignia -ib bundle.exe -o engine.exe
... sign engine.exe
insignia -ab engine.exe bundle.exe -o bundle.exe
... sign bundle.exe
25
jchoover

Pour moi, utiliser l'outil intégré de WiX insignia est le plus simple. Voici les étapes que j'ai faites pour signer le code d'un WiX MSI et bootstrap installer:
(les étapes 1 et 2 sont juste configurées pour rendre la lecture de 3 et 4 facile et plus réutilisable et modifiable! Les étapes 3 et 4 sont la signature réelle)

  1. Configurez le signtool en tant que fichier de commandes dans mon CHEMIN afin que je puisse l'appeler et le changer facilement. J'utilise Windows 10 et donc mon "signtool.bat" ressemble à ceci:
    "c:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" %*
  2. Configurez également insignia en tant que fichier de commandes dans mon CHEMIN afin de pouvoir le modifier avec les nouvelles versions WiX au fur et à mesure. Mon "insignia.bat" ressemble à ceci:
    "C:\Program Files (x86)\WiX Toolset v3.10\bin\insignia.exe" %*
  3. Signer mon MSI dans un événement post-build (Projet MSI -> Propriétés -> Build Events) en appelant ceci:
    signtool sign /f "c:\certificates\mycert.pfx" /p cert-password /d "Your Installer Label" /t http://timestamp.verisign.com/scripts/timstamp.dll /v $(TargetFileName)
  4. Signer mon bundle dans un événement post-build pour le projet bootstrap comme ceci:

    CALL insignia -ib "$(TargetFileName)" -o engine.exe
    CALL signtool sign /f "c:\certificates\mycert.pfx" /p cert-password /d "Installer Name" /t http://timestamp.verisign.com/scripts/timstamp.dll /v engine.exe
    CALL insignia -ab engine.exe "$(TargetFileName)" -o "$(TargetFileName)"
    CALL signtool sign /f "c:\certificates\mycert.pfx" /p cert-password /d "Installer Name" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "$(TargetFileName)"


Notes et réflexions supplémentaires:

  • J'ai également signé la demande (je pense) en faisant simplement Project Properties -> Signing et activer les manifestes click-once, sélectionner le certificat et vérifier le Sign the Assembly option.

  • La spécification de CALL est nécessaire dans les événements post-génération lors de l'appel d'un fichier batch ou seul le premier est appelé.

16
noelicus

En outre, la réponse de @ jchoover, vous avez 3 options lors de la signature des bundles:

  • Créez le bundle non signé, puis signez-le plus tard. Cependant, vous devez également signer l'exe du moteur qui est intégré au bundle. Comme l'indique @jchoover, vous pouvez utiliser insignia pour contourner ce problème en extrayant le moteur dans un fichier. Vous pouvez ensuite signer le fichier à l'aide de votre processus normal (par exemple, avec signtool.exe), puis le réimporter dans le bundle

  • Ajoutez les cibles SignBundle et SignBundleEngine à vos projets. Pour ce faire, ouvrez-les dans un éditeur de texte et modifiez le code MSBuild sous-jacent. La réponse de @ jchoover décrit comment vous pouvez le faire.

  • Créez un fichier .targets avec les cibles SignBundle et SignBundleEngine et passez le chemin à l'aide de la propriété CustomAfterWixTargets:

    msbuild your.sln /p:CustomAfterWixTargets=customafterwix.targets /p:SignOutput=true

5
JohnL

Mise à jour pour VS2019, et basée sur la réponse de @ jchoover, voici ce que j'ai travaillé.

Cela exploite certains travaux de fonction de propriété MSBuild par @webjprgm ici qui rend la recherche de signtool.exe plus générique dans les versions du Kit Windows. Comme mentionné par @karfus dans un commentaire ci-dessus, l'ajout de la section SignOutput est l'incantation qui donne le coup d'envoi.

Cela va à la fin de votre fichier bootstrap.wixproj, avant la balise de fermeture/Project.

  <!-- SignOutput must be present in some PropertyGroup to trigger signing. -->
  <PropertyGroup> 
    <SignOutput>true</SignOutput>
  </PropertyGroup>

  <!-- Find Windows Kit path and then SignTool path for the post-build event -->
  <Target Name="FindSignTool">
      <PropertyGroup>
        <WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
        <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot81', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
        <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
        <SignToolPath Condition="'$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU' and Exists('$(WindowsKitsRoot)bin\x64\signtool.exe')">$(WindowsKitsRoot)bin\x64\</SignToolPath>
        <SignToolPath Condition="'$(SignToolPath)' == '' And Exists('$(WindowsKitsRoot)bin\$(Platform)\signtool.exe')">$(WindowsKitsRoot)bin\$(Platform)\</SignToolPath>
        <SignToolPathBin Condition="'$(SignToolPath)' == ''">$([System.IO.Directory]::GetDirectories('$(WindowsKitsRoot)bin',"10.0.*"))</SignToolPathBin>
        <SignToolPathLen Condition="'$(SignToolPathBin)' != ''">$(SignToolPathBin.Split(';').Length)</SignToolPathLen>
        <SignToolPathIndex Condition="'$(SignToolPathLen)' != ''">$([MSBuild]::Add(-1, $(SignToolPathLen)))</SignToolPathIndex>
        <SignToolPathBase Condition="'$(SignToolPathIndex)' != ''">$(SignToolPathBin.Split(';').GetValue($(SignToolPathIndex)))\</SignToolPathBase>
        <SignToolPath Condition="'$(SignToolPath)' == '' And '$(SignToolPathBase)' != '' And '$(Platform)' == 'AnyCPU'">$(SignToolPathBase)x64\</SignToolPath>
        <SignToolPath Condition="'$(SignToolPath)' == '' And '$(SignToolPathBase)' != ''">$(SignToolPathBase)$(Platform)\</SignToolPath>
      </PropertyGroup>
  </Target>

  <!-- Sign the bundle engine -->
  <Target Name="SignBundleEngine" DependsOnTargets="FindSignTool">
    <Exec Command="&quot;$(SignToolPath)signtool.exe&quot; sign /d &quot;MyApp Setup&quot; /fd SHA256 /td SHA256 /a /f &quot;MyApp Code Certificate.pfx&quot; /p CertPassword /tr http://timestamp.digicert.com /a &quot;@(SignBundleEngine)&quot;" />
  </Target>

  <!-- Sign the final bundle -->
  <Target Name="SignBundle" DependsOnTargets="FindSignTool">
    <Exec Command="&quot;$(SignToolPath)signtool.exe&quot; sign /d &quot;MyApp Setup&quot;  /fd SHA256 /td SHA256 /a /f &quot;MyApp Code Certificate.pfx&quot; /p CertPassword /tr http://timestamp.digicert.com /a &quot;@(SignBundle)&quot;" />
  </Target>
2
entiat