首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Xades4j验证签名Xades :错误的XML签名

Xades4j验证签名Xades :错误的XML签名
EN

Stack Overflow用户
提问于 2017-12-01 02:10:15
回答 1查看 2.5K关注 0票数 1

我正在使用Xades4J开发一个简单的Java程序,该程序使用XADES签名和验证XML。签名过程似乎工作正常,并生成一个有效的签名XML (尽管我们不需要它上的SignaturePolicyIdentifier部分)。

*选项参数是从joptsimple到解析参数的

这是我的符号功能:

void signXML(OptionSet选项){

代码语言:javascript
复制
KeyingDataProvider kp;
代码语言:javascript
复制
try {
代码语言:javascript
复制
    SignaturePolicyInfoProvider policyInfoProvider = new SignaturePolicyInfoProvider() {
代码语言:javascript
复制
        public SignaturePolicyBase getSignaturePolicy() {
代码语言:javascript
复制
            return new SignaturePolicyIdentifierProperty(
代码语言:javascript
复制
                    new ObjectIdentifier("oid:/1.2.4.0.9.4.5", IdentifierType.OIDAsURI, "Policy description"),
代码语言:javascript
复制
                    new ByteArrayInputStream("Test policy input stream".getBytes()))
代码语言:javascript
复制
                            .withLocationUrl("http://www.example.com/policy");
代码语言:javascript
复制
        }
代码语言:javascript
复制
    };
代码语言:javascript
复制
    kp = new FileSystemKeyStoreKeyingDataProvider("pkcs12", options.valueOf("certificate").toString(),
代码语言:javascript
复制
            new FirstCertificateSelector(), new DirectPasswordProvider(options.valueOf("password").toString()),
代码语言:javascript
复制
            new DirectPasswordProvider(options.valueOf("password").toString()), false);
代码语言:javascript
复制
    // SignaturePolicyInfoProvider spi = new
代码语言:javascript
复制
    XadesSigningProfile p = new XadesEpesSigningProfile(kp, policyInfoProvider);
代码语言:javascript
复制
    p.withBasicSignatureOptionsProvider(new SignatureOptionsProvider());
代码语言:javascript
复制
    XadesSigner signer = p.newSigner();
代码语言:javascript
复制
    // open file
代码语言:javascript
复制
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
代码语言:javascript
复制
    factory.setNamespaceAware(true);
代码语言:javascript
复制
    DocumentBuilder builder = null;
代码语言:javascript
复制
    builder = factory.newDocumentBuilder();
代码语言:javascript
复制
    Document doc1 = builder.parse(new File(options.valueOf("input").toString()));
代码语言:javascript
复制
    Element elemToSign = doc1.getDocumentElement();
代码语言:javascript
复制
    // sign whole document
代码语言:javascript
复制
    new Enveloped(signer).sign(elemToSign);
代码语言:javascript
复制
    // save output file
代码语言:javascript
复制
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
代码语言:javascript
复制
    Result output = new StreamResult(new File(options.valueOf("output").toString()));
代码语言:javascript
复制
    Source input = new DOMSource(doc1);
代码语言:javascript
复制
    transformer.transform(input, output);
代码语言:javascript
复制
} catch (KeyStoreException | ParserConfigurationException | SAXException | IOException | XAdES4jException
代码语言:javascript
复制
        | TransformerException e) {
代码语言:javascript
复制
    e.printStackTrace();
代码语言:javascript
复制
}

}

代码语言:javascript
复制
This is a sample signature that it creates: (Is it normal to have 

在base64值的每一行末尾?)

代码语言:javascript
复制
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686-ref0" URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>h20v8PSCwU5ymBKMj5o8scN3FyMfGCmN8OA2bnRHTnI=</ds:DigestValue>
</ds:Reference>
<ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-f5700b65-334e-4905-96f6-ca6156139686-signedprops">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>tEyMfk39qnevJRyLbxQJIGpEBJuCcYRSZNNjm7HfaaA=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686-sigvalue">
ZhdQPEz7KwYoLTc72rxqUN2rlMfRGmqHd0MVSEeHRf/kmoqAGAqit5tw6k9k8oFCyuPDS/+DoXHJ&#13;
rooMDEMr+cuvbwwDwy77kHT+8JeUuIAamyqP/OByLytxXm/oKHVAraMhHNsGHvhcsYzULHl+n6JB&#13;
fhsYeR6rZdksS+QkgeUYohEktodl20/kyug4ymZjbJ7rCtH6+nRRR1nqc8oVT2ZpgfEaPHqWO06V&#13;
QURYYkuQEPOsNgFUu+YiWAX9pz94tlsOlLu6efBUP4lDZbCSq75J7nVZonmTbj/+mPl/oxpLCAgG&#13;
utWpL1RwyWn454G+Rd/AG3+MLWnbPVVSWUTcNK2gv4S2MVmosGxBnKwA71Zu30S+KaDwoktzZ62X&#13;
ViDLMmf6YbTKhiCIZYdjXPXr9QwSOHr+2B5GNUwo/CoOENJY/sXNHiHXxw+d+cyoowN4faJoVb5C&#13;
YFT7DACHyRd/d6TGdVEviHToTak+xPIK0HGnLvmkqzpICX8SFuMybur5Tttex4hqJNmXI7XbI9pk&#13;
YGLESBvKmzp4O9wLTJdABsLLxZSwU1plagu+5nb8ujIzmngVEHx4yBRprRVr3cBrHKoQBOHAiaGQ&#13;
96qUVTFogIX3vxN/1Q8xKDfB99FlzDdqnc2SW5lgYHnkuHHStJhoaCKRraUWVtU1miT/gMES+YM=
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIFgTCCA2mgAwIBAgIJAPzDOBvbJQYvMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkFVMRMw&#13;
EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEDAO&#13;
BgNVBAMMB1Fwcm90ZXgwHhcNMTcxMTI5MDIwMjIyWhcNMTgxMTI5MDIwMjIyWjBXMQswCQYDVQQG&#13;
EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg&#13;
THRkMRAwDgYDVQQDDAdRcHJvdGV4MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt1+k&#13;
sAGGc1kvhs3AjTfIyBRRBb3sB5C+IlGplS1lOpViUsYOZKT/t0u1PWTxWnTNYpEChSg4ECnbaNje&#13;
nuyIQct5AS+MMMD2R8SSGGfvlhwr/yypEzcIfsOjFMhnV95Kto0abqLDucOyZotZfbaQQcwK7ATI&#13;
/TrumoUX6lRaryeIYBhENRCvmTjcR3ecinL+FSEpEOdXSh0jtHRtoV/HCzHdgNvXXLPD2YkyjY/0&#13;
D9rvHmVmKXtRfnLsiNcc2vMuE0XlfBz/WbP+lOpMKpka5F7ocnDeMJ2Tb24tL60M+DS7IYWOJ4wm&#13;
Vpb9FsBI3mDZ1AndsTIp5lljLIT7CVvgIvIbCxlOx6vcRxjOhpzNLmCJuMuI2dLtg5qn6q4QoLrE&#13;
6LAQZ8Zt9ljK2s33Vc84FZi+nZx6A1enTnLyHjds6BdrzvKLOJeUtLlTbufxNrkQzWSIhI2ZbfhY&#13;
Mn4yC1REj4kH30AKD6YkN028TasJDnv30g9n9eSbZ0fq2buT2DawGAA9GP02daaaOyTmBVJMonpi&#13;
xSD7lN7iR3zvDUxtjIoOi15XZw+2k28VqkwVdOwo3xkz5zVhSxm7Xv1NHdiUO2AUzvWMdBNMTS2t&#13;
0rr31B232UQvuqDHW1ws6em1iA+Lu1X3Z59Mer6Hg2mVclNKSBrYxUSwSv9poZqxXlGH6R0CAwEA&#13;
AaNQME4wHQYDVR0OBBYEFNG3ss8QEfGFgyxHpb54iRRNz9BDMB8GA1UdIwQYMBaAFNG3ss8QEfGF&#13;
gyxHpb54iRRNz9BDMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBACuhTI0prkRc15OI&#13;
HGQq+xhHRfbnG3dUEaXuAYhyDbrRXz2urEjIf2vGPIn7hheOrScSbQgblHq/tV1nQTyRsyHCvZlV&#13;
aE2+OWCfrQDdrwZKE2N2xC1ALgGTtF+I4lXgy6/9OzNVFnV0oZUnO6PN5cH6SVy+RHpO9Lsr5ndI&#13;
YBSuu0Zd7/IsOYY/vWcfJjq3+SnRotgGj0Jf4F7SH74XPz0QkoVKM1z3zGlbF/w8OzJw71yRVkaX&#13;
Ld+TDFC6jDFV+kjQ1k8pa4Hjs2Yko2AmNmpOZmMVjRLTdGLdSU/Gt1ewDp5TsEa2y/5u2PcZY/fd&#13;
dNaMyH7Qx0SmqvYvgG0C3mSGhhFv6++SaXXmo1lQCDgY9OK975KnQPSIHXeuK7oh/82a2ZhmQau0&#13;
B/ISxrjtRJbSHByLefJAkJpRVGowa14Nq/jI/Dvl46LVepTq2eNxbbMmbaW60HMwDS+YfNIwRpRS&#13;
n/W1/7mWLQRRP0Mb1/fjZlIZBV83fynZU5BSsoW+LZ8EWXt+VhtC8SWZ3m3ffk3KKqZDKJTih5c1&#13;
IFz2veIrHZH6O9n3taU+mVuNC8piuG+GBCBPo7dQwFmGo2zZ9BvSqUdytLniuej1PcPBTkcxfhCN&#13;
h5lKWwZCNE5v8RlEd9RbjEC5nAm8kCVvHX5SZivd77Yum8eBMAUQ++M2oNfz
</ds:X509Certificate>
<ds:X509SubjectName>CN=Qprotex,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU</ds:X509SubjectName>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=Qprotex,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU</ds:X509IssuerName>
<ds:X509SerialNumber>18213463010308326959</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>
t1+ksAGGc1kvhs3AjTfIyBRRBb3sB5C+IlGplS1lOpViUsYOZKT/t0u1PWTxWnTNYpEChSg4ECnb&#13;
aNjenuyIQct5AS+MMMD2R8SSGGfvlhwr/yypEzcIfsOjFMhnV95Kto0abqLDucOyZotZfbaQQcwK&#13;
7ATI/TrumoUX6lRaryeIYBhENRCvmTjcR3ecinL+FSEpEOdXSh0jtHRtoV/HCzHdgNvXXLPD2Yky&#13;
jY/0D9rvHmVmKXtRfnLsiNcc2vMuE0XlfBz/WbP+lOpMKpka5F7ocnDeMJ2Tb24tL60M+DS7IYWO&#13;
J4wmVpb9FsBI3mDZ1AndsTIp5lljLIT7CVvgIvIbCxlOx6vcRxjOhpzNLmCJuMuI2dLtg5qn6q4Q&#13;
oLrE6LAQZ8Zt9ljK2s33Vc84FZi+nZx6A1enTnLyHjds6BdrzvKLOJeUtLlTbufxNrkQzWSIhI2Z&#13;
bfhYMn4yC1REj4kH30AKD6YkN028TasJDnv30g9n9eSbZ0fq2buT2DawGAA9GP02daaaOyTmBVJM&#13;
onpixSD7lN7iR3zvDUxtjIoOi15XZw+2k28VqkwVdOwo3xkz5zVhSxm7Xv1NHdiUO2AUzvWMdBNM&#13;
TS2t0rr31B232UQvuqDHW1ws6em1iA+Lu1X3Z59Mer6Hg2mVclNKSBrYxUSwSv9poZqxXlGH6R0=
</ds:Modulus>
<ds:Exponent>AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
<ds:Object><xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#" Target="#xmldsig-f5700b65-334e-4905-96f6-ca6156139686"><xades:SignedProperties Id="xmldsig-f5700b65-334e-4905-96f6-ca6156139686-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>2017-11-30T20:58:18.009-05:00</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>JkEubWWYvvoh7kOnuAvYeXE4cFamHJ5FOBYt3b3dCj4=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>CN=Qprotex,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU</ds:X509IssuerName><ds:X509SerialNumber>18213463010308326959</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyId><xades:SigPolicyId><xades:Identifier Qualifier="OIDAsURI">oid:/1.2.4.0.9.4.5</xades:Identifier><xades:Description>Policy description</xades:Description></xades:SigPolicyId><xades:SigPolicyHash><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>MaW9PDxJruPHhjBVAMWyrF9zP+kMnNqkoQOUXxDDGAk=</ds:DigestValue></xades:SigPolicyHash><xades:SigPolicyQualifiers><xades:SigPolicyQualifier><xades:SPURI>http://www.example.com/policy</xades:SPURI></xades:SigPolicyQualifier></xades:SigPolicyQualifiers></xades:SignaturePolicyId></xades:SignaturePolicyIdentifier></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object>
</ds:Signature>

这是我打印不良XML签名的验证代码。

代码语言:javascript
复制
void verifyXML(OptionSet options) {
    try {
        File file = new File(options.valueOf("certificate").toString());
        FileSystemDirectoryCertStore store = new FileSystemDirectoryCertStore(file.getAbsoluteFile().getParent());
        FileInputStream fis = new FileInputStream(options.valueOf("certificate").toString());
        KeyStore ks = KeyStore.getInstance("pkcs12");
        ks.load(fis, options.valueOf("password").toString().toCharArray());                         
        fis.close();            
        CertificateValidationProvider provider = new PKIXCertificateValidationProvider(ks, false, store.getStore());

        XadesVerifier verifier = new XadesVerificationProfile(provider).newVerifier();

        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(options.valueOf("input").toString()));

        doc.getDocumentElement().normalize();

        Element sig = (Element)doc.getElementsByTagName("ds:Signature").item(0);
        PrintWriter out = null;
        try {
            out = new PrintWriter(options.valueOf("output").toString());
            XAdESVerificationResult result = verifier.verify(sig, null);
            out.println("true");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            out.println("false");
        }
        out.close();


    } catch (Exception ex) {
        System.err.println("Error: " + ex.getMessage());
    }

如果有人能告诉我问题可能在哪里,我将不胜感激。谢谢!

UPDATE在我检查堆栈跟踪之后发现了以下异常:

代码语言:javascript
复制
    xades4j.xml.unmarshalling.UnmarshalException: Bad XML signature
    at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:130)
    at com.qprotex.Main.verifyXML(Main.java:190)
    at com.qprotex.Main.<init>(Main.java:99)
    at com.qprotex.Main.main(Main.java:81)
Caused by: org.apache.xml.security.exceptions.XMLSecurityException: Cannot create a null:null from a http://www.w3.org/2000/09/xmldsig#:Signature element

我找到了提到相同错误的这个职位,在验证方法中启用factory.setNamespaceAware(true)之后,我得到以下异常:

代码语言:javascript
复制
java.lang.NullPointerException
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.getLocationUrl(FromXmlSignaturePolicyConverter.java:71)
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:64)
at xades4j.xml.unmarshalling.FromXmlSignaturePolicyConverter.convertFromObjectTree(FromXmlSignaturePolicyConverter.java:1)
at xades4j.xml.unmarshalling.UnmarshallerModule.convertProperties(UnmarshallerModule.java:64)
at xades4j.xml.unmarshalling.DefaultQualifyingPropertiesUnmarshaller.unmarshalProperties(DefaultQualifyingPropertiesUnmarshaller.java:83)
at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:175)
at com.qprotex.Main.verifyXML(Main.java:190)
at com.qprotex.Main.<init>(Main.java:99)
at com.qprotex.Main.main(Main.java:81)

UPDATE 2,因为我没有使用SignaturePolicyIdentifier,所以我更改了符号函数,改为使用XadesBesSigningProfile而不是XadesEpesSigningProfile。我现在唯一的问题是,只有当我使用KeyStore.getInstance(“Windows”)时,它才能工作。

这样做是可行的:

代码语言:javascript
复制
            KeyStore trustAnchors = KeyStore.getInstance("Windows-ROOT"); 
            trustAnchors.load(null);

            CertificateValidationProvider provider = new PKIXCertificateValidationProvider(trustAnchors, false);

但是这不起作用,我得到了一个"xades4j.providers.CannotBuildCertificationPathException:信任锚,KeyStore没有可信的证书条目“异常”。

代码语言:javascript
复制
            FileInputStream fis = new FileInputStream(options.valueOf("certificate").toString());
            KeyStore ks = KeyStore.getInstance("pkcs12");
            ks.load(fis, options.valueOf("password").toString().toCharArray());                         
            fis.close();
            CertificateValidationProvider provider = new PKIXCertificateValidationProvider(ks, false);
EN

回答 1

Stack Overflow用户

发布于 2017-12-03 12:36:08

  • 你可能在图书馆里发现了一个bug。我创建了关于吉突布的问题来跟踪它。如果你愿意的话就订阅吧。
  • 如果它确实是一个bug,那么它肯定是在v1.4.0中引入的,所以现在,您可以尝试使用v1.3.2。
  • 既然你说你不需要SignaturePolicyIdentifier,你为什么要使用XAdES?您可以使用XadesBesSigningProfile代替,并生成XAdES-BES签名。
  • 假设您仍然需要XAdES-EPES,请注意,您需要指定如何获取签名策略文档,以便使用withPolicyDocumentProviderXadesVerificationProfile上进行验证。
  • 我不确定base64字符串之后的编码字符,但是让我们等待看看这是否是一个问题。

更新后2:

异常信息似乎很清楚。您的目标也是使用签名证书作为信任锚?keystore上条目的类型需要是“信任锚”。我想您应该添加两个条目:一个带有cert/key (键入“证书”),另一个只有证书(键入“信任锚”)。或者使用单独的密钥存储库。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47585633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档