问题描述
我正在使用Java XML DSig api签署XML文档的一部分。我试图了解它是如何达到摘要值的。
I'm signing part of an XML document using the Java XML DSig api. I'm trying to understand how it is arriving at the Digest value.
我的文件是:
<?xml version=\"1.0\" encoding=\"UTF-8\"?><PurchaseOrder><foo>bar</foo></PurchaseOrder>
我的xpath表达式为:
My xpath expression is:
PurchaseOrder/foo/text()
我尝试做的是:
- 调用Java DSIG库并查看生成的摘要的值。
- 使用MessageDigest(SHA-1)类,用于消化值bar。
- 验证1和2的摘要是否匹配。
当我这样做时,1和2产生不同的摘要值。要么我的DSIG代码完全出错了,要么我不明白DSIG是如何工作的。有什么好主意吗?
When I do this, 1 and 2 produce different digest values. Either I'm doing something totally wrong with my DSIG code, or I don't understand how DSIG works. Any ideas?
这是我的测试代码(对不起,这么久......我应该回到perl):
Here is my test code (sorry it is so long ... I should go back to perl):
public class GenerateXmlSignature2 {
private static final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><PurchaseOrder><foo>bar</foo></PurchaseOrder>";
private static final String xpath = "PurchaseOrder/foo/text()";
public static void main(String[] args) throws Exception {
Base64 base64 = new Base64();
// Create a DOM XMLSignatureFactory that will be used to
// generate the enveloped signature.
final XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
// Create a Reference to the enveloped document (in this case,
// you are signing the whole document, so a URI of "" signifies
// that, and also specify the SHA1 digest algorithm and
// the ENVELOPED Transform.
final List<XPathType> xpaths = new ArrayList<XPathType>() {
{
add(new XPathType(xpath, XPathType.Filter.UNION));
}
};
List<Transform> transforms = new ArrayList<Transform>() {{
add(fac.newTransform(
Transform.XPATH2,
new XPathFilter2ParameterSpec(xpaths)
)
);
}};
Reference ref = fac.newReference
("", fac.newDigestMethod(DigestMethod.SHA1, null),
transforms,
null, null);
// Create the SignedInfo.
SignedInfo si = fac.newSignedInfo
(fac.newCanonicalizationMethod
(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));
// Load the KeyStore and get the signing key and certificate.
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("mykeystore.jks"), "changeit".toCharArray());
KeyStore.PrivateKeyEntry keyEntry =
(KeyStore.PrivateKeyEntry) ks.getEntry
("mykey", new KeyStore.PasswordProtection("changeit".toCharArray()));
X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = fac.getKeyInfoFactory();
List x509Content = new ArrayList();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
// Instantiate the document to be signed.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse
(new ByteArrayInputStream(xml.getBytes()));
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element.
DOMSignContext dsc = new DOMSignContext
(keyEntry.getPrivateKey(), doc.getDocumentElement());
// Create the XMLSignature, but don't sign it yet.
XMLSignature signature = fac.newXMLSignature(si, ki);
// Marshal, generate, and sign the enveloped signature.
signature.sign(dsc);
// Output the resulting document.
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(System.out));
System.out.println("\n\n*** SHA-1 Digest ***");
XPathExpression xpathExpression = XPathFactory.newInstance().newXPath().compile(xpath);
String data = xpathExpression.evaluate(new InputSource(new StringReader(xml)));
System.out.println("Xpath: " + data);
MessageDigest md;
md = MessageDigest.getInstance("SHA");
byte[] sha1hash;
md.update(data.getBytes(), 0, data.length());
sha1hash = md.digest();
String base64Sha1OfCanonicalXml = new String(base64.encode(sha1hash));
System.out.println("Digest: " + base64Sha1OfCanonicalXml);
}
}
推荐答案
关注例如:,我发现我需要更改 XPathType.Filter.UNION
to XPathType.FILTER.INTERSECT
。这似乎解决了我的问题。 XML DSig库现在使用我期望的正确值。
Following an example at: http://markmail.org/message/tdgioazns7l4yg6d#query:java%20xpath%20xml%20dsig%20bug+page:1+mid:tgw5kr7uscwkcran+state:results, I found that I needed to change the XPathType.Filter.UNION
to XPathType.FILTER.INTERSECT
. That seems to have solved my problem. The XML DSig library is now using the correct value that I expected.
这篇关于Java XML DSig和XPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!