JAXB Unmarshall 正在删除数字签名中的回车

问题描述 投票:0回答:2

我正在使用以下依赖项进行 XML 签名:

<dependency>
        <groupId>jakarta.activation</groupId>
        <artifactId>jakarta.activation-api</artifactId>
        <version>2.1.1</version>
    </dependency>
    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
        <version>4.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>4.0.0</version>
        <scope>runtime</scope>
    </dependency>

我能够使用信封成功生成签名:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>xndyhbkzbLreG3cxXqa5Q5RdKEavhrc2Fvd0Wsc+Oug=</DigestValue></Reference></SignedInfo><SignatureValue>No+gNx3Hwd3WfH0v6OZ8uptWVyneZT55CfUrxMnW33a87egeiImwsyepZZXTbya0ifzX1iOtyyaf&#13;
OwEDxTFhf/FCPH6Nj9KCFNabZddwN38tCOkkAkYdkKdW14AM80HU/9yPIAMWytibbyd3AKVuRQgd&#13;
+qkf1/V8J1Ki1LNO4tbPzxqpNMpRmpH/469lgMHEz9Xy1DnJ154E+H2OWNufooGwwpV/pMbM8RzY&#13;

当我尝试这样验证时,它起作用了:

 signature.sign(dsc);

 System.out.println("doc: " + getStringFromDocument(doc) + " validate: " + validate(doc));

但是,当我尝试解组签名以便将其分配给 DTO 时,它失败了:

JAXBElement<?> root = XmlUtils.getUnMarshaller(xml.getClass().getName()).unmarshal(getStreamSource(doc), xml.getClass());

xml.setSignature(((SignXml<?>) root.getValue()).getSignature());

在比较文档中生成的签名和解组的签名时,我发现字符 被删除:

医生

<SignatureValue>No+gNx3Hwd3WfH0v6OZ8uptWVyneZT55CfUrxMnW33a87egeiImwsyepZZXTbya0ifzX1iOtyyaf&#13;
    OwEDxTFhf/FCPH6Nj9KCFNabZddwN38tCOkkAkYdkKdW14AM80HU/9yPIAMWytibbyd3AKVuRQgd&#13;
    +qkf1/V8J1Ki1LNO4tbPzxqpNMpRmpH/469lgMHEz9Xy1DnJ154E+H2OWNufooGwwpV/pMbM8RzY&#13;
    +yVSjKguJr9UWKWswQkD0XUasVXBZckjlYxZL24ZwD1rwU7wP2itOli3VH9ReC3CA33YOUMT0ktP&#13;

解组

<ns2:SignatureValue>No+gNx3Hwd3WfH0v6OZ8uptWVyneZT55CfUrxMnW33a87egeiImwsyepZZXTbya0ifzX1iOtyyafOwEDxTFhf/FCPH6Nj9KCFNabZddwN38tCOkkAkYdkKdW14AM80HU/9yPIAMWyt

正如我们所看到的,签名是相同的,唯一的区别是字符 被删除了。

我试着查看 EscapeCharacter 解决方案,但它似乎只在旧的 JAXB 实现中可用。有什么想法吗?

xml jakarta-ee marshalling digital-signature unmarshalling
2个回答
0
投票

性格 是回车 (CR) 字符的转义序列。似乎这个字符在解组过程中被删除,这导致签名不同。

一个解决方案可能是显式添加 字符返回到未编组的签名值。一种方法是创建一个自定义 XMLAdapter,它将添加 解组期间将字符添加到签名值。

这是一个如何创建自定义 XMLAdapter 的示例:

public class SignatureValueAdapter extends XmlAdapter<String, String> {
    @Override
    public String unmarshal(String value) throws Exception {
        return value + "&#13;";
    }

    @Override
    public String marshal(String value) throws Exception {
        return value;
    }
}

这个适配器只是添加了 解组期间签名值末尾的字符。要使用此适配器,您需要使用 @XmlJavaTypeAdapter(SignatureValueAdapter.class) 注释 DTO 中的 SignatureValue 字段。

举个例子:

@XmlRootElement(name = "SignXml")
@XmlAccessorType(XmlAccessType.FIELD)
public class SignXml<T> {
    @XmlElement(name = "Signature")
    @XmlJavaTypeAdapter(SignatureValueAdapter.class)
    private String signature;

    // getters and setters
}

通过将 @XmlJavaTypeAdapter(SignatureValueAdapter.class) 注释添加到签名字段,自定义 XMLAdapter 将在解组期间使用以添加 字符返回签名值。


0
投票

一个可能的解决方案是将 CR 字符的所有实例替换为数据中不存在的不同字符或字符串。例如,您可以替换“的所有实例 “ 和 ” " 在编组之前,然后替换 " 的所有实例 “ 和 ” " 解组后。这将确保作为数据一部分的 CR 字符被正确保留。

或者,您可以使用不依赖换行符的不同编码格式,例如二进制编码或 JSON。这些格式旨在处理复杂的数据结构,并且不太可能受到换行问题的影响。

© www.soinside.com 2019 - 2024. All rights reserved.