客户端计算机上的"清单XML签名无效",但在开发人员计算机上运行正常

Dzy*_*ann 24 clickonce

在工作中,我们有一个ClickOnce应用程序,当客户端尝试安装时,它会抛出异常:

  • 从文件中读取异常:/ FILEPATH:清单可能无效或无法打开文件.

    清单XML签名无效.

    无法为提供的签名算法创建SignatureDescription.

为了解决这个问题,我们最终使用了另一个证书文件,并且工作正常(重新签署了清单).

但是我们无法理解为什么在开发人员机器中安装应用程序(甚至是不使用该应用程序的开发人员)会起作用,但它不适用于客户端的机器?

我们没有太多关于如何创建证书或ClickOnce包的信息,因为执行该证书的人已经离开并且没有留下关于它的文档.

正在使用的证书没有密码,普通用户没有管理员权限.

从Stack Overflow问题Manifest XML签名无效,我猜测问题可能是他们使用.NET Framework 4.5 创建项目和证书,然后当他们将应用程序设置为使用.NET Framework 4.0运行时,他们没有更改签名算法.但后来我认为它不应该对开发人员起作用.

您可以给我的任何见解将不胜感激.

Mat*_*ing 26

更新:从Visual Studio 2013 Update 3开始修复此问题.尝试从该版本的VS或更高版本发布您的应用程序.

上一个答案:

这是因为您的开发人员计算机安装了.NET 4.5,而您的客户端计算机只安装了.NET 4.0..NET 4.0客户端计算机无法读取清单,因为他们期望SHA-1,而.NET 4.5开发人员计算机可以.

有关其他上下文,请参阅此博客文章.

此更改是由于我们在NetFX4.5中停止使用旧证书作为默认值(SHA-1)来对清单进行签名,而是使用较新版本(SHA-256),这是NetFx4.0运行时无法识别的.因此,在解析清单时,4.0运行时会抱怨无效的清单.对于遗留框架,当我们尝试在没有目标运行时的框上运行ClickOnce应用程序时,ClickOnce会向用户弹出一条消息,说"您需要xxxx.xx运行时才能运行此应用程序".但是从.NET 4.5开始,如果在仅安装了.NET 4.0的盒子上运行4.5 ClickOnce应用程序,则该消息会报告无效的清单.要解决此问题,必须在目标系统上安装.Net Framework 4.5.

尝试使用SHA-1证书而不是SHA-2证书对清单进行签名.

  • +1,但该死的MS,如果你不能安装4.5,因为它是2k3服务器怎么办?如果你不能安装它们,那么能够定位早期版本的运行时有什么意义呢? (7认同)
  • 如果您想在答案中添加说明,解决方案是在VS2010中打开项目,转到项目属性并选择签名,然后"创建测试证书".这将使用SHA1生成一个并且似乎不会更改项目中的任何其他内容. (4认同)

Mir*_*kov 13

我们遇到了类似的问题 - 我们有一个.NET 4.0应用程序,适用于运行.NET 4.0或更高版本的计算机.由于我们的代码签名证书已过期,我们购买了新的代码签名证书,因为Sha1将被删除,我们收到了一个Sha256.我应该说我们的构建机器已经安装了.NET 4.5,因此框架程序集都在该机器上进行了更新.

我们注意到,迁移到新证书后,以下错误才开始出现在.NET 4.0计算机上:

* Activation of http://localhost/publish/Test.application resulted in exception. Following failure messages were detected:
    + Exception reading manifest from http://localhost/publish/Test.application: the manifest may not be valid or the file could not be opened.
    + Manifest XML signature is not valid.
    + SignatureDescription could not be created for the signature algorithm supplied.
Run Code Online (Sandbox Code Playgroud)

经过一番研究后,fe发现了这个线程和其他一些,建议升级到.NET 4.5,但这对我们来说不是一个有效的解决方案 - 我们不想强迫我们的客户更新.NET框架(~20%仍在使用.NET 4.0).以下是我们提出的解决方案:

  • 在仅安装了.NET 4.0的计算机上签署清单
  • 使用以下PowerShell脚本而不是使用mage.exe进行签名:
function SignFile($filePath, $timeStampUri, $certThumbprint)
{
    #Add-Type System.Security

    $x509Store = New-Object -TypeName ([System.Security.Cryptography.X509Certificates.X509Store]) -ArgumentList ([System.Security.Cryptography.X509Certificates.StoreName]::My),([System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser)
    try
    {
        $x509Store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
        $x509Certificate2Collection = $x509Store.Certificates.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint, $certThumbprint, $false);
        if ($x509Certificate2Collection.Count -eq 1)
        {
            $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]@($x509Certificate2Collection)[0]

            # This will force using of SHA1 instead of SHA256
            $cert.SignatureAlgorithm.FriendlyName = ""

            Add-Type -AssemblyName "Microsoft.Build.Tasks.v4.0"

            [Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities]::SignFile($cert, $timeStampUri, $filePath)
        }
    }
    finally
    {
        $x509Store.Close();
    }
}

编辑:我实际上使用此命令 - 来签署清单文件: https ://gist.github.com/nedyalkov/a563dd4fb04d21cb91dc

希望这些信息可以节省时间和精力!