使用 DigestMethod 的 sha256 算法修改 C# 清单

Modify a C# Manifest using the sha256 algorithm for the DigestMethod

我需要更新 .NET 4.5.1 应用程序清单,确保 DigestMethod 保持为 sha256 哈希。

原因如下:我最初将带有 ClickOnce 的 WPF 应用程序部署到开发环境,然后脚本配置、签署应用程序并将其复制到特定的生产环境。我有一个执行此操作的现有脚本,但从 .NET 4.0 升级到 .NET 4.5.1 后,该脚本不再有效。我认为这是由于这些 .NET 版本中的默认清单哈希算法从 sha1 更改为 sha256。

脚本的相关部分很小:

using Microsoft.Build.Tasks.Deployment.ManifestUtilities;
// This comes from Microsoft.Build.Tasks.v12.0.dll

public class Program
    {
        public static void Main(string[] args)
            {
                // set up...

                DeployManifest manifest= ManifestReader.ReadManifest(manifestPath, true) as DeployManifest;

                // I perform some updates to the manifest...

                ManifestWriter.WriteManifest(manifest);
            }
    }
}

即使我只是简单地读取清单并再次写出来,而不进行任何更新,DigestMethod 算法也会从 sha256 更改为 sha1,如下面的清单文件所示:

原始清单:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
  <assemblyIdentity name="program.application" version="1.9.9.10" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="amd64" xmlns="urn:schemas-microsoft-com:asm.v1" />
  <description asmv2:publisher="me" asmv2:product="program (dev)" xmlns="urn:schemas-microsoft-com:asm.v1" />
  <deployment install="true" mapFileExtensions="true" />
  <compatibleFrameworks xmlns="urn:schemas-microsoft-com:clickonce.v2">
    <framework targetVersion="4.5.1" profile="Full" supportedRuntime="4.0.30319" />
  </compatibleFrameworks>
  <dependency>
    <dependentAssembly dependencyType="install" codebase="Application Files\program_1_9_9_10\program.exe.manifest" size="44259">
      <assemblyIdentity name="program.exe" version="1.9.9.10" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="amd64" type="win32" />
      <hash>
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
        <dsig:DigestValue>0R79PRqWqhrE60GSHC/rE2WczQ4jqxCKBGr4lsjS4ZE=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
</asmv1:assembly>

重写清单:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
  <assemblyIdentity name="program.application" version="1.9.9.10" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="amd64" xmlns="urn:schemas-microsoft-com:asm.v1" />
  <description asmv2:publisher="me" asmv2:product="program (dev)" xmlns="urn:schemas-microsoft-com:asm.v1" />
  <deployment install="true" mapFileExtensions="true" />
  <dependency>
    <dependentAssembly dependencyType="install" codebase="Application Files\program_1_9_9_10\program.exe.manifest" size="44259">
      <assemblyIdentity name="program.exe" version="1.9.9.10" publicKeyToken="0000000000000000" language="neutral" processorArchitecture="amd64" type="win32" />
      <hash>
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>0R79PRqWqhrE60GSHC/rE2WczQ4jqxCKBGr4lsjS4ZE=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
  <compatibleFrameworks xmlns="urn:schemas-microsoft-com:clickonce.v2">
    <framework targetVersion="4.5.1" profile="Full" supportedRuntime="4.0.30319" />
  </compatibleFrameworks>
</asmv1:assembly>

注意两者之间的区别是 dsig:DigestMethod 元素中从 sha256 到 sha1 的变化。奇怪的是,DigestValue 没有改变。当我尝试 运行 已部署的应用程序时,这最终会导致错误,如“"xxxx has a different computed hash than specified in manifest."

我在这里展示了部署清单,但我看到应用程序清单也发生了同样的效果。

我想如果我能用 sha256 哈希写出清单,它就会解决我的问题。有谁知道如何做到这一点?任何建议将不胜感激。

我能够通过使用 Mage.exe rather than ManifestUtilities 获得正确的哈希值。

Mage.exe 有 -Algorithm 标志来选择哈希算法:

// -Algorithm <sha256RSA|sha1RSA>  -a
//     Specifies the algorithm to generate digests.
//     Example:
//        -Algorithm sha1RSA

我用来更新 .NET 4.5 ClickOnce 清单(包括签名)的整个过程是:

// Update the application manifest
// (I first had to strip the .deploy extensions from all the files referenced in the manifest for the mage tool to work)
mage -Update <applicationManifest> -Algorithm sha256RSA -CertFile <certificate > -Password <password>
// Then I replaced the .deploy extensions

// Update the deployment manifest (I didn't need to replace any .deploy extensions for this)
 mage -Update <deploymentManifest> -AppManifest <applicationManifest>
 -Algorithm sha256RSA -CertFile <certificate> -Password <password>

在我的项目文件夹中包含 mage.exe 并将 'Copy to output directory' 设置为 'Copy always' 之后,我使用此方法从 C# 运行 mage.exe。

    private static void RunMage(string arguments)
    {
        var startInfo = new ProcessStartInfo
        {
            FileName = "mage.exe",
            Arguments = arguments,
            UseShellExecute = false,
            RedirectStandardOutput = true,
        };

        using (Process mage = Process.Start(startInfo))
        {
            while (!mage.StandardOutput.EndOfStream)
            {
                Console.Out.WriteLine(mage.StandardOutput.ReadLine());
            }
            mage.WaitForExit();
        }
    }

这个 link 有助于弄清楚如何处理法师:http://www.nullskull.com/a/1540/update-configuration-of-a-clickonce-wpf-application-using-mage-or-mageui.aspx

我遇到了同样的问题并通过使用让您指定目标框架版本的重载简单地解决了它:

ManifestWriter.WriteManifest(manifest, manifestPath, "4.5.1");