0

描述

我们正在尝试与要求我们签署我们发送的 XML 的服务提供商建立通信。这是在使用 Java 1.6 的 Lotus Domino 平台上完成的。问题在于,使用 Domino JRE 运行代码时生成的签名与使用常规 JRE 在例如 Eclipse 中运行代码时生成的签名不同。在 Domino 中运行时,它会在接收端触发验证错误。因此,在 Eclipse 中使用相同的代码并仅针对 IBM JRE 会导致此错误。这很清楚地表明,Domino JRE 中有一些东西导致了这个问题,我们只是不知道是什么或如何找到它的底部。任何想法什么设置可能是造成这种差异的原因?

为澄清起见,请注意我们对所有测试使用相同的内容,并且在 Eclipse 中运行 i 两次会产生完全相同的结果。

错误信息

返回的错误只是说签名无效:2013-08-05 16:38:18 Agent Manager: Agent error: ESignClientException: ESigningFacade.getOrder failed。原因:(RMS 返回错误响应。TransId [-1971835324952692066] RMS ErrorCode [RMS1002] ErrorText [SignatureVerification failed. The Signature is not valid.])

代码

我们正在使用服务提供者 API,但这里有一个我们正在运行的代码的简短示例:

public void test() {
    try {
        String xmlrequest = "SOME XML"
        String keyStorePath = "keystore.p12";
        char[] pwdChars = "********".toCharArray();
        PrivateKey privateKey = null;
        String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());
        KeyInfoFactory kif = fac.getKeyInfoFactory();

        KeyStore store = KeyStore.getInstance("PKCS12");
        store.load(new FileInputStream(keyStorePath), pwdChars);

        Enumeration ksAliases = store.aliases();
        String keyAlias = null;
        while (ksAliases.hasMoreElements()) {
            String currAlias = (String) ksAliases.nextElement();
            if (store.isKeyEntry(currAlias)) {
                keyAlias = currAlias;
                privateKey = ((PrivateKey) store.getKey(currAlias, pwdChars));
                break;
            }
        }

        Certificate certificate = store.getCertificate(keyAlias);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(new   ByteArrayInputStream(certificate.getEncoded()));
        X509Data x5 = kif.newX509Data(Collections.nCopies(1, cert));
        KeyInfo ki = kif.newKeyInfo(Collections.nCopies(1, x5));
        Reference ref = fac.newReference("#object", fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        dbf.setValidating(false);
        dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new InputSource(new StringReader(xmlrequest)));
        XMLStructure content = new DOMStructure(doc.getFirstChild());

        XMLObject obj = fac.newXMLObject(Collections.nCopies(1, content), "object", null, null);
        SignedInfo si =    fac.newSignedInfo(fac.newCanonicalizationMethod("http://www.w3.org/2001/10/xml-exc-c14n#", (C14NMethodParameterSpec) null),                fac.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#rsa-sha1", null),       Collections.nCopies(1, ref));
        XMLSignature signature = fac.newXMLSignature(si, ki, Collections.nCopies(1, obj), null, null);
        DOMSignContext dsc = new DOMSignContext(privateKey, doc);
        signature.sign(dsc);

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));
        os.flush();
        String res = new String(os.toByteArray(), "UTF-8");
        os.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}
4

1 回答 1

0

好的,经过大量试验和错误,我设法自己解决了这个问题。由于提供程序“org.jcp.xml.dsig.internal.dom.XMLDSigRI”未包含在 IBM JRE 中,因此它也未添加到 java.security 文件 (jvm/lib/security/java.security) 中。所以我在 java.security 文件中为新的提供者添加了一行,然后它就起作用了。或者我是这么想的。它只适用于我在 Eclipse 中使用 IBM JRE 的测试项目。当我在服务器上尝试相同的修复时,它根本没有任何影响。当我像以前一样将提供程序添加到 java.security 文件时,提供程序列表没有改变。因此,经过更多测试后,我发现当我将提供程序 JAR (xmlsec-1.4.2.jar) 添加到文件夹“jvm/lib/ext/”时,提供程序已注册。这就是我让它工作的方式。

于 2013-08-14T11:48:17.733 回答