0

0

XML签名(XML Signature)的基本结构和作用是什么?

幻夢星雲

幻夢星雲

发布时间:2025-08-01 18:36:02

|

692人浏览过

|

来源于php中文网

原创

xml签名通过在xml文档中添加“数字指纹”来确保其完整性和来源可靠性。1. 其核心是<signature>元素,包含< signedinfo>(含<canonicalizationmethod>、<signaturemethod>、<reference>等子元素)、<signaturevalue>和<keyinfo>;2. 支持三种签名模式:enveloped signature(签名嵌入文档内部)、enveloping signature(签名包裹内容)、detached signature(签名与内容分离);3. 可使用java的javax.xml.crypto、python的xmlsec、c#的system.security.cryptography.xml等库实现签名生成与验证;4. 广泛应用于电子发票、电子病历、金融交易、软件更新和web services安全等场景,确保数据不可篡改和身份可信。选择强哈希算法(如sha256)和足够密钥长度并定期更新密钥是保障安全的关键措施。

XML签名(XML Signature)的基本结构和作用是什么?

XML签名,简单来说,就是给XML文档加上一个“数字指纹”,确保文档的完整性和来源可靠性。它能防止文档被篡改,并验证签名者的身份。

解决方案:

XML签名的核心在于

<Signature>
元素,它包含了签名所需的全部信息。让我们逐步拆解它的结构和作用:

  1. <SignedInfo>
    : 这是签名信息的摘要,也是实际被签名的部分。它包含了:

    • <CanonicalizationMethod>
      : 指定规范化算法。规范化是为了消除XML文档在不同环境下可能存在的差异(比如空格、属性顺序等),确保签名的一致性。常用的算法是
      http://www.w3.org/2001/10/xml-exc-c14n#
      (Exclusive Canonicalization)。

    • <SignatureMethod>
      : 指定签名算法。例如,
      http://www.w3.org/2001/09/xmldsig#rsa-sha1
      表示使用RSA算法和SHA1哈希函数。但请注意,SHA1由于安全性问题,现在已经不推荐使用,更安全的选择包括SHA256或SHA512。

    • <Reference>
      : 包含一个或多个引用,指向被签名的资源。每个
      <Reference>
      元素都有:

      • URI
        : 指向被签名的资源。如果为空,表示签名的是整个文档。

      • <Transforms>
        : 指定在计算摘要之前对资源进行的转换。例如,可以用来提取文档的特定部分。

      • <DigestMethod>
        : 指定摘要算法。例如,
        http://www.w3.org/2001/04/xmlenc#sha256
        表示使用SHA256哈希函数。

      • <DigestValue>
        : 被签名资源的摘要值。

  2. <SignatureValue>
    : 包含实际的签名值。这是对
    <SignedInfo>
    元素进行签名算法处理后的结果。

  3. <KeyInfo>
    : 包含签名者的公钥或证书信息,用于验证签名。它可以包含:

    • <X509Data>
      : 包含X.509证书。

    • <KeyValue>
      : 包含公钥。

    • <RetrievalMethod>
      : 指向包含密钥信息的外部资源。

举个例子,假设我们要签名一个简单的XML文档:

<message>Hello, world!</message>

签名后的XML文档可能如下所示(简化版):

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
  <SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <SignatureMethod Algorithm="http://www.w3.org/2001/09/xmldsig#rsa-sha1"/>
    <Reference URI="">
      <Transforms>
        <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped"/>
      </Transforms>
      <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
      <DigestValue>...</DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue>...</SignatureValue>
  <KeyInfo>
    <X509Data>
      <X509Certificate>...</X509Certificate>
    </X509Data>
  </KeyInfo>
</Signature>
<message>Hello, world!</message>

XML签名有哪些不同的签名模式?

轻舟办公
轻舟办公

基于AI的智能办公平台

下载

XML签名支持多种签名模式,主要区别在于

<Signature>
元素在XML文档中的位置:

  • Enveloped Signature (信封签名):

    <Signature>
    元素是XML文档的根元素,它“包裹”着被签名的内容。上面的例子就是Enveloped Signature。

  • Enveloping Signature (内含签名):

    <Signature>
    元素包含被签名的内容。 也就是说,
    <Signature>
    元素本身是根元素,并且它内部包含了要签名的XML片段。

  • Detached Signature (分离签名):

    <Signature>
    元素和被签名的内容是分离的。
    <Signature>
    元素通过
    URI
    属性指向外部的XML文档。

选择哪种签名模式取决于具体的需求。Enveloped Signature 适合签名整个XML文档,而 Detached Signature 适合签名外部资源。

如何使用编程语言生成和验证XML签名?

许多编程语言都提供了XML签名库,可以简化签名和验证过程。

  • Java: Java的内置库

    javax.xml.crypto
    提供了XML签名API。你可以使用它来创建、验证XML签名。 Apache Santuario - XML Security for Java 也是一个流行的选择,提供了更丰富的功能和更好的性能。

    // 使用 Java XML Digital Signature API 签名 XML 文档
    import javax.xml.crypto.*;
    import javax.xml.crypto.dsig.*;
    import javax.xml.crypto.dsig.dom.DOMSignContext;
    import javax.xml.crypto.dsig.keyinfo.*;
    import javax.xml.crypto.dsig.spec.*;
    import java.io.*;
    import java.security.*;
    import java.security.cert.Certificate;
    import java.util.*;
    import javax.xml.parsers.DocumentBuilderFactory;
    import org.w3c.dom.Document;
    
    public class XMLSigner {
    
        public static void main(String[] args) throws Exception {
            // 1. 加载 XML 文档
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            Document doc = dbf.newDocumentBuilder().parse(new File("document.xml"));
    
            // 2. 创建密钥对
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();
    
            // 3. 创建 XMLSignatureFactory
            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
    
            // 4. 创建 Reference 对象
            Reference ref = fac.newReference
                ("", fac.newDigestMethod(DigestMethod.SHA256, null),
                 Collections.singletonList
                 (fac.newTransform
                  (Transform.ENVELOPED, (TransformParameterSpec) null)),
                 null, null);
    
            // 5. 创建 SignedInfo 对象
            SignedInfo signedInfo = fac.newSignedInfo
                (fac.newCanonicalizationMethod
                 (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
                  (C14NMethodParameterSpec) null),
                 fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null),
                 Collections.singletonList(ref));
    
            // 6. 创建 KeyInfo 对象
            KeyInfoFactory kif = fac.getKeyInfoFactory();
            List<Object> x509Content = new ArrayList<>();
            x509Content.add(publicKey);
            KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(kif.newKeyValue(publicKey)));
    
            // 7. 创建 Signature 对象
            XMLSignature signature = fac.newXMLSignature(signedInfo, keyInfo);
    
            // 8. 创建 DOMSignContext 并签名
            DOMSignContext dsc = new DOMSignContext(privateKey, doc.getDocumentElement());
            signature.sign(dsc);
    
            // 9. 输出签名后的 XML 文档
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new javax.xml.transform.dom.DOMSource(doc), new javax.xml.transform.stream.StreamResult(System.out));
        }
    }
  • Python:

    xmlsec
    库是一个不错的选择。它提供了对XML签名和加密的全面支持。

    import xmlsec
    from lxml import etree
    
    # 1. 加载 XML 文档
    with open("document.xml", "r") as f:
        xml_data = f.read()
    root = etree.fromstring(xml_data.encode('utf-8'))
    
    # 2. 加载密钥
    with open("private.pem", "r") as f:
        private_key = f.read()
    
    # 3. 创建 XML Security Context
    ctx = xmlsec.DSigCtx()
    
    # 4. 加载密钥到 Context
    key = xmlsec.Key.from_memory(private_key, xmlsec.KeyDataFormat.PEM)
    ctx.sign_key = key
    
    # 5. 找到 Signature 节点 (如果已经存在,否则创建)
    signature_node = xmlsec.tree.find_node(root, xmlsec.constants.NodeSignature)
    if signature_node is None:
        signature_node = xmlsec.template.create(root, xmlsec.constants.TransformExclC14N11, xmlsec.constants.SigRsaSha256)
        root.append(signature_node)
    
        ref = xmlsec.template.add_reference(signature_node, xmlsec.constants.TransformSha256, uri="");
        xmlsec.template.add_transform(ref, xmlsec.constants.TransformEnveloped)
    
        keyinfo = xmlsec.template.ensure_key_info(signature_node)
        xmlsec.template.add_key_name(keyinfo)
    
    # 6. 签名 XML 文档
    ctx.sign(signature_node)
    
    # 7. 输出签名后的 XML 文档
    print(etree.tostring(root, pretty_print=True).decode('utf-8'))
  • C# (.NET): .NET Framework 提供了

    System.Security.Cryptography.Xml
    命名空间,包含了XML签名相关的类。

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Cryptography.Xml;
    using System.Xml;
    
    public class XMLSigner {
    
        public static void Main(string[] args) {
            try {
                // 1. 加载 XML 文档
                XmlDocument doc = new XmlDocument();
                doc.Load("document.xml");
    
                // 2. 加载证书
                X509Certificate2 cert = new X509Certificate2("certificate.pfx", "password"); // 替换为你的证书路径和密码
    
                // 3. 创建 SignedXml 对象
                SignedXml signedXml = new SignedXml(doc);
                signedXml.SigningKey = cert.PrivateKey;
    
                // 4. 创建 Reference 对象
                Reference reference = new Reference();
                reference.Uri = ""; // 签名整个文档
    
                // 5. 添加转换
                XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
                reference.AddTransform(env);
    
                // 6. 将 Reference 添加到 SignedXml
                signedXml.AddReference(reference);
    
                // 7. 创建 KeyInfo 对象
                KeyInfo keyInfo = new KeyInfo();
                keyInfo.AddClause(new KeyInfoX509Data(cert));
    
                // 8. 将 KeyInfo 添加到 SignedXml
                signedXml.KeyInfo = keyInfo;
    
                // 9. 计算签名
                signedXml.ComputeSignature();
    
                // 10. 获取 XML 签名
                XmlElement xmlDigitalSignature = signedXml.GetXml();
    
                // 11. 将签名添加到 XML 文档
                doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
    
                // 12. 保存签名后的 XML 文档
                doc.Save("signed_document.xml");
    
                Console.WriteLine("XML 文档已成功签名并保存为 signed_document.xml");
            } catch (Exception e) {
                Console.WriteLine("发生错误: " + e.Message);
            }
        }
    }

这些示例代码展示了如何使用不同的编程语言和库来生成XML签名。验证过程类似,需要加载签名、提取公钥或证书,并使用相同的算法验证签名值。

XML签名在哪些场景下应用广泛?

XML签名在安全性要求较高的场景下应用广泛,例如:

  • 电子发票: 确保发票的真实性和完整性,防止篡改。

  • 电子病历: 保护患者隐私,防止病历被非法修改。

  • 金融交易: 确保交易数据的安全性和不可抵赖性。

  • 软件更新: 验证软件更新包的来源和完整性,防止恶意软件传播。

  • Web Services 安全: 在SOAP消息中使用XML签名来保证消息的完整性和身份验证。

选择合适的签名算法和密钥长度至关重要,并且需要定期更新密钥以应对新的安全威胁。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1950

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2120

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1180

2024.11.28

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

508

2023.08.14

apache是什么意思
apache是什么意思

Apache是Apache HTTP Server的简称,是一个开源的Web服务器软件。是目前全球使用最广泛的Web服务器软件之一,由Apache软件基金会开发和维护,Apache具有稳定、安全和高性能的特点,得益于其成熟的开发和广泛的应用实践,被广泛用于托管网站、搭建Web应用程序、构建Web服务和代理等场景。本专题为大家提供了Apache相关的各种文章、以及下载和课程,希望对各位有所帮助。

422

2023.08.23

apache启动失败
apache启动失败

Apache启动失败可能有多种原因。需要检查日志文件、检查配置文件等等。想了解更多apache启动的相关内容,可以阅读本专题下面的文章。

939

2024.01.16

Java 流式处理与 Apache Kafka 实战
Java 流式处理与 Apache Kafka 实战

本专题专注讲解 Java 在流式数据处理与消息队列系统中的应用,系统讲解 Apache Kafka 的基础概念、生产者与消费者模型、Kafka Streams 与 KSQL 流式处理框架、实时数据分析与监控,结合实际业务场景,帮助开发者构建 高吞吐量、低延迟的实时数据流管道,实现高效的数据流转与处理。

182

2026.02.04

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

507

2023.11.09

Python WebSocket实时通信与异步服务开发实践
Python WebSocket实时通信与异步服务开发实践

本专题聚焦 Python 在实时通信场景中的开发实践,系统讲解 WebSocket 协议原理、长连接管理、消息推送机制以及异步服务架构设计。内容包括客户端与服务端通信实现、连接稳定性优化、消息队列集成及高并发处理策略。通过完整案例,帮助开发者构建高效稳定的实时通信系统,适用于聊天应用、实时数据推送等场景。

7

2026.03.18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP数字签名与加密解密
PHP数字签名与加密解密

共12课时 | 1.4万人学习

最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号