I've been trying to wrap my mind around Authenticode certificates for a week now. I purchased a CSC from Comodo and I've got a ClickOnce application I'd like to sign so that the SmartScreen Filter warnings go away.
My application assembly is strong-named and I've ticked the box to "Sign the assembly" in my Project Properties. I've also ticked the box to "Sign the ClickOnce manifest" in the same Project Properties. And finally, I have the following executions set up as AfterCompile targets in my project file, in order to dual-sign the executable with both SHA1 and 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>
Then I run the following the command to publish the project:
"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /target:Publish /p:Configuration=Release /p:Platform=AnyCPU MyCoolApplication.csproj
What I've noticed is that this command ultimately creates three separate versions of MyCoolApplication.exe:
Unfortunately it's the copy in bin\Release\app.publish that needs to work, but for some reason this version is removing the dual signature. My understanding – which could be wrong – was that it built things in obj\Release, copied them to bin\Release\app.publish, and then signed the manifest. However clearly something else is going on, as the digital signature on the final executable is clearly changed. Here's the properties of those two files side-by-side:
The problem with the final single-signed/missing timestamp version is that the application still gets flagged with the SmartScreen filter, rendering the whole process pointless. How can I fix this?
UPDATE: After reading this guide, it seems that even if I sign things properly, I may still bump into the SmartScreen Filter by virtue of not having enough "reputation" for my application. However I would like to confirm that I have signed things properly in the first place, and am not chasing smoke. (Or if this is indicative of a breakdown in the build process, I want to correct that!)
EDIT: Here is the end of the MSBuild.exe output, which @CodeFuller has requested:
AfterCompile:
"signtool.exe" sign /f "certificate.pfx" /p mypassword /t http://timestamp.comodoca.com /v "MyCoolApplication\obj\Release\MyCoolApplication.exe"
The following certificate was selected:
...
Done Adding Additional Store
Successfully signed: MyCoolApplication\obj\Release\MyCoolApplication.exe
Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 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\Release\MyCoolApplication.exe"
The following certificate was selected:
...
Done Adding Additional Store
Successfully signed: MyCoolApplication\obj\Release\MyCoolApplication.exe
Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0
_DeploymentComputeClickOnceManifestInfo:
Creating directory "bin\Release\app.publish".
Copying file from "obj\Release\MyCoolApplication.exe" to "bin\Release\app.publish\MyCoolApplication.exe".
_CopyAppConfigFile:
Copying file from "App.config" to "bin\Release\MyCoolApplication.exe.config".
_CopyManifestFiles:
Copying file from "obj\Release\MyCoolApplication.exe.manifest" to "bin\Release\MyCoolApplication.exe.manifest".
MyCoolApplication -> C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\bin\Release\MyCoolApplication.exe.manifest
Copying file from "obj\Release\MyCoolApplication.application" to "bin\Release\MyCoolApplication.application".
MyCoolApplication -> C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\bin\Release\MyCoolApplication.application
CopyFilesToOutputDirectory:
Copying file from "obj\Release\MyCoolApplication.exe" to "bin\Release\MyCoolApplication.exe".
MyCoolApplication -> C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\bin\Release\MyCoolApplication.exe
Copying file from "obj\Release\MyCoolApplication.pdb" to "bin\Release\MyCoolApplication.pdb".
_CopyFilesToPublishFolder:
Creating directory "bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0".
Copying file from "bin\Release\MyCoolApplication.exe.manifest" to "bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\MyCoolApplication.exe.manifest". Copying file from "bin\Release\app.publish\MyCoolApplication.exe" to "bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\MyCoolApplication.exe.deploy". Copying file from "App.config" to "bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\MyCoolApplication.exe.config.deploy". Copying file from "triforce.ico" to "bin\Release\app.publish\Application Files\MyCoolApplication_1_0_0_0\triforce.ico.deploy". Done Building Project "C:\Users\Gordon\Documents\Visual Studio 2015\Projects\MyCoolApplication\MyCoolApplication\MyCoolApplication.csproj" (Publish target(s)).
Build succeeded. 0 Warning(s) 0 Error(s)
Time Elapsed 00:00:06.53
To disable ClickOnce security settings With a project selected in Solution Explorer, on the Project menu, click Properties. Click the Security tab. Clear the Enable ClickOnce Security Settings check box.
ClickOnce applications are fundamentally low impact. Applications are completely self-contained & install per-user, meaning no-admin rights are required. You don't have to worry about a ClickOnce application breaking other applications. ClickOnce applications can be deployed via web servers, file servers or CDs.
ClickOnce data directory. Every ClickOnce application installed on a local computer has a data directory, stored in the user's Documents and Settings folder. Any file included in a ClickOnce application and marked as a "data" file is copied to this directory when an application is installed.
You're correct in your expectation that binaries are built in obj\Release
and then copied to bin\Release\app.publish
. And for my test project with the same custom steps for AfterCompile
target everything works as expected. So most likely something goes wrong during the build. For further investigation, please update your question with output of MSBuild.exe
.
Here is my build sequence:
AfterCompile:
"signtool.exe" sign /f "MyKey.pfx" /p mypassword /t http://timestamp.comodoca.com /v "MyCoolApplication\obj\Release\MyCoolApplication.exe"
...
Successfully signed: MyCoolApplication\obj\Release\MyCoolApplication.exe
Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 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"
...
Successfully signed: MyCoolApplication\obj\Release\MyCoolApplication.exe
Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0
CleanPublishFolder:
Removing directory "bin\Release\app.publish\".
_DeploymentComputeClickOnceManifestInfo:
Creating directory "bin\Release\app.publish".
Copying file from "obj\Release\MyCoolApplication.exe" to "bin\Release\app.publish\MyCoolApplication.exe".
...
Build succeeded.
0 Warning(s)
0 Error(s)
So I'd continue with following questions:
obj\Release\MyCoolApplication.exe
and Release\app.publish\MyCoolApplication.exe
files equal?UPDATE:
After enabling Diagnostic verbosity of build output all cleared up a bit.
Enabling of 'Sign the ClickOnce manifests' on Signing tab of project settings leads to SignTool.exe
call for bin\Release\app.publish\MyCoolApplication.exe
. By default SignTool will overwrite existing signature. That's why second call of SignTool in your AfterCompile target is done with /as
key - the option for appending the signature.
So if you want to keep your custom signing commands you should disable option 'Sign the ClickOnce manifests' and add custom commands for signing the manifest. To complete this following files should be signed on following build steps:
After _DeploymentComputeClickOnceManifestInfo
target:
bin\Release\app.publish\MyCoolApplication.exe
. The macro for filename is "$(PublishDir)$(TargetFileName)"
After _DeploymentSignClickOnceDeployment
target:
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
Manifest should be signed with mage.exe
tool.
Here is updated project file that achieves what you need:
<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With