2

我正在使用智能卡进行签名以及 SunMSCAPI 提供程序和 Windows 密钥存储。使用 xades4j 1.3.2 版本我正在唱一个 xml 文件,如下所示,它运行良好,证书也嵌入在 KeyInfo 的 xml 文件中,

private Document signXMLData(Document doc) {
        try {
            XadesSigningProfile p;
            p = new XadesBesSigningProfile(keyingDataProvider).withSignaturePropertiesProvider(new SignaturePropertiesProvider() {
                @Override
                public void provideProperties(SignaturePropertiesCollector signedPropsCol) {
                    signedPropsCol.setSignerRole(new SignerRoleProperty(SignerRole));
                    signedPropsCol.setSignatureProductionPlace(new SignatureProductionPlaceProperty(City, State, PostalCode, Country));
                    signedPropsCol.setSigningTime(new SigningTimeProperty());
                }
            });
            XadesSigner signer = p.newSigner();
            Element elemToSign = doc.getDocumentElement();
            new Enveloped(signer).sign(elemToSign);
            Log.LogOperation("XML signing completed successfully.");
        } catch (Exception ex) {
            Log.LogException(ex);
            doc = null;
        }
        return doc;
    }

但我的问题是,在使用以下代码进行验证时,出现以下错误,

代码

public boolean VerifyXMLSign(String data) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException, Exception {
        InputSource isIn = new InputSource();
        isIn.setCharacterStream(new StringReader(data));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(isIn);
        //Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("c:/xml.xml"));
        DOMHelper.useIdAsXmlId(doc.getDocumentElement());

        KeyStore ks = KeyStore.getInstance("Windows-ROOT", "SunMSCAPI");
        ks.load(null, null);

        X509Certificate x509Certificate = null;
        PublicKey key = null;
        DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(ks), getSigElement(doc));
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
        fac.newDigestMethod(DigestMethod.SHA256, null);
        XMLSignature signature = fac.unmarshalXMLSignature(valContext);
        KeyInfo keyInfo = signature.getKeyInfo();
        Iterator hKeyInfo = keyInfo.getContent().iterator();
        while (hKeyInfo.hasNext()) {
            XMLStructure hX509Data = (XMLStructure) hKeyInfo.next();
            if (!(hX509Data instanceof X509Data)) {
                continue;
            }
            X509Data x509Data = (X509Data) hX509Data;
            Iterator hX509Certificate = x509Data.getContent().iterator();
            while (hX509Certificate.hasNext()) {
                Object oX509Certificate = hX509Certificate.next();
                if (!(oX509Certificate instanceof X509Certificate)) {
                    continue;
                }
                x509Certificate = ((X509Certificate) oX509Certificate);
                key = x509Certificate.getPublicKey();
            }
        }

        //FileSystemDirectoryCertStore certStore = createDirectoryCertStore("my");
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        ks.setCertificateEntry("df", x509Certificate);

        CertificateValidationProvider validationProviderMySigs = new PKIXCertificateValidationProvider(ks, false, null);//certStore.getStore());
        XadesVerificationProfile instance = new XadesVerificationProfile(validationProviderMySigs);
        XadesVerifier verifier = instance.newVerifier();
        XAdESVerificationResult r = verifier.verify(getSigElement(doc), null);

        System.out.println(r.getSignatureForm());
        System.out.println(r.getSignatureAlgorithmUri());
        System.out.println(r.getSignedDataObjects().size());
        System.out.println(r.getQualifyingProperties().all().size());
        return false;
    }

错误

Log Date Time:- 2017/06/08 14:38:01
xades4j.utils.XadesProfileResolutionException: com.google.inject.internal.ComputationException: java.lang.SecurityException: class "org.bouncycastle.cms.jcajce.JcaX509CertSelectorConverter"'s signer information does not match signer information of other classes in the same package
    at xades4j.utils.XadesProfileCore.getInstance(XadesProfileCore.java:223)
    at xades4j.verification.XadesVerificationProfile.newVerifier(XadesVerificationProfile.java:147)
    at slr.DigitalVerification.VerifyXMLSign(DigitalVerification.java:163)
    at slr.Handlers$OpenEVerifierHandler.handle(Handlers.java:186)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
    at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:83)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:80)
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:677)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:77)
    at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:647)
    at sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:158)
    at sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:433)
    at sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:398)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.google.inject.internal.ComputationException: ..........

我尝试了https://github.com/luisgoncalves/xades4j/issues/37中建议的方法,但这也给出了同样的错误。

请建议我做错了什么。

4

1 回答 1

3

从错误看来,这似乎与混合安全提供程序有关,可能是因为您KeyStore从“SunMSCAPI”创建了,然后X509Certificate由 XML 签名上使用的提供程序创建,这似乎是充气城堡。

无论如何,由于签名证书包含在签名中,您不需要解析 XML 并查找它xades4j的目的是将您从这些东西中抽象出来。xades4j将收集所有证书KeyInfo并在验证签名证书时使用它们来构建一个链(在这种情况下可能只有一个)。

如果验证您的歌唱证书所需的所有中间证书和根证书都在Windows-ROOT或 内KeyInfo,您只需创建受信任的根KeyStore并将其按PKIXCertificateValidationProvider原样传递。如果需要包含额外的证书,可以使用构造函数的CertStore参数PKIXCertificateValidationProvider

因此,总而言之,您应该需要的所有代码都是第一部分和最后一部分。就像是:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().parse(isIn);
DOMHelper.useIdAsXmlId(doc.getDocumentElement());

KeyStore ks = KeyStore.getInstance("Windows-ROOT", "SunMSCAPI");
ks.load(null, null);
CertificateValidationProvider validationProviderMySigs = new PKIXCertificateValidationProvider(ks, false, null);
XadesVerificationProfile instance = new XadesVerificationProfile(validationProviderMySigs);
XadesVerifier verifier = instance.newVerifier();
XAdESVerificationResult r = verifier.verify(getSigElement(doc), null);
于 2017-06-08T10:24:17.020 回答