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 签名无法验证 的相关文章

  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 如何锁定/密码保护 XML 文件?

    我在 XML 文件中读取和写入数据 我不希望其他人阅读该文件 所以我想为我的文件创建密码或锁定文件 我怎样才能做到这一点 如果不使用加密软件 则无法使用密码保护 XML 文件 XML 文件只是文本 但像 PGP 谷歌搜索 这样的程序应该可以
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐

  • 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 来说并不是什么新鲜事 但它应该适用于任何版本