XML签名如何工作?如何确保完整性?

来源:安卓APP网作者:新井头衔:网络博主
导读:本期聚焦于小伙伴创作的《XML签名如何工作?如何确保完整性?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《XML签名如何工作?如何确保完整性?》有用,将其分享出去将是对创作者最好的鼓励。

XML签名是基于XML格式的数字签名标准,用于对XML文档或文档中的部分内容生成数字签名,验证数据的来源合法性和内容完整性,广泛应用于Web服务、数据交换等场景。

XML签名如何工作?如何确保完整性?

XML签名的核心组成

一个标准的XML签名主要包含三个核心部分,各部分承担不同的功能:

  • SignedInfo:包含被签名的数据引用、签名算法、规范转换规则等信息,是签名计算的核心输入。
  • SignatureValue:对SignedInfo内容进行哈希和加密后得到的签名值,用于后续验证。
  • KeyInfo:可选部分,包含验证签名所需的公钥信息,方便接收方获取验证密钥。

XML签名的工作流程

1. 签名生成流程

签名生成方需要按照以下步骤完成XML签名的生成:

  1. 确定需要签名的XML内容,可以是整个文档,也可以是文档中的特定节点。
  2. 对被签名的内容进行规范转换,统一XML的编码、换行、属性顺序等格式,避免格式差异导致哈希值不同。
  3. 使用哈希算法(如SHA256)计算被签名内容的摘要值。
  4. 将摘要值、签名算法、引用信息等组装成SignedInfo元素。
  5. 使用发送方的私钥对SignedInfo元素进行加密,得到SignatureValue。
  6. 将SignedInfo、SignatureValue、KeyInfo等元素组装成完整的XML签名,插入到原XML文档中。

2. 签名验证流程

接收方收到带签名的XML文档后,验证流程如下:

  1. 从XML文档中提取SignedInfo、SignatureValue、KeyInfo等签名相关信息。
  2. 按照签名中指定的规范转换规则,重新计算被签名内容的摘要值。
  3. 使用发送方的公钥对SignatureValue进行解密,得到原始计算的SignedInfo摘要值。
  4. 对比解密得到的摘要值和重新计算的SignedInfo摘要值,如果一致则签名验证通过。

XML签名如何确保完整性

XML签名通过多层机制保障数据的完整性,避免数据在传输或存储过程中被篡改:

  • 哈希摘要校验:被签名的内容会先通过哈希算法生成固定长度的摘要,哪怕内容只修改一个字符,生成的摘要值都会完全不同,接收方重新计算摘要即可发现内容变化。
  • 私钥加密保护:SignedInfo包含被签名内容的引用和摘要信息,使用私钥加密后,任何对内容的篡改都会导致解密后的摘要和重新计算的摘要不匹配,验证无法通过。
  • 规范转换统一格式:签名过程会对XML内容进行规范转换,消除不同解析器对XML格式处理的差异,避免非内容修改导致的签名验证失败,同时保证只有内容本身的变化才会影响签名结果。

代码示例:Java实现XML签名生成与验证

以下是使用Java的XML签名API实现简单XML签名生成和验证的示例代码:

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class XmlSignatureDemo {
    // 生成XML签名
    public static void signXml(String xmlPath, String keyStorePath, String keyStorePass, String keyAlias, String keyPass) throws Exception {
        // 加载XML文档
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(xmlPath));
        
        // 加载密钥库获取私钥和证书
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(new FileInputStream(keyStorePath), keyStorePass.toCharArray());
        PrivateKey privateKey = (PrivateKey) ks.getKey(keyAlias, keyPass.toCharArray());
        X509Certificate cert = (X509Certificate) ks.getCertificate(keyAlias);
        
        // 创建签名工厂
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
        
        // 创建规范转换方法
        C14NMethod c14nMethod = fac.newC14NMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null);
        // 创建签名算法
        SignatureMethod signatureMethod = fac.newSignatureMethod(SignatureMethod.RSA_SHA256, null);
        // 创建摘要算法
        DigestMethod digestMethod = fac.newDigestMethod(DigestMethod.SHA256, null);
        
        // 创建对文档的引用
        List<Transform> transforms = new ArrayList<>();
        transforms.add(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
        Reference ref = fac.newReference("", digestMethod, transforms, null, null);
        List<Reference> refs = Collections.singletonList(ref);
        
        // 创建SignedInfo
        SignedInfo signedInfo = fac.newSignedInfo(c14nMethod, signatureMethod, refs);
        
        // 创建KeyInfo
        KeyInfoFactory kif = fac.getKeyInfoFactory();
        X509Data x509Data = kif.newX509Data(Collections.singletonList(cert));
        KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(x509Data));
        
        // 创建XML签名
        XMLSignature signature = fac.newXMLSignature(signedInfo, keyInfo);
        DOMSignContext signContext = new DOMSignContext(privateKey, doc.getDocumentElement());
        signature.sign(signContext);
        
        System.out.println("XML签名生成完成");
    }
    
    // 验证XML签名
    public static boolean validateXml(String xmlPath, String keyStorePath, String keyStorePass, String keyAlias) throws Exception {
        // 加载XML文档
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(xmlPath));
        
        // 加载密钥库获取公钥
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(new FileInputStream(keyStorePath), keyStorePass.toCharArray());
        PublicKey publicKey = ks.getCertificate(keyAlias).getPublicKey();
        
        // 查找签名节点
        NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
        if (nl.getLength() == 0) {
            throw new Exception("未找到XML签名节点");
        }
        
        // 创建验证上下文
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
        DOMValidateContext valContext = new DOMValidateContext(publicKey, nl.item(0));
        
        // 验证签名
        XMLSignature signature = fac.unmarshalXMLSignature(valContext);
        return signature.validate(valContext);
    }
}

常见问题说明

在实际使用XML签名时,需要注意以下几点:

  • 规范转换规则需要和接收方协商一致,否则容易出现签名验证失败的问题。
  • 私钥需要妥善保管,一旦私钥泄露,攻击者可以伪造合法的XML签名。
  • 如果只需要校验完整性不需要验证来源,也可以采用对称加密的方式生成签名,但安全性会低于非对称加密方案。

XML_signature完整性校验数字签名XML_加密修改时间:2026-06-14 22:57:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。