【发布时间】:2015-01-13 04:05:39
【问题描述】:
我需要对 XML 文档进行数字签名。给出的要求是输入是一个 XML 文件和一个私钥。签名应该使用 SHA256/RSA-2048,并且签名应该是 Enveloping。我想出了以下方法来做到这一点。在测试中,使用 KeyPairGenerator 类生成 KeyPair,其中 RSA 作为算法,密钥大小设置为 2048。传递的输入流是 FileInputStream 对象,输出流是 FileOutputStream 对象。该方法似乎工作正常。
public void sign(InputStream inputStream, OutputStream outputStream, KeyPair kp) throws Exception {
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
Reference ref = fac.newReference("#object", fac.newDigestMethod(DigestMethod.SHA256, null));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
org.w3c.dom.Document doc = dbf.newDocumentBuilder().parse(inputStream);
XMLStructure content = new DOMStructure(doc.getDocumentElement());
XMLObject obj = fac.newXMLObject(Collections.singletonList(content), "object", null, null);
SignatureMethod signatureMethod = fac.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null);
CanonicalizationMethod canonicalizationMethod = fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null);
SignedInfo si = fac.newSignedInfo(canonicalizationMethod, signatureMethod, Collections.singletonList(ref));
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(kp.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
XMLSignature signature = fac.newXMLSignature(si, ki, Collections.singletonList(obj), null, null);
DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), doc);
signature.sign(dsc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(outputStream));
}
我有一些问题:
我没有在代码中指定应该在签名中使用 RSA,那么它是如何知道的呢?另外,我知道在加密中,还有模式和填充。同样,这些也没有指定,那么它们是什么?
我真的不知道 XML 的规范化是如何工作的。 CanonicalizationMethod.INCLUSIVE 和 CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS 都产生相同的输出(都具有相同的 DigestValue 值)。这些不同的方法是什么意思?
对象标签中的封装消息似乎与输入的 XML 文件内容完全相同。封装的消息应该与原始 XML 相同还是应该是规范化的版本?我知道摘要中使用了规范化版本,但不确定是否应该规范化封装版本。我的原始 XML 有 cmets 标签,但无论我输入 INCLUSIVE 还是 INCLUSIVE_WITH_COMMENTS,cmets 标签都会出现在输出中。
是否需要公钥?给我的要求是私钥是一个输入,但我不确定我是否也应该询问公钥。 KeyValue 对象似乎需要公钥。
提前致谢。
【问题讨论】:
标签: java encryption key digital-signature xml-signature