XmlElement 的 Xml 签名无法验证

2023-12-06

我提前为相当长的代码块表示歉意,但这是我可以生成的最小的可编译示例。我已经省略了原始代码中的所有错误检查。我正在使用 Visual Studio 2012 和 .NET 4.5,尽管这对于 4.5 来说并不是什么新鲜事,但它应该适用于任何版本。

我正在尝试对 XML 文档的元素进行签名以防止它们被篡改。我不想保护整个文档,而只想保护某些元素。甚至可能具有不同键的不同元素。

但是,当我签署三个示例元素并尝试验证它们时,第一个总是验证,其他两个则失败。更糟糕的是,如果我在签名后修改它,第一个甚至会成功。我用谷歌搜索了很多,阅读了很多教程,甚至在这里问了一个理论问题,但我不知道我做错了什么。有人能发现我的错误吗?

注意:我非常乐意为解决此问题的任何人提供与周五问题相同的赏金。

该证书是通过执行以下命令创建的:

“C:\ Program Files(x86)\ Microsoft SDKs \ Windows \ v7.1A \ Bin \ makecert”-r -pe -n“CN = XMLDSIG_Test”-b 01/01/2013 -e 01/01/2014 -sky签名-ss我的

测试 xml 文件是:

<?xml version="1.0" encoding="utf-8" ?>
<PackageRoot>
  <Package>
    <Changes >
     <Change/>
    </Changes>
  </Package>
  <Package>
    <Changes>
     <Change/>
     <Change/>
    </Changes>
  </Package>
  <Package>
    <Changes>
     <Change/>
     <Change/>
     <Change/>
    </Changes>
  </Package>
</PackageRoot>

用于签名和验证的代码:

namespace SOExample
{
  using System;
  using System.Security.Cryptography.X509Certificates;
  using System.Security.Cryptography.Xml;
  using System.Xml;

  public static class Program
  {
    public static void Sign(this XmlElement element, X509Certificate2 certificate)
    {
        var identifier = Guid.NewGuid().ToString();

        element.SetAttribute("Id", identifier);

        var signedXml = new SignedXml(element) { SigningKey = certificate.PrivateKey };

        var reference = new Reference("#" + identifier);

        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());

        signedXml.AddReference(reference);

        signedXml.ComputeSignature();

        var xmlDigitalSignature = signedXml.GetXml();

        element.AppendChild(element.OwnerDocument.ImportNode(xmlDigitalSignature, true));
    }

    public static bool VerifySignature(this XmlElement element, X509Certificate2 certificate)
    {
      var signedXml = new SignedXml(element);

      XmlNodeList nodeList = element.GetElementsByTagName("Signature");

      if (nodeList.Count != 1) return false;

      signedXml.LoadXml((XmlElement)nodeList[0]);

      return signedXml.CheckSignature(certificate, true);
    }

    public static void Main()
    {
        var xmlDoc = new XmlDocument { PreserveWhitespace = true };

        xmlDoc.Load("ExamplePackage.xml");

        var certificate = GetCertificateBySubject("CN=XMLDSIG_Test");

        foreach (XmlElement root in xmlDoc.GetElementsByTagName("PackageRoot"))
        {
          foreach (XmlElement package in root.GetElementsByTagName("Package"))
          {
            package.Sign(certificate);
          }
        }

        xmlDoc.Save("test_signed.xml");

        Console.WriteLine("XML file signed.");
        Console.WriteLine("Press any key to verify");
        Console.ReadLine();

        var signedDoc = new XmlDocument();

        signedDoc.Load("test_signed.xml");

        foreach (XmlElement root in xmlDoc.GetElementsByTagName("PackageRoot"))
        {
          foreach (XmlElement package in root.GetElementsByTagName("Package"))
          {
            Console.Write("Verifying Package " + package.GetAttribute("Id"));
            var success = package.VerifySignature(certificate);
            Console.WriteLine(success ? " successful!" : " failed!");
          }
        }

        Console.WriteLine("Done.");
        Console.ReadLine();
    }

    private static X509Certificate2 GetCertificateBySubject(string certificateSubject)
    {
      var store = new X509Store("My", StoreLocation.CurrentUser);

      store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

      foreach (X509Certificate2 c in store.Certificates)
      {
        if (c.Subject == certificateSubject)
        {
          store.Close();
          return c;
        }
      }

      store.Close();
      return null;
    }
  }
}

您的测试代码中有一个错误。第二个 foreach 再次循环xmlDoc代替signedDoc。修复此问题将导致所有节点都失败。
为什么他们会失败我还不知道。


我无法找出为什么他们的代码失败,但我找到了一种让它工作的方法。 区别:所有签名都是根元素的直接子元素:

public static void Main()
{

    // ...

    var signedDoc = new XmlDocument { PreserveWhitespace = true };

    signedDoc.Load("test_signed.xml");

    foreach (XmlElement root in signedDoc.GetElementsByTagName("PackageRoot"))
    {
        foreach (XmlElement signature in root.GetElementsByTagName("Signature"))
        {
            var success = signature.VerifySignature(certificate);
            Console.WriteLine(success ? " successful!" : " failed!");
        }
    }

    Console.WriteLine("Done.");
    Console.ReadLine();
}

public static void Sign(this XmlElement element, X509Certificate2 certificate)
{
    var identifier = Guid.NewGuid().ToString("N");
    element.SetAttribute("Id", identifier);

    var signedXml = new SignedXml(element) { SigningKey = certificate.PrivateKey };
    signedXml.AddReference(new Reference("#" + identifier));
    signedXml.ComputeSignature();

    var xmlDigitalSignature = signedXml.GetXml();

    element.OwnerDocument.DocumentElement.AppendChild(
        element.OwnerDocument.ImportNode(xmlDigitalSignature, true));
}

public static bool VerifySignature(this XmlElement element, X509Certificate2 certificate)
{
    var signedXml = new SignedXml(element.OwnerDocument);
    signedXml.LoadXml(element);

    return signedXml.CheckSignature(certificate, true);
}

需要注意的一个重要细节:PreserveWhitespace需要设置为true for signedDoc, too.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XmlElement 的 Xml 签名无法验证 的相关文章

  • 使用php将文本文件转换为xml?

    data txt ha15rs 250 home2 gif 2 ha36gs 150 home3 gif 1 ha27se 300 home4 gif 4 ha4678 200 home5 gif 5 我想使用 php 使用 simplex
  • boost::multi_index_container 复合键中的 equal_range 与比较运算符

    我正在尝试从多索引容器查询结果 其中值类型是三个元素的结构 第一个值已给出 但第二个和第三个值必须大于或小于查询参数 经过搜索后 我发现必须实现自定义密钥提取器 并且这里的一些链接建议相同 但我无法实现它 boost multi index
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐

  • Google 地图:为什么我会收到referer-not-allowed-map-error? [关闭]

    Closed 这个问题需要调试细节 目前不接受答案 我有一个 Android 应用程序 在 Play 商店之外 它使用带有 Javascript 的 HTML 页面来调用 Google 地图 我得到一个referer not allowed
  • 如何向服务器套接字写入字节

    我正在编写一个java套接字程序来从服务器读取数据 我无法控制服务器 下面是约定的协议 2字节 幻数 2字节 数据长度 N 字节 ASCII 字符串数据有效负载 幻数和数据长度的大端序 例如 如果我的请求是 command 1 getuse
  • 如果 value 中的 a 值等于 R 中的上一行,则删除整行

    我是 R 编程新手 需要帮助根据单列的值删除整行 如果单列中的值等于前一行的值 我想删除该行 以下是我的数据 x id x timestamp x count 71 1 1435114605 61 72 1 1435114606 61 73
  • WordPress自定义文件在页面上传

    我目前正在使用此代码进行 PHP 文件上传 直接在 WordPress 页面上找到
  • 徽标/图像未显示在shinyapps.io 上

    我的徽标正在显示本地 R 闪亮 但是当我将应用程序部署到闪亮应用程序io 在这里检查应用程序 标志显示一张空白图片 有人可以帮我吗 The blank logo My code library dplyr library shiny lib
  • Highcharts 多线图

    这是我的小提琴 http jsfiddle net a4UQf Code function container highcharts title text Monthly Average Temperature x 20 center su
  • 在 Django 中序列化外键对象

    我一直致力于在 Django 中开发一些 RESTful 服务 以便与 Flash 和 Android 应用程序一起使用 开发服务接口非常简单 但我在序列化具有外键和多对多关系的对象时遇到了问题 我有一个这样的模型 class Artifa
  • python脚本杀死并启动自身

    我想在一小时内达到指定时间时启动 python 脚本的新实例并杀死当前实例 python 脚本使用 crontab 在启动时自动启动 无限 while 循环读取数据 如果在第 59 秒 30 和第 59 秒 59 之间有数据传入 则文件将关
  • PyRhO 似乎在安装时破坏了我的其他库

    我正在运行 Ubuntu 18 10 和 Python 3 6 并且已经使用这台笔记本电脑和常见的 Python 库 numpy scipy matplotlib 几个月了 没有任何问题 我用了 pip3 install pyrho 安装P
  • Phalcon 和 nginx - 框架仅运行 indexController

    我正在使用 Phalcon 和 Nginx 但遇到了问题 当我去http myapp dev segmentationPhalcon 应该运行 SegmentationController 及其 indexAction 方法 但相反 Pha
  • 使用 Pandas 进行数据分组

    我有一个数据框 Name Subset Type System A00 IU00 A OP A A00 IT00 PP A B01 IT 01A PP B B01 IU OP B B03 IM 09 B LP A B03 IM03A OP
  • .net core 依赖注入发生“无法找到包“enc.dll”的编译库位置”错误

    我正在使用 asp net core mvc 构建一个网站 对于登录 我添加了 enc dll 文件的依赖项 该文件只是加密 解密用户信息 我用 enc dll 文件创建了一个 Seeder 类 该类具有密钥属性并使用密钥进行加密 解密 然
  • 关于多表数据库设计问题的评论

    我有桌子 Articles Recipes Notifications Photos 我需要实现 用户评论 功能 如Facebook 我应该制作表格吗 ArticleComments RecipesComments等1 n关系 或者创建一个
  • 为什么我的 ObservableCollection 序列化不起作用?

    我正在尝试序列化和反序列化这个 ObservableCollection public class DataCollection ObservableCollection
  • 使用 jQuery-UI 的文件输入按钮样式

    我正在使用 jQuery UI 我注意到 输入文件 按钮
  • AIR 将服务器托管的 swf 加载到同一沙箱中

    我正在开发一个 AIR 应用程序 需要加载一个 swf 始终来自本地主机 它将访问其父级中的一些方法 反之亦然 不过 我并不关心在桌面应用程序中打开巨大的安全漏洞 我一直在到处寻找 但每次实施都遇到困难 我当前的设置加载到 swf 中并播放
  • R bnlearn Grow-Shrink结构学习返回无向图

    Nagarajan 等人 书 R 中的贝叶斯网络 奥莱利 2013 年 第 14 页 35 说 当我获取 R bnlearn 包的标记数据集并要求通过编写使用增长 收缩实现来学习结构时 library bnlearn data marks
  • 如何在 LIBGDX 游戏中完全禁用多窗口支持

    我在渲染线程中分配了很多内存 并且我已经traced多窗口支持的原因很奇怪 因为我有我的手机禁用了此功能 我已将以下内容添加到 AndroidManifest 基于this 应用程序标记内的代码 但运气不好 我仍然得到不需要的内存分配 仅当
  • JSON.stringify 大对象优化

    我想使用以下方法将大型 JSON 对象转换为字符串JSON stringify 但由于对象的大小 我得到了一个错误 lt Last few GCs gt 20817 0x2cc2830 295727 ms Scavenge 1335 8 1
  • XmlElement 的 Xml 签名无法验证

    我提前为相当长的代码块表示歉意 但这是我可以生成的最小的可编译示例 我已经省略了原始代码中的所有错误检查 我正在使用 Visual Studio 2012 和 NET 4 5 尽管这对于 4 5 来说并不是什么新鲜事 但它应该适用于任何版本