如何在Java中生成一个内部分离的XML签名?

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

我不明白如何将签名节点作为数据节点的兄弟节点。我找到的例子来自Oracle,但只涵盖了普通的分离签名,其中XML作为URI传递给Reference对象。

引用Oracle的例子。https:/docs.oracle.comjavase8docstechnotesguidessecurityxmldsigGenDetached.java。

java xml security pki xml-dsig
1个回答
0
投票

一种方法如下。

第一步 - 以字符串形式获取签名XML。

改变样本 GenDetached 在你的链接中的代码如下,所以输出的是一个字符串。

在类的底部做了如下修改。

// output the resulting document
OutputStream os = System.out;
//if (args.length > 0) {
//    os = new FileOutputStream(args[0]);
//} else {
//    os = System.out;
//}

// my changes, to write to a string:
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
StringWriter writer = new StringWriter();
trans.transform(new DOMSource(doc), new StreamResult(writer));
return writer.toString();

同时修改方法签名,使其返回一个字符串,例如:

public class GenDetached {
    public static String generate() throws Exception {
        // code not shown
    }
}

第二步 - 将签名数据添加到您的目标XML文档中。

假设我们有以下目标文档。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <data>all your data in here...</data>
</root>

下面的代码提取了 <Signature> 节点,并将其添加为签名XML的子节点。<root> 节点。

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.InputSource;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.StringReader;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;

...

String signatureXml = GenDetached.generate();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// My test document to hold the data and the signature:
String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><root><data>foo</data></root>";

Document doc = db.parse(new InputSource(new StringReader(xmlString)));
Node docRootNode = doc.getFirstChild();

Document sig = db.parse(new InputSource(new StringReader(signatureXml)));
NodeList sigNodeList = sig.getElementsByTagName("Signature");
Node sigNode = sigNodeList.item(0);

// First import the signature node into the main document:
Node docImportedNode = doc.importNode(sigNode, true);
// Then add the signature node to the main document's root:
docRootNode.appendChild(docImportedNode);

// Show the output (as a String in this case, for the demo):
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
trans.transform(new DOMSource(doc), new StreamResult(writer));
System.out.println(writer.toString());

结果是这样的(细节省略)。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <data>foo</data>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            ...
        </SignedInfo>
        <SignatureValue>...</SignatureValue>
        <KeyInfo>
            <KeyValue>
                <DSAKeyValue>
                    ...
                </DSAKeyValue>
            </KeyValue>
        </KeyInfo>
    </Signature>
</root>

希望能帮到你

关于问题中的 "内部分离 "术语的小观点(由 维基百科):

用于在其所含的XML文档之外签署资源的XML签名称为 附签如果它被用于签署其包含文件的某些部分,则称为 签名信.

我假设这个例子是后者。

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