soa*_*gem 5 c# msbuild clickonce code-signing signtool
一周以来,我一直在努力思考Authenticode 证书。我从 Comodo 购买了一个 CSC,我有一个 ClickOnce 应用程序,我想签名以便 SmartScreen 过滤器警告消失。
我的应用程序程序集是强命名的,我在我的项目属性中勾选了“签署程序集”框。我还在同一项目属性中勾选了“签署 ClickOnce 清单”的框。最后,我在我的项目文件中将以下执行设置为 AfterCompile 目标,以便使用 SHA1 和 SHA256 对可执行文件进行双重签名:
<Target Name="AfterCompile">
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /t http://timestamp.comodoca.com /v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"" />
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /as /v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"" />
</Target>
Run Code Online (Sandbox Code Playgroud)
然后我运行以下命令来发布项目:
"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /target:Publish /p:Configuration=Release /p:Platform=AnyCPU MyCoolApplication.csproj
我注意到这个命令最终会创建三个独立版本的 MyCoolApplication.exe:
不幸的是,需要工作的是 bin\Release\app.publish 中的副本,但由于某种原因,此版本正在删除双重签名。我的理解——这可能是错误的——是它在 obj\Release 中构建东西,将它们复制到 bin\Release\app.publish,然后签署清单。然而,很明显其他事情正在发生,因为最终可执行文件上的数字签名显然已更改。这是并排的这两个文件的属性:
最终单签名/缺失时间戳版本的问题是应用程序仍然被 SmartScreen 过滤器标记,使整个过程变得毫无意义。我怎样才能解决这个问题?
更新:阅读本指南后,似乎即使我正确签名,由于我的应用程序没有足够的“声誉”,我仍然可能会遇到 SmartScreen 过滤器。但是,我想确认我首先正确地签署了东西,并且不是在追逐烟雾。(或者,如果这表明构建过程出现故障,我想纠正它!)
编辑:这是@CodeFuller 要求的 MSBuild.exe 输出的结尾:
编译后:
"signtool.exe" sign /f "certificate.pfx" /p mypassword /t http://timestamp.comodoca.com /v "MyCoolApplication\obj\Release\MyCoolApplication.exe"
选择了以下证书:
...
完成添加额外的商店
签名成功:MyCoolApplication\obj\Release\MyCoolApplication.exe
成功签名的文件数:1
警告数:0
错误数:0
"signtool.exe" sign /f "MyCoolApp lication\certificate.pfx" /p mypassword /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /as /v "MyCoolApplication\obj\发布\MyCoolApplication.exe”
选择了以下证书:
...
完成添加额外的商店
签名成功:MyCoolApplication\obj\Release\MyCoolApplication.exe
成功签名的文件数:1
警告数:0
错误数:0
_DeploymentComputeClickOnceManifestInfo:
创建目录“bin\Release\app.publish”。
将文件从“obj\Release\MyCoolApplication.exe”复制到“bin\Release\app.publish\MyCoolApplication.exe”。
_CopyAppConfigFile:
将文件从“App.config”复制到“bin\Release\MyCoolApplication.exe.config”。
_CopyManifestFiles:
将文件从“obj\Release\MyCoolApplication.exe.manifest”复制到“bin\Release\MyCoolApplication.exe.manifest”。
MyCoolApplication -> C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\bin\Release\MyCoolApplication.exe.manifest
将文件从“obj\Release\MyCoolApplication.application”复制到“bin\Release\MyCoolApplication.application”。
MyCoolApplication -> C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\bin\Release\MyCoolApplication.application
复制文件到输出目录:
将文件从“obj\Release\MyCoolApplication.exe”复制到“bin\Release\MyCoolApplication.exe”。
MyCoolApplication -> C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\bin\Release\MyCoolApplication.exe
将文件从“obj\Release\MyCoolApplication.pdb”复制到“bin\Release\MyCoolApplication.pdb”。
_CopyFilesToPublishFolder:
创建目录“bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0”。
将文件从“bin\Release\MyCoolApplication.exe.manifest”复制到“bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\MyCoolApplication.exe.manifest”。将文件从“bin\Release\app.publish\MyCoolApplication.exe”复制到“bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\MyCoolApplication.exe.deploy”。将文件从“App.config”复制到“bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\MyCoolApplication.exe.config.deploy”。将文件从“triforce.ico”复制到“bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\triforce.ico.deploy”。完成构建项目“C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\MyCoolApplication.csproj”
构建成功。0 警告 0 错误
已用时间 00:00:06.53
您期望二进制文件是内置的obj\Release然后复制到bin\Release\app.publish. 对于我的测试项目,AfterCompile目标的自定义步骤相同,一切都按预期工作。所以很可能在构建过程中出现问题。如需进一步调查,请使用输出更新您的问题MSBuild.exe。
这是我的构建顺序:
AfterCompile:
"signtool.exe" sign /f "MyKey.pfx" /p mypassword /t http://timestamp.comodoca.com /v "MyCoolApplication\obj\Release\MyCoolApplication.exe"
...
签名成功:MyCoolApplication\ obj\Release\MyCoolApplication.exe
成功签名的文件数:1
警告数:0
错误数:0
“signtool.exe” sign /f “MyKey.pfx” /p mypassword /fd sha256 /tr http://timestamp .comodoca.com/?td=sha256 /td sha256 /as /v "MyCoolApplication\obj\Release\MyCoolApplication.exe"
...
成功签名:MyCoolApplication\obj\Release\MyCoolApplication.exe
成功签名的文件数:1
警告数:0
错误数:0
CleanPublishFolder:
正在删除目录“bin\Release\app.publish\”。
_DeploymentComputeClickOnceManifestInfo:
创建目录“bin\Release\app.publish”。
将文件从“obj\Release\MyCoolApplication.exe”复制到“bin\Release\app.publish\MyCoolApplication.exe”。
...
构建成功。
0 警告
0 错误
所以我会继续回答以下问题:
obj\Release\MyCoolApplication.exe和Release\app.publish\MyCoolApplication.exe文件的时间戳是否相等?更新:
启用构建输出的诊断详细程度后,所有内容都清除了一点。
在项目设置的签名选项卡上启用“签署 ClickOnce 清单”会导致SignTool.exe调用bin\Release\app.publish\MyCoolApplication.exe. 默认情况下,SignTool 将覆盖现有签名。这就是为什么在 AfterCompile 目标中第二次调用 SignTool 是使用/askey完成的- 用于附加签名的选项。
因此,如果您想保留自定义签名命令,则应禁用“签署 ClickOnce 清单”选项并添加用于签署清单的自定义命令。要完成此操作,应在以下构建步骤中签署以下文件:
之后_DeploymentComputeClickOnceManifestInfo的目标:
bin\Release\app.publish\MyCoolApplication.exe。文件名的宏是"$(PublishDir)$(TargetFileName)"
之后_DeploymentSignClickOnceDeployment的目标:
bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_3\MyCoolApplication.exe.manifest- "$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)"
bin\Release\app.publish\MyCoolApplication.application- "$(PublishDir)$(TargetDeployManifestFileName)"
bin\Release\app.publish\setup.exe-$(PublishDir)\setup.exe
清单应使用mage.exe工具签名。
这是更新的项目文件,可满足您的需求:
<Target Name="AfterCompile">
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /t http://timestamp.comodoca.com /v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"" />
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /as /v "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"" />
</Target>
<Target Name="SignAssembly" AfterTargets="_DeploymentComputeClickOnceManifestInfo">
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /t http://timestamp.comodoca.com /v "$(PublishDir)$(TargetFileName)"" />
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /as /v "$(PublishDir)$(TargetFileName)"" />
</Target>
<Target Name="SignManifest" AfterTargets="_DeploymentSignClickOnceDeployment">
<Exec Command=""c:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\mage.exe" -Sign "$(_DeploymentApplicationDir)$(_DeploymentTargetApplicationManifestFileName)" -CertFile "$(ProjectDir)certificate.pfx" -Password mypassword -TimeStampUri http://timestamp.comodoca.com" />
<Exec Command=""c:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\mage.exe" -Sign "$(PublishDir)$(TargetDeployManifestFileName)" -CertFile "$(ProjectDir)certificate.pfx" -Password mypassword -TimeStampUri http://timestamp.comodoca.com" />
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /t http://timestamp.comodoca.com /v "$(PublishDir)\setup.exe"" />
<Exec Command=""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "$(ProjectDir)certificate.pfx" /p mypassword /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /as /v "$(PublishDir)\setup.exe"" />
</Target>
Run Code Online (Sandbox Code Playgroud)