当前位置: 首页 > 面试题库 >

Java XML DSig和XPath

宗政斌
2023-03-14
问题内容

我正在使用Java XML DSig API签名XML文档的一部分。我试图了解它是如何达到Digest值的。

我的文件是:

<?xml version=\"1.0\" encoding=\"UTF-8\"?><PurchaseOrder><foo>bar</foo></PurchaseOrder>

我的xpathhtml" target="_blank">表达式是:

PurchaseOrder/foo/text()

我试图做的是:

  1. 调用Java DSIG库并查看生成的摘要的值。
  2. 使用MessageDigest(SHA-1)类可消化值“ bar”。
  3. 验证1和2中的摘要是否匹配。

当我这样做时,1和2会产生不同的摘要值。我对DSIG代码的处理完全不对,或者我不了解DSIG的工作方式。有任何想法吗?

这是我的测试代码(抱歉,它太长了……我应该回到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);
    }
}

问题答案:

以下示例位于:http
:
//markmail.org/message/tdgioazns7l4yg6d#query
:
java%20xpath%20xml%20dsig%20bug+page
:1+
mid
:
tgw5kr7uscwkcran+state
:
results,我发现需要将更XPathType.Filter.UNION改为XPathType.FILTER.INTERSECT。那似乎解决了我的问题。XML
DSig库现在使用了我期望的正确值。




 类似资料:
  • 问题内容: 我想使用API使用XPATH在父节点内定位一个节点。我以为这会让我回到父母那边。但是,它将返回我在整个DOM树中找到的第一个。我使用了错误的XPATH吗? 我也曾尝试使用XPATH,但这确实会返回任何东西。 谢谢。 更新: 给定下面的HTML,我想为子标题和子日期定义一个定位器,并使用WebElement.findElement()API对其进行定位,而不管父级是“ // a / li

  • 这个问题给出了正确的节点,但是所有的节点都同时给出了。 还有当时,它什么也不返回?

  • 问题内容: 关于它们有很多传说。我想知道真相。以下两个示例之间有什么区别? 问题答案: 不确定从何处获得传说,但: 提交按钮 与: IE6将在标记之间提交此按钮的所有文本,其他浏览器将仅提交值。使用可使您在按钮的设计上享有更大的布局自由度。从各种意图和目的看,它乍一看似乎很棒,但是各种浏览器怪癖使它有时很难使用。 在您的示例中,IE6将发送到服务器,而其他大多数浏览器将不发送任何内容。要使其跨浏览

  • 什么区别以及如何正确重写代码?

  • 我试图理解为什么下面两个代码块会产生不同的结果。 代码块1按预期工作,并返回从数据库中查找的提供程序的数组。另一方面,代码块2返回函数数组。在理解promissione.all()和async/await时,我觉得缺少了一些简单的东西。 代码块的差异如下: > 块1:创建许诺函数数组,然后使用map运算符将其包装在异步函数中。 块2:许诺函数的数组被创建为异步函数。因此,不调用map运算符。 如果

  • 问题内容: 我才刚刚开始研究SQL。 我有一个SQL Server 2008r2数据库,它将返回两个字段DocDate和InvValue。我需要将InvValues汇总为今天的MTD和YTD,所以看起来像 我已经做了大量的Google搜寻,并且可以使用SUM&DATEPART进行一项或多项,但是我坚持尝试两者兼而有之。 有人可以给我一些伪代码,以帮助我进一步谷歌。 谢谢@戈登·利诺夫(Gordon