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

幻夢星雲
发布: 2025-08-01 18:36:02
原创
143人浏览过

xml签名通过在xml文档中添加“数字指纹”来确保其完整性和来源可靠性。1. 其核心是元素,包含(含等子元素)、;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文档可能如下所示(简化版):


  <SignedInfo>
    
    
    
      <Transforms>
        
      
      
      <DigestValue>...
    
  
  <SignatureValue>...
  <KeyInfo>
    <X509Data>
      ...
    
  

<message>Hello, world!</message>
登录后复制

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

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签名来保证消息的完整性和身份验证。

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

以上就是XML签名(XML Signature)的基本结构和作用是什么?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号