You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WS Security中XML签名STR-Transform算法原理及签名实现问询

STR-Transform 工作原理与WS Security场景下的XML签名实现指南

我来帮你拆解STR-Transform的工作原理,以及针对你这个X509 Thumbprint场景的具体实现步骤——我之前处理过类似的WS-Security签名需求,踩过不少坑,应该能帮到你。


一、STR-Transform 核心工作原理

STR-Transform(全称Security Token Reference Transform)是OASIS WS-Security规范专门为SecurityTokenReference(STR)节点设计的转换算法。

在WS-Security场景中,STR用来引用签名用的安全令牌(比如你的X509证书),但不同系统生成的STR可能有细微格式差异:比如命名空间前缀不同、多了无关空白、带了非必要属性。这些小差异会导致签名时计算的摘要不一致,最终验证失败。

STR-Transform的核心作用就是:

  • 提取STR中与令牌身份绑定的核心信息,生成一个标准化的STR片段
  • 对这个标准化片段应用指定的XML规范化算法(比如你用的exc-c14n#),确保签名和验证时使用完全一致的输入,彻底解决格式差异问题

二、针对X509 Thumbprint STR的签名分步算法

结合你提供的签名结构(用X509证书Thumbprint引用,需要对STR本身签名),具体步骤如下:

步骤1:定位目标STR节点

首先找到消息中带有wsu:Id="str_U1sjQ5j8JtKnObLk"的<wsse:SecurityTokenReference>节点——这就是你要签名的核心对象:

<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="str_U1sjQ5j8JtKnObLk">
  <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">h5...ow=</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>

步骤2:执行STR-Transform生成标准化STR片段

根据WS-Security规范,针对X509 Thumbprint类型的STR,STR-Transform会生成一个仅保留核心标识信息的新STR元素:

  • 保留原STR的wsse11:TokenType属性(用来明确令牌是X509v3类型)
  • 完整保留<wsse:KeyIdentifier>子元素(包含EncodingType、ValueType和Thumbprint值,这是绑定证书的核心)
  • 移除所有非必要属性(比如wsu:Id,因为签名引用已经通过URI关联,转换后的片段不需要这个ID)
  • 确保命名空间声明完整且符合规范

转换后的中间STR片段大致如下:

<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">
  <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">h5...ow=</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>

步骤3:应用指定的规范化算法

对上述标准化STR片段,应用你指定的http://www.w3.org/2001/10/xml-exc-c14n#(Exclusive XML Canonicalization)算法。这个步骤会统一处理XML的空白、命名空间前缀、属性顺序等,确保跨系统的一致性——这一步是避免验证失败的关键。

步骤4:计算摘要并生成签名引用

对规范化后的字节流,使用http://www.w3.org/2001/04/xmlenc#sha256摘要算法计算出DigestValue,然后把这个值填入<dsig:Reference>节点中,就得到了你提供的签名结构里的STR引用部分。

步骤5:完成整体签名

把所有Reference(包括Timestamp和STR的)的DigestValue整合到<dsig:SignedInfo>中,使用http://www.w3.org/2000/09/xmldsig#rsa-sha1算法对整个SignedInfo进行签名,生成<dsig:SignatureValue>。


三、Java实现示例(使用Apache Santuario)

Apache Santuario是Java生态中处理XML签名的成熟库,以下是针对你场景的简化实现:

import org.apache.xml.security.Init;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.FileInputStream;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

public class STRTransformSignature {
    public static void main(String[] args) throws Exception {
        // 初始化XML Security库(必须先执行)
        Init.init();

        // 加载你的SOAP消息文档
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true); // 必须开启命名空间支持
        Document soapDoc = dbf.newDocumentBuilder().parse(new FileInputStream("your-soap-message.xml"));

        // 定位到要签名的STR节点(通过wsu:Id)
        Element strNode = (Element) soapDoc.getElementById("str_U1sjQ5j8JtKnObLk");

        // 创建XMLSignature实例,指定签名算法和默认规范化方法
        XMLSignature signature = new XMLSignature(soapDoc, "", XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
        signature.getSignedInfo().setCanonicalizationMethod(Constants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

        // 配置STR-Transform
        Transforms transforms = new Transforms(soapDoc);
        // 添加STR-Transform算法
        Element strTransform = transforms.addTransform(Constants.TRANSFORM_STR_TRANSFORM);
        // 设置TransformationParameters:指定规范化算法
        Element params = soapDoc.createElementNS(Constants.NS_WSSE, "wsse:TransformationParameters");
        Element c14nMethod = soapDoc.createElementNS(Constants.SignatureSpecNS, "dsig:CanonicalizationMethod");
        c14nMethod.setAttribute("Algorithm", Constants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
        params.appendChild(c14nMethod);
        strTransform.appendChild(params);

        // 添加STR的Reference,指定摘要算法
        signature.addReference("#str_U1sjQ5j8JtKnObLk", transforms, Constants.ALGO_ID_DIGEST_SHA256);

        // 添加其他Reference(比如Timestamp,这里省略,你可以参考现有逻辑添加)
        // signature.addReference("#Timestamp_C1Ih1AB1vpPT5uG2", ...);

        // 将Signature节点添加到SOAP的Security头中(假设Security头已存在)
        Element securityHeader = (Element) soapDoc.getElementsByTagNameNS(Constants.NS_WSSE, "Security").item(0);
        securityHeader.appendChild(signature.getElement());

        // 加载你的X509私钥和证书(这里需要你自己实现加载逻辑)
        PrivateKey privateKey = loadYourPrivateKey();
        X509Certificate cert = loadYourX509Cert();

        // 执行签名
        signature.sign(privateKey);

        // 输出签名后的SOAP文档(这里可以添加代码将Document转为XML字符串)
        printDocument(soapDoc);
    }

    // 以下是占位方法,需要你自己实现
    private static PrivateKey loadYourPrivateKey() { /* 加载私钥逻辑 */ return null; }
    private static X509Certificate loadYourX509Cert() { /* 加载证书逻辑 */ return null; }
    private static void printDocument(Document doc) { /* 输出XML文档逻辑 */ }
}

四、关键注意事项

  • 命名空间必须严格一致:wsse、wsse11、wsu、dsig的命名空间URI必须和规范完全匹配,不能有拼写错误
  • TransformationParameters不能少:STR-Transform必须指定规范化算法参数,否则签名和验证会直接失败
  • STR的wsu:Id必须唯一:确保每个STR的ID在整个SOAP消息中是唯一的,Reference的URI要准确指向这个ID

内容的提问来源于stack exchange,提问作者Guillermo Gutiérrez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:30:56