2016-09-16 62 views
4

通过Visual Studio的项目“签名”设置页签署我的ClickOnce部署时,我指定了我们的SHA2(SHA256)EV Authenticode证书并发布。如何使用EV SHA2证书对ClickOnce部署进行身份验证并避免“未知发布者”

enter image description here

发布后,并尝试运行引导程序(SETUP.EXE)我呈现在ClickOnce的对话框中的“未知发布者”。

enter image description here

有问题的EV证书是有效的运行与SafeNet的客户端工具的电子令牌硬件令牌与令牌通信。使用signtool签署常规PE文件(exe和dll)总是会生成完全有效的程序集,并且发布者是已知的。 这只是ClickOnce部署的一个问题。另外,ClickOnce部署的单个文件看起来完全有效,因为文件属性对话框的数字签名选项卡已正确列出引导程序(setup.exe),而程序集文件后缀为“.deploy”。

enter image description here

另外,“应用”和“.manifest的”文件被适当地突变的(可能是通过由Visual Studio法师)以包含<publisherIdentity>元件与算法正确地设置沿。

enter image description here

签字机器运行Win10,我已经想尽排列我能想象:

  • 带和不带时间戳
  • 带和不带强名称签署
  • 随着并且没有在线发布
  • 有和没有https在线发布
  • 带和不特定的“位置更新”通过发布页面
  • 带和不带“出版商名称”通过描述设置在发布页面
  • 随着清单选项的每个组合:
    • 排除部署提供网址
    • 从通过URL
    • 使用应用程序清单的信任信息
  • 多町被激活块应用通过对法师和signtool各种版本的Windows
  • 手册清单签名和程序集签名的NES(是mageui以及)
  • 确保证书没有与证书提供商

似乎有someone else experiencing this撤销。

回答

2

发生这种情况的原因是由于几个因素

  1. 使用SHA2验证码证书时的ClickOnce显示“未知出版商”。
  2. 2016年1月1日Windows不推荐使用SHA1进行Authenticode签名/代码签名。 Windows SmartScreen技术因此在使用SHA1 Authenticode证书时显示“未知发布者”。

这实际上是一个catch-22,则需要SHA1为ClickOnce出版商验证和SHA2进行的SmartScreen。 尼斯

使用证书提供商(希望真正的CA)

工作,让你一个SHA1 SHA2证书。 DigiCert的人很棒。在大多数情况下,您必须使用您的CA,因为即使您已经拥有了自己的SHA2证书,并且您也可以使用它们以获得SHA1证书(或反之亦然),它可能会自动撤销您随身携带的任何现有证书。就DigiCert而言,当我解释我想要尝试的内容(双重签名)时,他们能够阻止自动撤销。

在您的EV令牌上安装这些令牌之后,请将Visual Studio配置为使用SHA1证书对您的ClickOnce清单进行签名。理想情况下,您还可以在同一个对话框中提供一个Timestamp服务器,以便证书最终到期。

enter image description here

本地发布的ClickOnce部署后和分发之前,双签上您的ClickOnce引导程序(SETUP.EXE)通过附加的SHA2证书。

signtool.exe sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /as /sha1 YourCertThumbprintHash "X:\Deployment\ClickOnceCert\setup.exe" 

请注意,找到您的证书指纹的一种方法是通过证书MMC管理单元。是的,指纹应该是用于SHA2证书的SHA1。现在

enter image description here

,该bootstapper同时显示在文件属性对话框的数字签名选项卡的证书。

enter image description here

当您从指定为在Visual Studio中的发布页面的“安装文件夹URL”位置的setup.exe,你应该看到出版商的信任。理解安装文件夹非常重要,因为如果您要从另一个位置运行应用程序,您应该预计不会被信任,因为引导程序将调用已知的安装文件夹来检索应用程序文件。

enter image description here

+0

时间

SignClickOnceApp.ps1

代码我试图按照这些指示。我联系了一个月前发布我的SHA2 EV证书的COMODO。他们说,“我们不再颁发SHA1证书。” 很明显,我正在和一个没有能力升级问题的工作人员聊天。我不知道下一步该怎么做。 –

+0

@RobPerkins有点旧了,但是你有没有在这方面取得进展?我在与USB令牌上的GlobalSign EV证书相同的情况下... –

+0

没有。我将不得不经过昂贵的使用证书提供者的过程来生产这两种证书。现在不值得。 –

1

的显着答案,因为我反正,导致智能屏警告。您可能对我编写的PowerShell脚本感兴趣,它通过用SHA256证书签名可以解决这两个问题,然后使用SHA1证书签署ClickOnce(.application)文件。在发布

<# 
.SYNOPSIS 
    A PowerShell Script to correctly sign a ClickOnce Application. 
.DESCRIPTION 
    Microsoft ClickOnce Applications Signed with a SHA256 Certificate show as Unknown Publisher during installation, ClickOnce Applications signed with a SHA1 Certificate show an Unknown Publisher SmartScreen Warning once installed, this happens because: 
    1) The ClickOnce installer only supports SHA1 certificates (not SHA256), but, 
    2) Microsoft has depreciated SHA1 for Authenticode Signing. 

    This script uses two code signing certificates (one SHA1 and one SHA256) to sign the various parts of the ClickOnce Application so that both the ClickOnce Installer and SmartScreen are happy. 
.PARAMETER VSRoot 
    The Visual Studio Projects folder, if not provided .\Documents\Visual Studio 2015\Projects will be assumed 
.PARAMETER SolutionName 
    The Name of the Visual Studio Solution (Folder), if not provided the user is prompted. 
.PARAMETER ProjectName 
    The Name of the Visual Studio Project (Folder), if not provided the user is prompted. 
.PARAMETER SHA1CertThumbprint 
    The Thumbprint of the SHA1 Code Signing Certificate, if not provided the user is prompted. 
.PARAMETER SHA256CertThumbprint 
    The Thumbprint of the SHA256 Code Signing Certificate, if not provided the user is prompted. 
.PARAMETER TimeStampingServer 
    The Time Stamping Server to be used while signing, if not provided the user is prompted. 
.PARAMETER PublisherName 
    The Publisher to be set on the ClickOnce files, if not provided the user is prompted. 
.PARAMETER Verbose 
    Writes verbose output. 
.EXAMPLE 
    SignClickOnceApp.ps1 -VSRoot "C:\Users\Username\Documents\Visual Studio 2015\Projects" -SolutionName "MySolution" -ProjectName "MyProject" -SHA1CertThumbprint "f3f33ccc36ffffe5baba632d76e73177206143eb" -SHA256CertThumbprint "5d81f6a4e1fb468a3b97aeb3601a467cdd5e3266" -TimeStampingServer "http://time.certum.pl/" -PublisherName "Awesome Software Inc." 
    Signs MyProject in MySolution which is in C:\Users\Username\Documents\Visual Studio 2015\Projects using the specified certificates, with a publisher of "Awesome Software Inc." and the Certum Timestamping Server. 
.NOTES 
    Author : Joe Pitt 
    License : SignClickOnceApp by Joe Pitt is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/. 
.LINK 
    https://www.joepitt.co.uk/Project/SignClickOnceApp/ 
#> 
param (
    [string]$VSRoot, 
    [string]$SolutionName, 
    [string]$ProjectName, 
    [string]$SHA1CertThumbprint, 
    [string]$SHA256CertThumbprint, 
    [string]$TimeStampingServer, 
    [string]$PublisherName, 
    [switch]$Verbose 
) 

$oldverbose = $VerbosePreference 
if($Verbose) 
{ 
    $VerbosePreference = "continue" 
} 

# Visual Studio Root Path 
if(!$PSBoundParameters.ContainsKey('VSRoot')) 
{ 
    $VSRoot = '.\Documents\Visual Studio 2015\Projects\' 
} 
if (Test-Path "$VSRoot") 
{ 
    Write-Verbose "Using '$VSRoot' for Visual Studio Root" 
} 
else 
{ 
    Write-Error -Message "VSRoot does not exist." -RecommendedAction "Check path and try again" -ErrorId "1" ` 
     -Category ObjectNotFound -CategoryActivity "Testing VSRoot Path" -CategoryReason "The VSRoot path was not found" ` 
     -CategoryTargetName "$VSRoot" -CategoryTargetType "Directory" 
    exit 1 
} 

# Solution Path 
if(!$PSBoundParameters.ContainsKey('SolutionName')) 
{ 
    $SolutionName = Read-Host "Solution Name" 
} 
if (Test-Path "$VSRoot\$SolutionName") 
{ 
    Write-Verbose "Using '$VSRoot\$SolutionName' for Solution Path" 
    $SolutionPath = "$VSRoot\$SolutionName" 
} 
else 
{ 
    Write-Error -Message "Solution does not exist." -RecommendedAction "Check Solution Name and try again" -ErrorId "2" ` 
     -Category ObjectNotFound -CategoryActivity "Testing Solution Path" -CategoryReason "The Solution path was not found" ` 
     -CategoryTargetName "$VSRoot\$SolutionName" -CategoryTargetType "Directory" 
    exit 2 
} 

# Project Path 
if(!$PSBoundParameters.ContainsKey('ProjectName')) 
{ 
    $ProjectName = Read-Host "Project Name" 
} 
if (Test-Path "$SolutionPath\$ProjectName") 
{ 
    Write-Verbose "Using '$SolutionPath\$ProjectName' for Project Path" 
    $ProjectPath = "$SolutionPath\$ProjectName" 
} 
else 
{ 
    Write-Error -Message "Project does not exist." -RecommendedAction "Check Project Name and try again" -ErrorId "3" ` 
     -Category ObjectNotFound -CategoryActivity "Testing Project Path" -CategoryReason "The Project path was not found" ` 
     -CategoryTargetName "$SolutionPath\$ProjectName" -CategoryTargetType "Directory" 
    exit 3 
} 

# Publish Path 
if (Test-Path "$ProjectPath\publish") 
{ 
    Write-Verbose "Using '$ProjectPath\publish' for Publish Path" 
    $PublishPath = "$ProjectPath\publish" 
} 
else 
{ 
    Write-Error -Message "Publish path does not exist." -RecommendedAction "Check Project has been published to \publish and try again" -ErrorId "4" ` 
     -Category ObjectNotFound -CategoryActivity "Testing Publish Path" -CategoryReason "The publish path was not found" ` 
     -CategoryTargetName "$ProjectPath\publish" -CategoryTargetType "Directory" 
    exit 4 
} 

# Application Files Path 
if (Test-Path "$PublishPath\Application Files") 
{ 
    Write-Verbose "Using '$PublishPath\Application Files' for Application Files Path" 
    $AppFilesPath = "$PublishPath\Application Files" 
} 
else 
{ 
    Write-Error -Message "Application Files path does not exist." -RecommendedAction "Check Project has been published to \publish and try again" -ErrorId "5" ` 
     -Category ObjectNotFound -CategoryActivity "Testing Application Files Path" -CategoryReason "The Application Files path was not found" ` 
     -CategoryTargetName "$PublishPath\Application Files" -CategoryTargetType "Directory" 
    exit 5 
} 

# Target Path 
$TargetPath = Convert-Path "$AppFilesPath\${ProjectName}_*" 
if ($($TargetPath.Length) -ne 0) 
{ 
    Write-Verbose "Using $TargetPath for Target Path" 
} 
else 
{ 
    Write-Error -Message "No versions." -RecommendedAction "Check Project has been published to \publish and try again" -ErrorId "6" ` 
     -Category ObjectNotFound -CategoryActivity "Searching for published version path" -CategoryReason "No Application has been published using ClickOnce" ` 
     -CategoryTargetName "$AppFilesPath\${ProjectName}_*" -CategoryTargetType "Directory" 
    exit 6 
} 

# SHA1 Certificate 
if(!$PSBoundParameters.ContainsKey('SHA1CertThumbprint')) 
{ 
    $SHA1CertThumbprint = Read-Host "SHA1 Certificate Thumbprint" 
} 
if ("$SHA1CertThumbprint" -notmatch "^[0-9A-Fa-f]{40}$") 
{ 
    Write-Error -Message "SHA1 Thumbprint Malformed" -RecommendedAction "Check the thumbprint and try again" -ErrorId "7" ` 
     -Category InvalidArgument -CategoryActivity "Verifying Thumbprint Format" -CategoryReason "Thumbprint is not a 40 character Base64 string" ` 
     -CategoryTargetName "$SHA1CertThumbprint" -CategoryTargetType "Base64String" 
    exit 7 
} 
$SHA1Found = Get-ChildItem -Path Cert:\CurrentUser\My | where {$_.Thumbprint -eq "$SHA1CertThumbprint"} | Measure-Object 
if ($SHA1Found.Count -eq 0) 
{ 
    Write-Error -Message "SHA1 Certificate Not Found" -RecommendedAction "Check the thumbprint and try again" -ErrorId "8" ` 
     -Category ObjectNotFound -CategoryActivity "Searching for certificate" -CategoryReason "Certificate with Thumbprint not found" ` 
     -CategoryTargetName "$SHA1CertThumbprint" -CategoryTargetType "Base64String" 
    exit 8 
} 

# SHA256 Certificate 
if(!$PSBoundParameters.ContainsKey('SHA256CertThumbprint')) 
{ 
    $SHA256CertThumbprint = Read-Host "SHA256 Certificate Thumbprint" 
} 
if ("$SHA256CertThumbprint" -notmatch "^[0-9A-Fa-f]{40}$") 
{ 
    Write-Error -Message "SHA256 Thumbprint Malformed" -RecommendedAction "Check the thumbprint and try again" -ErrorId "9" ` 
     -Category InvalidArgument -CategoryActivity "Verifying Thumbprint Format" -CategoryReason "Thumbprint is not a 40 character Base64 string" ` 
     -CategoryTargetName "$SHA256CertThumbprint" -CategoryTargetType "Base64String" 
    exit 9 
} 
$SHA256Found = Get-ChildItem -Path Cert:\CurrentUser\My | where {$_.Thumbprint -eq "$SHA256CertThumbprint"} | Measure-Object 
if ($SHA256Found.Count -eq 0) 
{ 
    Write-Error -Message "SHA256 Certificate Not Found" -RecommendedAction "Check the thumbprint and try again" -ErrorId "10" ` 
     -Category ObjectNotFound -CategoryActivity "Searching for certificate" -CategoryReason "Certificate with Thumbprint not found" ` 
     -CategoryTargetName "$SHA256CertThumbprint" -CategoryTargetType "Base64String" 
    exit 10 
} 

# TimeStamping Server 
if(!$PSBoundParameters.ContainsKey('TimeStampingServer')) 
{ 
    $TimeStampingServer = Read-Host "TimeStamping Server URL" 
} 
if ("$TimeStampingServer" -notmatch "^http(s)?:\/\/[A-Za-z0-9-._~:/?#[\]@!$&'()*+,;=]+$") 
{ 
    Write-Error -Message "SHA256 Thumbprint Malformed" -RecommendedAction "Check the TimeStamp URL and try again" -ErrorId "11" ` 
     -Category InvalidArgument -CategoryActivity "Verifying TimeStamping URL" -CategoryReason "TimeStamping URL is not a RFC Compliant URL" ` 
     -CategoryTargetName "$TimeStampingServer" -CategoryTargetType "URL" 
    exit 11 
} 

# Publisher Name 
# Project Path 
if(!$PSBoundParameters.ContainsKey('PublisherName')) 
{ 
    $PublisherName = Read-Host "Publisher Name" 
} 

# Sign setup.exe and application.exe with SHA256 Cert 
Write-Verbose "Signing '$PublishPath\Setup.exe' (SHA256)" 
Start-Process "$PSScriptRoot\signtool.exe" -ArgumentList "sign /fd SHA256 /td SHA256 /tr $TimeStampingServer /sha1 $SHA256CertThumbprint `"$PublishPath\Setup.exe`"" -Wait -NoNewWindow 
Write-Verbose "Signing '$TargetPath\$ProjectName.exe.deploy' (SHA256)" 
Start-Process "$PSScriptRoot\signtool.exe" -ArgumentList "sign /fd SHA256 /td SHA256 /tr $TimeStampingServer /sha1 $SHA256CertThumbprint `"$TargetPath\$ProjectName.exe.deploy`"" -Wait -NoNewWindow 

# Remove .deploy extensions 
Write-Verbose "Removing .deploy extensions" 
Get-ChildItem "$TargetPath\*.deploy" -Recurse | Rename-Item -NewName { $_.Name -replace '\.deploy','' } 

# Sign Manifest with SHA256 Cert 
Write-Verbose "Signing '$TargetPath\$ProjectName.exe.manifest' (SHA256)" 
Start-Process "$PSScriptRoot\mage.exe" -ArgumentList "-update `"$TargetPath\$ProjectName.exe.manifest`" -ch $SHA256CertThumbprint -if `"Logo.ico`" -ti `"$TimeStampingServer`"" -Wait -NoNewWindow 

# Sign ClickOnces with SHA1 Cert 
Write-Verbose "Signing '$TargetPath\$ProjectName.application' (SHA1)" 
Start-Process "$PSScriptRoot\mage.exe" -ArgumentList "-update `"$TargetPath\$ProjectName.application`" -ch $SHA1CertThumbprint -appManifest `"$TargetPath\$ProjectName.exe.manifest`" -pub `"$PublisherName`" -ti `"$TimeStampingServer`"" -Wait -NoNewWindow 
Write-Verbose "Signing '$PublishPath\$ProjectName.application' (SHA1)" 
Start-Process "$PSScriptRoot\mage.exe" -ArgumentList "-update `"$PublishPath\$ProjectName.application`" -ch $SHA1CertThumbprint -appManifest `"$TargetPath\$ProjectName.exe.manifest`" -pub `"$PublisherName`" -ti `"$TimeStampingServer`"" -Wait -NoNewWindow 

# Readd .deply extensions 
Write-Verbose "Re-adding .deploy extensions" 
Get-ChildItem -Path "$TargetPath\*" -Recurse | Where-Object {!$_.PSIsContainer -and $_.Name -notlike "*.manifest" -and $_.Name -notlike "*.application"} | Rename-Item -NewName {$_.Name + ".deploy"} 
+0

你可以复制PowerShell的源代码到链接应该链接去链接这个答案(也[这里](http://stackoverflow.com/questions/25004056/resign-clickonce-manifest-using-mage-exe/39811422 #39811422))?这改善了答案。此外,只要您的ClickOnce setup.exe已经用**有效的** SHA256证书签名,您就不会在我的回答后收到SmartScreen警告。欢迎来到SO,贡献很大! –

+0

@AdamCaviness当前代码按要求添加。参考SHA2签名的setup.exe,只有当用户使用setup.exe时才会出现这种情况,如果他们只是使用AppName.application,则会显示证书警告。 –

相关问题